Source code of Windows XP (NT5)
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.

242 lines
6.2 KiB

  1. /*** parsearg.c - Library functions for parsing command line arguments
  2. *
  3. * Copyright (c) 1996,1997 Microsoft Corporation
  4. * Author: Michael Tsang (MikeTs)
  5. * Created: 09/05/96
  6. *
  7. * This module provides general purpose services to parse
  8. * command line arguments.
  9. *
  10. * MODIFICATION HISTORY
  11. */
  12. #include "basedef.h"
  13. #include "parsearg.h"
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. /*** Local function prototypes
  18. */
  19. int LOCAL ParseArgSwitch(char **, PARGTYPE, PPROGINFO);
  20. VOID LOCAL PrintError(int, char *, PPROGINFO);
  21. /***EP ParseProgInfo - parse program path and module name
  22. *
  23. * ENTRY
  24. * pszArg0 -> argument 0
  25. * pPI -> program info structure
  26. *
  27. * EXIT
  28. * None
  29. */
  30. VOID EXPORT ParseProgInfo(char *pszArg0, PPROGINFO pPI)
  31. {
  32. char *pch;
  33. pPI->pszProgPath = _strlwr(pszArg0);
  34. if ((pch = strrchr(pszArg0, '\\')) != NULL)
  35. {
  36. *pch = '\0';
  37. pPI->pszProgName = pch + 1;
  38. }
  39. else
  40. {
  41. pPI->pszProgName = pszArg0;
  42. }
  43. if ((pch = strchr(pPI->pszProgName, '.')) != NULL)
  44. *pch = '\0';
  45. } //ParseProgInfo
  46. /***EP ParseSwitches - parse command switches
  47. *
  48. * ENTRY
  49. * pcArg -> argument count
  50. * pppszArg -> pointer to array of pointers to argument strings
  51. * pAT -> argument type array
  52. * pPI -> program info. structure
  53. *
  54. * EXIT-SUCCESS
  55. * returns ARGERR_NONE
  56. * EXIT-FAILURE
  57. * returns error code, *pppszArg -> error argument
  58. */
  59. int EXPORT ParseSwitches(int *pcArg, char ***pppszArg, PARGTYPE pAT, PPROGINFO pPI)
  60. {
  61. int rc = ARGERR_NONE;
  62. char *pszArg;
  63. if (pPI->pszSwitchChars == NULL)
  64. pPI->pszSwitchChars = DEF_SWITCHCHARS;
  65. if (pPI->pszSeparators == NULL)
  66. pPI->pszSeparators = DEF_SEPARATORS;
  67. for (; *pcArg; (*pcArg)--, (*pppszArg)++)
  68. {
  69. pszArg = **pppszArg;
  70. if (strchr(pPI->pszSwitchChars, *pszArg))
  71. {
  72. pszArg++;
  73. if ((rc = ParseArgSwitch(&pszArg, pAT, pPI)) != ARGERR_NONE)
  74. {
  75. PrintError(rc, pszArg, pPI);
  76. break;
  77. }
  78. }
  79. else
  80. break;
  81. }
  82. return rc;
  83. } //ParseSwitches
  84. /***LP ParseArgSwitch - parse a command line switch
  85. *
  86. * ENTRY
  87. * ppszArg -> pointer to argument
  88. * pAT -> argument type table
  89. * pPI -> program info. structure
  90. *
  91. * EXIT
  92. * return argument parsed status - ARGERR_NONE
  93. * - ARGERR_UNKNOWN_SWITCH
  94. * - ARGERR_INVALID_NUM
  95. * - ARGERR_NO_SEPARATOR
  96. * - ARGERR_INVALID_TAIL
  97. */
  98. int LOCAL ParseArgSwitch(char **ppszArg, PARGTYPE pAT, PPROGINFO pPI)
  99. {
  100. int rc = ARGERR_NONE;
  101. char *pEnd;
  102. PARGTYPE pAT1;
  103. int fFound = FALSE;
  104. int lenMatch = 0;
  105. pAT1 = pAT;
  106. while (pAT1->pszArgID[0])
  107. {
  108. lenMatch = strlen(pAT1->pszArgID);
  109. if (pAT1->uParseFlags & PF_NOI)
  110. fFound = (strncmp(pAT1->pszArgID, *ppszArg, lenMatch) == 0);
  111. else
  112. fFound = (_strnicmp(pAT1->pszArgID, *ppszArg, lenMatch) == 0);
  113. if (fFound)
  114. break;
  115. else
  116. pAT1++;
  117. }
  118. if (fFound)
  119. {
  120. *ppszArg += lenMatch;
  121. switch (pAT1->uArgType)
  122. {
  123. case AT_STRING:
  124. case AT_NUM:
  125. if (pAT1->uParseFlags & PF_SEPARATOR)
  126. {
  127. if (**ppszArg && strchr(pPI->pszSeparators, **ppszArg))
  128. (*ppszArg)++;
  129. else
  130. {
  131. rc = ARGERR_NO_SEPARATOR;
  132. break;
  133. }
  134. }
  135. if (pAT1->uArgType == AT_STRING)
  136. *(char **)pAT1->pvArgData = *ppszArg;
  137. else
  138. {
  139. *(int *)pAT1->pvArgData = (int)
  140. strtol(*ppszArg, &pEnd, pAT1->uArgParam);
  141. if (*ppszArg == pEnd)
  142. {
  143. rc = ARGERR_INVALID_NUM;
  144. break;
  145. }
  146. else
  147. *ppszArg = pEnd;
  148. }
  149. if (pAT1->pfnArgVerify)
  150. rc = (*pAT1->pfnArgVerify)(ppszArg, pAT1);
  151. break;
  152. case AT_ENABLE:
  153. case AT_DISABLE:
  154. if (pAT1->uArgType == AT_ENABLE)
  155. *(unsigned *)pAT1->pvArgData |= pAT1->uArgParam;
  156. else
  157. *(unsigned *)pAT1->pvArgData &= ~pAT1->uArgParam;
  158. if ((pAT1->pfnArgVerify) &&
  159. ((rc = (*pAT1->pfnArgVerify)(ppszArg, pAT1)) !=
  160. ARGERR_NONE))
  161. {
  162. break;
  163. }
  164. if (**ppszArg)
  165. {
  166. if (strchr(pPI->pszSwitchChars, **ppszArg))
  167. (*ppszArg)++;
  168. rc = ParseArgSwitch(ppszArg, pAT, pPI);
  169. }
  170. break;
  171. case AT_ACTION:
  172. #pragma warning(disable: 4055)
  173. rc = (*(PFNARG)pAT1->pvArgData)(ppszArg, pAT1);
  174. #pragma warning(default: 4055)
  175. break;
  176. }
  177. }
  178. else
  179. rc = ARGERR_UNKNOWN_SWITCH;
  180. return rc;
  181. } //ParseArgSwitch
  182. /***LP PrintError - print appropriate error message according to error code
  183. *
  184. * ENTRY
  185. * iErr = error code
  186. * pszArg -> argument in error
  187. * pPI -> program info. structure
  188. *
  189. * EXIT
  190. * None
  191. */
  192. VOID LOCAL PrintError(int iErr, char *pszArg, PPROGINFO pPI)
  193. {
  194. switch (iErr)
  195. {
  196. case ARGERR_UNKNOWN_SWITCH:
  197. printf("%s: unknown switch \"%s\"\n", pPI->pszProgName, pszArg);
  198. break;
  199. case ARGERR_NO_SEPARATOR:
  200. printf("%s: separator missing after the switch char '%c'\n",
  201. pPI->pszProgName, *(pszArg-1));
  202. break;
  203. case ARGERR_INVALID_NUM:
  204. printf("%s: invalid numeric switch \"%s\"\n",
  205. pPI->pszProgName, pszArg);
  206. break;
  207. case ARGERR_INVALID_TAIL:
  208. printf("%s: invalid argument tail \"%s\"\n",
  209. pPI->pszProgName, pszArg);
  210. }
  211. } //PrintError