stack.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. /*
  2. * stack.c
  3. * $Id: stack.c,v 4.15 2007/07/04 21:36:38 bkorb Exp $
  4. * Time-stamp: "2007-07-04 11:34:57 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-2007 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. * 239588c55c22c60ffe159946a760a33e pkg/libopts/COPYING.gplv3
  26. * fa82ca978890795162346e661b47161a 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 = (tArgList*)pOptDesc->optCookie;
  49. /*
  50. * IF we don't have any stacked options,
  51. * THEN indicate that we don't have any of these options
  52. */
  53. if (pAL == NULL) {
  54. pOptDesc->fOptState &= OPTST_PERSISTENT_MASK;
  55. if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
  56. pOptDesc->fOptState |= OPTST_DISABLED;
  57. return;
  58. }
  59. #ifdef WITH_LIBREGEX
  60. {
  61. regex_t re;
  62. int i, ct, dIdx;
  63. if (regcomp( &re, pOptDesc->optArg.argString, REG_NOSUB ) != 0)
  64. return;
  65. /*
  66. * search the list for the entry(s) to remove. Entries that
  67. * are removed are *not* copied into the result. The source
  68. * index is incremented every time. The destination only when
  69. * we are keeping a define.
  70. */
  71. for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) {
  72. tCC* pzSrc = pAL->apzArgs[ i ];
  73. char* pzEq = strchr( pzSrc, '=' );
  74. if (pzEq != NULL)
  75. *pzEq = NUL;
  76. res = regexec( &re, pzSrc, (size_t)0, NULL, 0 );
  77. switch (res) {
  78. case 0:
  79. /*
  80. * Remove this entry by reducing the in-use count
  81. * and *not* putting the string pointer back into
  82. * the list.
  83. */
  84. AGFREE(pzSrc);
  85. pAL->useCt--;
  86. break;
  87. default:
  88. case REG_NOMATCH:
  89. if (pzEq != NULL)
  90. *pzEq = '=';
  91. /*
  92. * IF we have dropped an entry
  93. * THEN we have to move the current one.
  94. */
  95. if (dIdx != i)
  96. pAL->apzArgs[ dIdx ] = pzSrc;
  97. dIdx++;
  98. }
  99. }
  100. regfree( &re );
  101. }
  102. #else /* not WITH_LIBREGEX */
  103. {
  104. int i, ct, dIdx;
  105. /*
  106. * search the list for the entry(s) to remove. Entries that
  107. * are removed are *not* copied into the result. The source
  108. * index is incremented every time. The destination only when
  109. * we are keeping a define.
  110. */
  111. for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) {
  112. tCC* pzSrc = pAL->apzArgs[ i ];
  113. char* pzEq = strchr( pzSrc, '=' );
  114. if (pzEq != NULL)
  115. *pzEq = NUL;
  116. if (strcmp( pzSrc, pOptDesc->optArg.argString ) == 0) {
  117. /*
  118. * Remove this entry by reducing the in-use count
  119. * and *not* putting the string pointer back into
  120. * the list.
  121. */
  122. AGFREE(pzSrc);
  123. pAL->useCt--;
  124. } else {
  125. if (pzEq != NULL)
  126. *pzEq = '=';
  127. /*
  128. * IF we have dropped an entry
  129. * THEN we have to move the current one.
  130. */
  131. if (dIdx != i)
  132. pAL->apzArgs[ dIdx ] = pzSrc;
  133. dIdx++;
  134. }
  135. }
  136. }
  137. #endif /* WITH_LIBREGEX */
  138. /*
  139. * IF we have unstacked everything,
  140. * THEN indicate that we don't have any of these options
  141. */
  142. if (pAL->useCt == 0) {
  143. pOptDesc->fOptState &= OPTST_PERSISTENT_MASK;
  144. if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
  145. pOptDesc->fOptState |= OPTST_DISABLED;
  146. AGFREE( (void*)pAL );
  147. pOptDesc->optCookie = NULL;
  148. }
  149. }
  150. /*
  151. * Put an entry into an argument list. The first argument points to
  152. * a pointer to the argument list structure. It gets passed around
  153. * as an opaque address.
  154. */
  155. LOCAL void
  156. addArgListEntry( void** ppAL, void* entry )
  157. {
  158. tArgList* pAL = *(void**)ppAL;
  159. /*
  160. * IF we have never allocated one of these,
  161. * THEN allocate one now
  162. */
  163. if (pAL == NULL) {
  164. pAL = (tArgList*)AGALOC( sizeof( *pAL ), "new option arg stack" );
  165. if (pAL == NULL)
  166. return;
  167. pAL->useCt = 0;
  168. pAL->allocCt = MIN_ARG_ALLOC_CT;
  169. *ppAL = (void*)pAL;
  170. }
  171. /*
  172. * ELSE if we are out of room
  173. * THEN make it bigger
  174. */
  175. else if (pAL->useCt >= pAL->allocCt) {
  176. size_t sz = sizeof( *pAL );
  177. pAL->allocCt += INCR_ARG_ALLOC_CT;
  178. /*
  179. * The base structure contains space for MIN_ARG_ALLOC_CT
  180. * pointers. We subtract it off to find our augment size.
  181. */
  182. sz += sizeof(char*) * (pAL->allocCt - MIN_ARG_ALLOC_CT);
  183. pAL = (tArgList*)AGREALOC( (void*)pAL, sz, "expanded opt arg stack" );
  184. if (pAL == NULL)
  185. return;
  186. *ppAL = (void*)pAL;
  187. }
  188. /*
  189. * Insert the new argument into the list
  190. */
  191. pAL->apzArgs[ (pAL->useCt)++ ] = entry;
  192. }
  193. /*=export_func optionStackArg
  194. * private:
  195. *
  196. * what: put option args on a stack
  197. * arg: + tOptions* + pOpts + program options descriptor +
  198. * arg: + tOptDesc* + pOptDesc + the descriptor for this arg +
  199. *
  200. * doc:
  201. * Keep an entry-ordered list of option arguments.
  202. =*/
  203. void
  204. optionStackArg(
  205. tOptions* pOpts,
  206. tOptDesc* pOD )
  207. {
  208. char * pz;
  209. if (pOD->optArg.argString == NULL)
  210. return;
  211. AGDUPSTR(pz, pOD->optArg.argString, "stack arg");
  212. addArgListEntry( &(pOD->optCookie), (void*)pz );
  213. }
  214. /*
  215. * Local Variables:
  216. * mode: C
  217. * c-file-style: "stroustrup"
  218. * indent-tabs-mode: nil
  219. * End:
  220. * end of autoopts/stack.c */