stack.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. /*
  2. * stack.c
  3. * $Id: stack.c,v 4.17 2008/08/02 16:10:07 bkorb Exp $
  4. * Time-stamp: "2008-07-30 16:56:32 bkorb"
  5. *
  6. * This is a special option processing routine that will save the
  7. * argument to an option in a FIFO queue.
  8. *
  9. * This file is part of AutoOpts, a companion to AutoGen.
  10. * AutoOpts is free software.
  11. * AutoOpts is copyright (c) 1992-2008 by Bruce Korb - all rights reserved
  12. * AutoOpts is copyright (c) 1992-2008 by Bruce Korb - all rights reserved
  13. *
  14. * AutoOpts is available under any one of two licenses. The license
  15. * in use must be one of these two and the choice is under the control
  16. * of the user of the license.
  17. *
  18. * The GNU Lesser General Public License, version 3 or later
  19. * See the files "COPYING.lgplv3" and "COPYING.gplv3"
  20. *
  21. * The Modified Berkeley Software Distribution License
  22. * See the file "COPYING.mbsd"
  23. *
  24. * These files have the following md5sums:
  25. *
  26. * 239588c55c22c60ffe159946a760a33e pkg/libopts/COPYING.gplv3
  27. * fa82ca978890795162346e661b47161a pkg/libopts/COPYING.lgplv3
  28. * 66a5cedaf62c4b2637025f049f9b826f pkg/libopts/COPYING.mbsd
  29. */
  30. #ifdef WITH_LIBREGEX
  31. # include REGEX_HEADER
  32. #endif
  33. /*=export_func optionUnstackArg
  34. * private:
  35. *
  36. * what: Remove option args from a stack
  37. * arg: + tOptions* + pOpts + program options descriptor +
  38. * arg: + tOptDesc* + pOptDesc + the descriptor for this arg +
  39. *
  40. * doc:
  41. * Invoked for options that are equivalenced to stacked options.
  42. =*/
  43. void
  44. optionUnstackArg(
  45. tOptions* pOpts,
  46. tOptDesc* pOptDesc )
  47. {
  48. int res;
  49. tArgList* pAL;
  50. if ((pOptDesc->fOptState & OPTST_RESET) != 0)
  51. return;
  52. pAL = (tArgList*)pOptDesc->optCookie;
  53. /*
  54. * IF we don't have any stacked options,
  55. * THEN indicate that we don't have any of these options
  56. */
  57. if (pAL == NULL) {
  58. pOptDesc->fOptState &= OPTST_PERSISTENT_MASK;
  59. if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
  60. pOptDesc->fOptState |= OPTST_DISABLED;
  61. return;
  62. }
  63. #ifdef WITH_LIBREGEX
  64. {
  65. regex_t re;
  66. int i, ct, dIdx;
  67. if (regcomp( &re, pOptDesc->optArg.argString, REG_NOSUB ) != 0)
  68. return;
  69. /*
  70. * search the list for the entry(s) to remove. Entries that
  71. * are removed are *not* copied into the result. The source
  72. * index is incremented every time. The destination only when
  73. * we are keeping a define.
  74. */
  75. for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) {
  76. tCC* pzSrc = pAL->apzArgs[ i ];
  77. char* pzEq = strchr( pzSrc, '=' );
  78. if (pzEq != NULL)
  79. *pzEq = NUL;
  80. res = regexec( &re, pzSrc, (size_t)0, NULL, 0 );
  81. switch (res) {
  82. case 0:
  83. /*
  84. * Remove this entry by reducing the in-use count
  85. * and *not* putting the string pointer back into
  86. * the list.
  87. */
  88. AGFREE(pzSrc);
  89. pAL->useCt--;
  90. break;
  91. default:
  92. case REG_NOMATCH:
  93. if (pzEq != NULL)
  94. *pzEq = '=';
  95. /*
  96. * IF we have dropped an entry
  97. * THEN we have to move the current one.
  98. */
  99. if (dIdx != i)
  100. pAL->apzArgs[ dIdx ] = pzSrc;
  101. dIdx++;
  102. }
  103. }
  104. regfree( &re );
  105. }
  106. #else /* not WITH_LIBREGEX */
  107. {
  108. int i, ct, dIdx;
  109. /*
  110. * search the list for the entry(s) to remove. Entries that
  111. * are removed are *not* copied into the result. The source
  112. * index is incremented every time. The destination only when
  113. * we are keeping a define.
  114. */
  115. for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) {
  116. tCC* pzSrc = pAL->apzArgs[ i ];
  117. char* pzEq = strchr( pzSrc, '=' );
  118. if (pzEq != NULL)
  119. *pzEq = NUL;
  120. if (strcmp( pzSrc, pOptDesc->optArg.argString ) == 0) {
  121. /*
  122. * Remove this entry by reducing the in-use count
  123. * and *not* putting the string pointer back into
  124. * the list.
  125. */
  126. AGFREE(pzSrc);
  127. pAL->useCt--;
  128. } else {
  129. if (pzEq != NULL)
  130. *pzEq = '=';
  131. /*
  132. * IF we have dropped an entry
  133. * THEN we have to move the current one.
  134. */
  135. if (dIdx != i)
  136. pAL->apzArgs[ dIdx ] = pzSrc;
  137. dIdx++;
  138. }
  139. }
  140. }
  141. #endif /* WITH_LIBREGEX */
  142. /*
  143. * IF we have unstacked everything,
  144. * THEN indicate that we don't have any of these options
  145. */
  146. if (pAL->useCt == 0) {
  147. pOptDesc->fOptState &= OPTST_PERSISTENT_MASK;
  148. if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
  149. pOptDesc->fOptState |= OPTST_DISABLED;
  150. AGFREE( (void*)pAL );
  151. pOptDesc->optCookie = NULL;
  152. }
  153. }
  154. /*
  155. * Put an entry into an argument list. The first argument points to
  156. * a pointer to the argument list structure. It gets passed around
  157. * as an opaque address.
  158. */
  159. LOCAL void
  160. addArgListEntry( void** ppAL, void* entry )
  161. {
  162. tArgList* pAL = *(void**)ppAL;
  163. /*
  164. * IF we have never allocated one of these,
  165. * THEN allocate one now
  166. */
  167. if (pAL == NULL) {
  168. pAL = (tArgList*)AGALOC( sizeof( *pAL ), "new option arg stack" );
  169. if (pAL == NULL)
  170. return;
  171. pAL->useCt = 0;
  172. pAL->allocCt = MIN_ARG_ALLOC_CT;
  173. *ppAL = (void*)pAL;
  174. }
  175. /*
  176. * ELSE if we are out of room
  177. * THEN make it bigger
  178. */
  179. else if (pAL->useCt >= pAL->allocCt) {
  180. size_t sz = sizeof( *pAL );
  181. pAL->allocCt += INCR_ARG_ALLOC_CT;
  182. /*
  183. * The base structure contains space for MIN_ARG_ALLOC_CT
  184. * pointers. We subtract it off to find our augment size.
  185. */
  186. sz += sizeof(char*) * (pAL->allocCt - MIN_ARG_ALLOC_CT);
  187. pAL = (tArgList*)AGREALOC( (void*)pAL, sz, "expanded opt arg stack" );
  188. if (pAL == NULL)
  189. return;
  190. *ppAL = (void*)pAL;
  191. }
  192. /*
  193. * Insert the new argument into the list
  194. */
  195. pAL->apzArgs[ (pAL->useCt)++ ] = entry;
  196. }
  197. /*=export_func optionStackArg
  198. * private:
  199. *
  200. * what: put option args on a stack
  201. * arg: + tOptions* + pOpts + program options descriptor +
  202. * arg: + tOptDesc* + pOptDesc + the descriptor for this arg +
  203. *
  204. * doc:
  205. * Keep an entry-ordered list of option arguments.
  206. =*/
  207. void
  208. optionStackArg(
  209. tOptions* pOpts,
  210. tOptDesc* pOD )
  211. {
  212. char * pz;
  213. if ((pOD->fOptState & OPTST_RESET) != 0) {
  214. tArgList* pAL = (void*)pOD->optCookie;
  215. int ix;
  216. if (pAL == NULL)
  217. return;
  218. ix = pAL->useCt;
  219. while (--ix >= 0)
  220. AGFREE(pAL->apzArgs[ix]);
  221. AGFREE(pAL);
  222. } else {
  223. if (pOD->optArg.argString == NULL)
  224. return;
  225. AGDUPSTR(pz, pOD->optArg.argString, "stack arg");
  226. addArgListEntry( &(pOD->optCookie), (void*)pz );
  227. }
  228. }
  229. /*
  230. * Local Variables:
  231. * mode: C
  232. * c-file-style: "stroustrup"
  233. * indent-tabs-mode: nil
  234. * End:
  235. * end of autoopts/stack.c */