Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

419 lines
13 KiB

  1. /*++
  2. OPTIONS.HXX
  3. My option parsing system
  4. Copyright (C) 1997 Microsoft Corporation
  5. Created 01/13/1997 DavidCHR
  6. --*/
  7. #ifndef INCLUDED_OPTIONS_H
  8. /* IMPORTANT! IMPORTANT! IMPORTANT!
  9. If you add option types, you MUST change this #define to point at
  10. your new type. The symbol used internally for certain assertions and at
  11. compile-time to find forgotten areas.
  12. IMPORTANT! IMPORTANT! IMPORTANT! */
  13. #define HIGHEST_OPTION_SUPPORTED OPT_STOP_PARSING
  14. #define INCLUDED_OPTIONS_HXX
  15. #define OPTION_DEBUGGING_LEVEL 0x10000000 /* set your DebugFlag to this
  16. if you want OPTIONS_DEBUG */
  17. #define OPTION_HELP_DEBUGGING_LEVEL 0x20000000 /* most people REALLY will not
  18. want to see this. */
  19. typedef int (OPTFUNC)(int, char **); /* this is what's expected of OPT_FUNC*/
  20. // OPT_FUNC2 and beyond will be defined in client.h
  21. /* NOTE that when defining this structure statically, you MUST use
  22. curly braces ({}), since the structure may change in size! */
  23. typedef struct {
  24. PCHAR cmd; /* this is what we call from the command line eg "h"
  25. for -h or /h */
  26. PVOID data; /* this is where we store the results of that,
  27. OR a function
  28. that can be called to store it (see below), OR null if
  29. this option is ignored or doesn't need storage */
  30. ULONG flags; /* flags describing this option (see below for flags) */
  31. PCHAR helpMsg; /* description of this option (example: "prints help
  32. screen" or "specifies a file to read") */
  33. PVOID optData; /* if we specify OPT_ENVIRONMENT (for example),
  34. this is the environment variable we'll take the
  35. data from */
  36. /* any/all remaining fields should be left alone */
  37. BOOL Initialized; /* initially FALSE */
  38. } optionStruct;
  39. /* use this macro to determine if you're at the end of the array or not--
  40. it will change if the array termination conditions change. */
  41. #define ARRAY_TERMINATED( poptions ) ( ( (poptions)->cmd == NULL ) && \
  42. ( (poptions)->helpMsg == NULL ) && \
  43. ( (poptions)->data == NULL ) && \
  44. ( (poptions)->flags == 0 ) )
  45. /* put this as the last element of your array. It will change if/when
  46. the termination conditions change */
  47. #define TERMINATE_ARRAY { 0 }
  48. /* FLAGS
  49. these tell ParseOptions and PrintHelpMessage what the option is: */
  50. /* These are mutually-exclusive, so they are set in a manner such that
  51. defining them together causes wierd results. */
  52. #define OPT_HELP 0x01 /* print the help message */
  53. #define OPT_STRING 0x02 /* option is a string */
  54. #define OPT_INT 0x03 /* an integer (can be hex) */
  55. #define OPT_LONG 0x04 /* a long integer */
  56. #define OPT_BOOL 0x05 /* boolean */
  57. #define OPT_FLOAT 0x06 /* a float */
  58. #define OPT_FUNC 0x07 /* needs a function to parse and store */
  59. #define OPT_DUMMY 0x08 /* don't store the result anywhere-- basically,
  60. a separator that appears in the help message */
  61. #define OPT_CONTINUE 0x09 /* line is a continuation of the previous line--
  62. useful for breaking really long descriptions
  63. into multiple short lines */
  64. #define OPT_PAUSE 0x0A /* wait for the user to press RETURN */
  65. #ifdef WINNT /* only available under Windows NT */
  66. #define OPT_USTRING 0x0B /* UNICODE_STRING */
  67. #define OPT_WSTRING 0x0C /* string of wide characters */
  68. #ifdef UNICODE /* use OPT_TSTRING for TCHAR strings */
  69. #define OPT_TSTRING OPT_WSTRING
  70. #else
  71. #define OPT_TSTRING OPT_STRING
  72. #endif
  73. #endif /* WINNT-- OPT_{U|W}STRING */
  74. #define OPT_SUBOPTION 0x0D /* suboptions-- format is:
  75. [+|-|/](optname):(subopt),
  76. optname is the name of THIS OPTION (serves as
  77. a kind of "routing option". This gets converted
  78. to:
  79. [+|-|/](subopt)
  80. and is reparsed with the optionStruct that is
  81. given as data to this parameter within this
  82. structure. Nesting IS supported.
  83. Example follows. */
  84. #if 0 /* EXAMPLE of OPT_SUBOPTION */
  85. static optionStruct RoutedOptions[] = {
  86. /* note that each suboption must have its own OPT_HELP-- the help
  87. code will not browse the substructure. */
  88. { "help", NULL, OPT_HELP, NULL },
  89. { "myroute", &some_variable, OPT_BOOL, "set this to enable routing" },
  90. { "nofoo", &defeat_foo, OPT_BOOL, "down with foo!" },
  91. TERMINATE_ARRAY
  92. }
  93. static optionStruct myOptions[] = {
  94. { "help", NULL, OPT_HELP, NULL },
  95. { "route", RoutedOptions, OPT_SUBOPTION, "Routing options" },
  96. TERMINATE_ARRAY
  97. };
  98. /* in this example, to get help with the routing options, one would specify
  99. -route:help
  100. to enable routing, the user would do:
  101. +route:myroute */
  102. #endif
  103. #define OPT_ENUMERATED 0x0E /* Enumerated type. Depending on what the user
  104. enters for the field, we enter a user-defined
  105. value for the specified variable. We
  106. deliberately ignore the type of the values,
  107. the mapping-vector goes into the optData
  108. field, so we can't use OPT_ENVIRONMENT with
  109. this.
  110. and the array is currently terminated by
  111. a NULL UserField. Since this may change,
  112. use TERMINATE_ARRAY as above.
  113. the options are not case-sensitive, but
  114. if the user specifies an unknown value,
  115. an error will occur. */
  116. typedef struct {
  117. PCHAR UserField;
  118. PVOID VariableField;
  119. PCHAR DescriptionField; /* if the description is left blank, the field
  120. will not be mentioned in help */
  121. } optEnumStruct;
  122. #if 0 /* Example of OPT_ENUMERATED option */
  123. typedef enum {
  124. UseUdpToConnect = 1,
  125. UseTcpToConnect = 2,
  126. } MyEnumType;
  127. optEnumStruct MyEnumerations[] = {
  128. { "udp", (PVOID) UseUdpToConnect, // casting will likely be needed if
  129. "Specifies a UDP connection" },
  130. { "tcp", (PVOID) UseTcpToConnect, // your assignment is not a pointer
  131. "Specifies a TCP connection" },
  132. TERMINATE_ARRAY
  133. };
  134. MyEnumType MethodOfConnection;
  135. optionStruct MyOptions[] = {
  136. /* ... */
  137. { "MyEnum", OPT_ENUMERATED, &MethodOfConnection,
  138. "example of an enumerated type-- -myEnum Tcp for tcp connections",
  139. MyEnumerations },
  140. /* ... */
  141. };
  142. #endif
  143. #define OPT_FUNC2 0x0F /* enhanced function-- goes in the
  144. optData field, instead of the data field.
  145. See OPTFUNC2 above. */
  146. #define OPT_STOP_PARSING 0x10 /* tells the parser to stop here. This is
  147. the equivalent of the ';' argument to
  148. -exec in unix's find command:
  149. find . -exec echo {} ; -something.
  150. the ; terminates parsing for the -exec
  151. option. However, parsing for find is
  152. unaffected. */
  153. #define OPT_MUTEX_MASK 0xff /* mask for mutually exclusive options */
  154. #define OPT_NONNULL 0x100 /* option cannot be zero or NULL after parsing--
  155. not useful for BOOLs, DUMMYs, or HELP.
  156. This is a way of ensuring that an option DOES
  157. get specified. */
  158. #define OPT_DEFAULT 0x200 /* option may be specified without the cmd--
  159. multiple OPT_DEFAULTs may be specified. They
  160. get "filled in" in the order they exist in the
  161. options array. See the examples for more */
  162. #define OPT_HIDDEN 0x400 /* option does not appear in help. I'm not
  163. sure if this ends up being useful or not,
  164. but I'm including it for completeness. */
  165. #define OPT_ENVIRONMENT 0x800 /* use the optData field as an environment
  166. string from which to extract the default */
  167. #define OPT_RECURSE 0x1000 /* define this if you want FindUnusedOptions
  168. to reparse the given substructure.
  169. Otherwise, it'll be ignored */
  170. #define OPT_NOSWITCH 0x2000 /* do not print the leading [switches] line */
  171. #define OPT_NOCOMMAND 0x4000 /* do not print the command name--
  172. I don't know if you'd ever really want to do
  173. JUST this, but here it is.. */
  174. #define OPT_NOALIGN 0x8000 /* don't even print alignment spaces. This will
  175. make your output REALLY UGLY if you're not
  176. careful */
  177. #define OPT_NOSEPARATOR 0x10000 /* don't use a separator sequence (by
  178. default, I think it's ": ". Again, this
  179. is REALLY UGLY */
  180. // should have named the below option "OPT_RAW", because that's what it is.
  181. #define OPT_NOHEADER ( OPT_NOSWITCH | OPT_NOCOMMAND | OPT_NOALIGN | \
  182. OPT_NOSEPARATOR )
  183. #define OPT_ENUM_IS_MASK 0x20000 /* force enumerated types to also accept
  184. enums of the form XXX | YYY | ZZZ */
  185. #if 0 /* EXAMPLE */
  186. optionStruct my_options[] = {
  187. { "default1", &myDefaultInt, OPT_INT | OPT_DEFAULT, "an int value"},
  188. {"default2", &myOtherInteger, OPT_INT | OPT_DEFAULT, "another int" },
  189. {"required", &myRequiredString, OPT_STRING | OPT_NONNULL, "a must have" },
  190. TERMINATE_ARRAY
  191. };
  192. /*++
  193. in the example above, if your app was named "foo", the following would
  194. be equivalent:
  195. foo -default1 0 -default2 13 -required bleah
  196. foo 0 13 -required bleah
  197. foo 0 -default2 13 -required bleah
  198. foo -required bleah -default2 13 0
  199. ...and failing to specify "-required" would always result in an error
  200. if myRequiredString is NULL to begin with. Note that the options must
  201. be in order. If you mix types (if default2 were a string, and you run
  202. "foo bleah 0 for example"), the results are undefined.
  203. --*/
  204. #endif
  205. /* ParseOptionsEx:
  206. initializes the option structure, which is a sentinally-terminated
  207. vector of optionStructs.
  208. argc, argv: arguments to main() (see K&R)
  209. pOptionStructure: vector of optionStructs, terminated with TERMINATE_ARRAY
  210. optionFlags: optional flags to control api behavior
  211. ppReturnedMemory: returned handle to a list of memory to be freed before
  212. program exit. Use CleanupOptionDataEx to free it.
  213. new_arg[c,v]: if nonnull, a new argc and argv are returned here.
  214. if all the options were used up, argc = 0 and argv is
  215. NULL. Note that it is safe to provide pointers to the
  216. original argv/argc if so desired.
  217. The function's behavior is complex:
  218. the function will always return FALSE on any critical error (unable to
  219. allocate memory, or invalid argument). On WINNT, Last Error will be
  220. set to the appropriate error.
  221. if new_argc AND new_argv are specified,
  222. ParseOptionsEx will always return TRUE unless help was called, and
  223. the two parameters will be updated to reflect new values.
  224. otherwise:
  225. ParseOptionsEx will return TRUE if it was able to recognize ALL args
  226. on the command line given. It will return FALSE if any of the options
  227. were unknown. This will probably be what most people want.
  228. */
  229. BOOL
  230. ParseOptionsEx( int argc,
  231. char **argv,
  232. optionStruct *pOptionStructure,
  233. ULONG optionFlags,
  234. void **ppReturnedMemory,
  235. int *new_argc, // optional
  236. char ***new_argv ); // optional
  237. /* These are the flags that ParseOptionsEx accepts: */
  238. #define OPT_FLAG_TERMINATE 0x01 // call exit() on error
  239. // these next two are not yet fully supported and are mutually exclusive.
  240. #define OPT_FLAG_SKIP_UNKNOWNS 0x02 // skip unknown parameters
  241. #define OPT_FLAG_REASSEMBLE 0x04 /* assemble new argv/argc with
  242. unknown parameters in it-- only
  243. valid if new_argc and new_argv
  244. are specified
  245. this is useless with SKIP_UNKNOWNS. */
  246. #define OPT_FLAG_MEMORYLIST_OK 0x08 /* this means ParseOptionsEx should not
  247. return a new memory list-- it should
  248. use the provided one. */
  249. #define OPT_FLAG_INTERNAL_RESERVED 0xf0 /* flags 0x80, 0x40, 0x20 and 0x10
  250. are reserved for internal use */
  251. // if you add flags, update this #define.
  252. #define HIGHEST_OPT_FLAG OPT_FLAG_INTERNAL_RESERVED
  253. /* CleanupOptionDataEx:
  254. frees data in the given list, which may be empty ( but not NULL ) */
  255. VOID
  256. CleanupOptionDataEx( PVOID pMemoryListToFree );
  257. /* UnparseOptions:
  258. creates an argc/argv-like structure from a flat command.
  259. This is needed particularly for unix clients, although nt clients
  260. can use it without pulling in SHELL32.LIB. :-) */
  261. BOOL
  262. UnparseOptions( PCHAR flatCommand,
  263. int *pargc,
  264. PCHAR *pargv[] );
  265. #ifndef OPTIONS_NO_BACKWARD_COMPATIBILITY
  266. /* ParseOptions initializes the option structure-- note that the vector
  267. (optionStruct *) must be terminated with a sentinal value.
  268. This function is obsolete and is included for compatibility with older
  269. code. Call ParseOptionsEx instead. */
  270. int
  271. ParseOptions(
  272. /* IN */ int argc,
  273. /* IN */ char **argv,
  274. /* IN */ /* OUT */optionStruct *options );
  275. /* call cleanupOptionData at the end of your program. This will clear
  276. all memory used by the option parsing and returning system. */
  277. VOID
  278. CleanupOptionData( VOID );
  279. #endif
  280. #define ISSWITCH( ch /*character*/ ) ( (ch=='-') || (ch=='+') || (ch=='/') )
  281. #endif // file inclusion check.