stack.c 7.2 KB

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