stack.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * stack.c
  3. * $Id: stack.c,v 4.13 2007/02/04 17:44:12 bkorb Exp $
  4. * Time-stamp: "2007-01-13 10:43:21 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. /*
  10. * Automated Options copyright 1992-2007 Bruce Korb
  11. *
  12. * Automated Options is free software.
  13. * You may redistribute it and/or modify it under the terms of the
  14. * GNU General Public License, as published by the Free Software
  15. * Foundation; either version 2, or (at your option) any later version.
  16. *
  17. * Automated Options is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with Automated Options. See the file "COPYING". If not,
  24. * write to: The Free Software Foundation, Inc.,
  25. * 51 Franklin Street, Fifth Floor,
  26. * Boston, MA 02110-1301, USA.
  27. *
  28. * As a special exception, Bruce Korb gives permission for additional
  29. * uses of the text contained in his release of AutoOpts.
  30. *
  31. * The exception is that, if you link the AutoOpts library with other
  32. * files to produce an executable, this does not by itself cause the
  33. * resulting executable to be covered by the GNU General Public License.
  34. * Your use of that executable is in no way restricted on account of
  35. * linking the AutoOpts library code into it.
  36. *
  37. * This exception does not however invalidate any other reasons why
  38. * the executable file might be covered by the GNU General Public License.
  39. *
  40. * This exception applies only to the code released by Bruce Korb under
  41. * the name AutoOpts. If you copy code from other sources under the
  42. * General Public License into a copy of AutoOpts, as the General Public
  43. * License permits, the exception does not apply to the code that you add
  44. * in this way. To avoid misleading anyone as to the status of such
  45. * modified files, you must delete this exception notice from them.
  46. *
  47. * If you write modifications of your own for AutoOpts, it is your choice
  48. * whether to permit this exception to apply to your modifications.
  49. * If you do not wish that, delete this exception notice.
  50. */
  51. #ifdef WITH_LIBREGEX
  52. # include REGEX_HEADER
  53. #endif
  54. /*=export_func optionUnstackArg
  55. * private:
  56. *
  57. * what: Remove option args from a stack
  58. * arg: + tOptions* + pOpts + program options descriptor +
  59. * arg: + tOptDesc* + pOptDesc + the descriptor for this arg +
  60. *
  61. * doc:
  62. * Invoked for options that are equivalenced to stacked options.
  63. =*/
  64. void
  65. optionUnstackArg(
  66. tOptions* pOpts,
  67. tOptDesc* pOptDesc )
  68. {
  69. int res;
  70. tArgList* pAL = (tArgList*)pOptDesc->optCookie;
  71. /*
  72. * IF we don't have any stacked options,
  73. * THEN indicate that we don't have any of these options
  74. */
  75. if (pAL == NULL) {
  76. pOptDesc->fOptState &= OPTST_PERSISTENT_MASK;
  77. if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
  78. pOptDesc->fOptState |= OPTST_DISABLED;
  79. return;
  80. }
  81. #ifdef WITH_LIBREGEX
  82. {
  83. regex_t re;
  84. int i, ct, dIdx;
  85. if (regcomp( &re, pOptDesc->optArg.argString, REG_NOSUB ) != 0)
  86. return;
  87. /*
  88. * search the list for the entry(s) to remove. Entries that
  89. * are removed are *not* copied into the result. The source
  90. * index is incremented every time. The destination only when
  91. * we are keeping a define.
  92. */
  93. for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) {
  94. tCC* pzSrc = pAL->apzArgs[ i ];
  95. char* pzEq = strchr( pzSrc, '=' );
  96. if (pzEq != NULL)
  97. *pzEq = NUL;
  98. res = regexec( &re, pzSrc, (size_t)0, NULL, 0 );
  99. switch (res) {
  100. case 0:
  101. /*
  102. * Remove this entry by reducing the in-use count
  103. * and *not* putting the string pointer back into
  104. * the list.
  105. */
  106. AGFREE(pzSrc);
  107. pAL->useCt--;
  108. break;
  109. default:
  110. case REG_NOMATCH:
  111. if (pzEq != NULL)
  112. *pzEq = '=';
  113. /*
  114. * IF we have dropped an entry
  115. * THEN we have to move the current one.
  116. */
  117. if (dIdx != i)
  118. pAL->apzArgs[ dIdx ] = pzSrc;
  119. dIdx++;
  120. }
  121. }
  122. regfree( &re );
  123. }
  124. #else /* not WITH_LIBREGEX */
  125. {
  126. int i, ct, dIdx;
  127. /*
  128. * search the list for the entry(s) to remove. Entries that
  129. * are removed are *not* copied into the result. The source
  130. * index is incremented every time. The destination only when
  131. * we are keeping a define.
  132. */
  133. for (i = 0, dIdx = 0, ct = pAL->useCt; --ct >= 0; i++) {
  134. tCC* pzSrc = pAL->apzArgs[ i ];
  135. char* pzEq = strchr( pzSrc, '=' );
  136. if (pzEq != NULL)
  137. *pzEq = NUL;
  138. if (strcmp( pzSrc, pOptDesc->optArg.argString ) == 0) {
  139. /*
  140. * Remove this entry by reducing the in-use count
  141. * and *not* putting the string pointer back into
  142. * the list.
  143. */
  144. AGFREE(pzSrc);
  145. pAL->useCt--;
  146. } else {
  147. if (pzEq != NULL)
  148. *pzEq = '=';
  149. /*
  150. * IF we have dropped an entry
  151. * THEN we have to move the current one.
  152. */
  153. if (dIdx != i)
  154. pAL->apzArgs[ dIdx ] = pzSrc;
  155. dIdx++;
  156. }
  157. }
  158. }
  159. #endif /* WITH_LIBREGEX */
  160. /*
  161. * IF we have unstacked everything,
  162. * THEN indicate that we don't have any of these options
  163. */
  164. if (pAL->useCt == 0) {
  165. pOptDesc->fOptState &= OPTST_PERSISTENT_MASK;
  166. if ( (pOptDesc->fOptState & OPTST_INITENABLED) == 0)
  167. pOptDesc->fOptState |= OPTST_DISABLED;
  168. AGFREE( (void*)pAL );
  169. pOptDesc->optCookie = NULL;
  170. }
  171. }
  172. /*
  173. * Put an entry into an argument list. The first argument points to
  174. * a pointer to the argument list structure. It gets passed around
  175. * as an opaque address.
  176. */
  177. LOCAL void
  178. addArgListEntry( void** ppAL, void* entry )
  179. {
  180. tArgList* pAL = *(void**)ppAL;
  181. /*
  182. * IF we have never allocated one of these,
  183. * THEN allocate one now
  184. */
  185. if (pAL == NULL) {
  186. pAL = (tArgList*)AGALOC( sizeof( *pAL ), "new option arg stack" );
  187. if (pAL == NULL)
  188. return;
  189. pAL->useCt = 0;
  190. pAL->allocCt = MIN_ARG_ALLOC_CT;
  191. *ppAL = (void*)pAL;
  192. }
  193. /*
  194. * ELSE if we are out of room
  195. * THEN make it bigger
  196. */
  197. else if (pAL->useCt >= pAL->allocCt) {
  198. size_t sz = sizeof( *pAL );
  199. pAL->allocCt += INCR_ARG_ALLOC_CT;
  200. /*
  201. * The base structure contains space for MIN_ARG_ALLOC_CT
  202. * pointers. We subtract it off to find our augment size.
  203. */
  204. sz += sizeof(char*) * (pAL->allocCt - MIN_ARG_ALLOC_CT);
  205. pAL = (tArgList*)AGREALOC( (void*)pAL, sz, "expanded opt arg stack" );
  206. if (pAL == NULL)
  207. return;
  208. *ppAL = (void*)pAL;
  209. }
  210. /*
  211. * Insert the new argument into the list
  212. */
  213. pAL->apzArgs[ (pAL->useCt)++ ] = entry;
  214. }
  215. /*=export_func optionStackArg
  216. * private:
  217. *
  218. * what: put option args on a stack
  219. * arg: + tOptions* + pOpts + program options descriptor +
  220. * arg: + tOptDesc* + pOptDesc + the descriptor for this arg +
  221. *
  222. * doc:
  223. * Keep an entry-ordered list of option arguments.
  224. =*/
  225. void
  226. optionStackArg(
  227. tOptions* pOpts,
  228. tOptDesc* pOD )
  229. {
  230. char * pz;
  231. if (pOD->optArg.argString == NULL)
  232. return;
  233. AGDUPSTR(pz, pOD->optArg.argString, "stack arg");
  234. addArgListEntry( &(pOD->optCookie), (void*)pz );
  235. }
  236. /*
  237. * Local Variables:
  238. * mode: C
  239. * c-file-style: "stroustrup"
  240. * indent-tabs-mode: nil
  241. * End:
  242. * end of autoopts/stack.c */