check.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /**
  2. * @file check.c
  3. *
  4. * @brief option consistency checks.
  5. *
  6. * @addtogroup autoopts
  7. * @{
  8. */
  9. /*
  10. * This file is part of AutoOpts, a companion to AutoGen.
  11. * AutoOpts is free software.
  12. * AutoOpts is Copyright (C) 1992-2016 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 sha256 sums:
  25. *
  26. * 8584710e9b04216a394078dc156b781d0b47e1729104d666658aecef8ee32e95 COPYING.gplv3
  27. * 4379e7444a0e2ce2b12dd6f5a52a27a4d02d39d247901d3285c88cf0d37f477b COPYING.lgplv3
  28. * 13aa749a5b0a454917a944ed8fffc530b784f5ead522b1aacaf4ec8aa55a6239 COPYING.mbsd
  29. */
  30. /**
  31. * Check for conflicts based on "must" and "cannot" attributes.
  32. */
  33. static bool
  34. has_conflict(tOptions * pOpts, tOptDesc * od)
  35. {
  36. if (od->pOptMust != NULL) {
  37. int const * must = od->pOptMust;
  38. while (*must != NO_EQUIVALENT) {
  39. tOptDesc * p = pOpts->pOptDesc + *(must++);
  40. if (UNUSED_OPT(p)) {
  41. const tOptDesc * ood = pOpts->pOptDesc + must[-1];
  42. fprintf(stderr, zneed_fmt, pOpts->pzProgName,
  43. od->pz_Name, ood->pz_Name);
  44. return true;
  45. }
  46. }
  47. }
  48. if (od->pOptCant != NULL) {
  49. int const * cant = od->pOptCant;
  50. while (*cant != NO_EQUIVALENT) {
  51. tOptDesc * p = pOpts->pOptDesc + *(cant++);
  52. if (SELECTED_OPT(p)) {
  53. const tOptDesc * ood = pOpts->pOptDesc + cant[-1];
  54. fprintf(stderr, zconflict_fmt, pOpts->pzProgName,
  55. od->pz_Name, ood->pz_Name);
  56. return true;
  57. }
  58. }
  59. }
  60. return false;
  61. }
  62. /**
  63. * Check that the option occurs often enough. Too often is already checked.
  64. */
  65. static bool
  66. occurs_enough(tOptions * pOpts, tOptDesc * pOD)
  67. {
  68. (void)pOpts;
  69. /*
  70. * IF the occurrence counts have been satisfied,
  71. * THEN there is no problem.
  72. */
  73. if (pOD->optOccCt >= pOD->optMinCt)
  74. return true;
  75. /*
  76. * IF MUST_SET means SET and PRESET are okay,
  77. * so min occurrence count doesn't count
  78. */
  79. if ( (pOD->fOptState & OPTST_MUST_SET)
  80. && (pOD->fOptState & (OPTST_PRESET | OPTST_SET)) )
  81. return true;
  82. if (pOD->optMinCt > 1)
  83. fprintf(stderr, zneed_more, pOpts->pzProgName, pOD->pz_Name,
  84. pOD->optMinCt);
  85. else fprintf(stderr, zneed_one, pOpts->pzProgName, pOD->pz_Name);
  86. return false;
  87. }
  88. /**
  89. * Verify option consistency.
  90. *
  91. * Make sure that the argument list passes our consistency tests.
  92. */
  93. LOCAL bool
  94. is_consistent(tOptions * pOpts)
  95. {
  96. tOptDesc * pOD = pOpts->pOptDesc;
  97. int oCt = pOpts->presetOptCt;
  98. /*
  99. * FOR each of "oCt" options, ...
  100. */
  101. for (;;) {
  102. /*
  103. * IF the current option was provided on the command line
  104. * THEN ensure that any "MUST" requirements are not
  105. * "DEFAULT" (unspecified) *AND* ensure that any
  106. * "CANT" options have not been SET or DEFINED.
  107. */
  108. if (SELECTED_OPT(pOD)) {
  109. if (has_conflict(pOpts, pOD))
  110. return false;
  111. }
  112. /*
  113. * IF this option is not equivalenced to another,
  114. * OR it is equivalenced to itself (is the equiv. root)
  115. * THEN we need to make sure it occurs often enough.
  116. */
  117. if ( (pOD->optEquivIndex == NO_EQUIVALENT)
  118. || (pOD->optEquivIndex == pOD->optIndex) )
  119. if (! occurs_enough(pOpts, pOD))
  120. return false;
  121. if (--oCt <= 0)
  122. break;
  123. pOD++;
  124. }
  125. /*
  126. * IF we are stopping on errors, check to see if any remaining
  127. * arguments are required to be there or prohibited from being there.
  128. */
  129. if ((pOpts->fOptSet & OPTPROC_ERRSTOP) != 0) {
  130. /*
  131. * Check for prohibition
  132. */
  133. if ((pOpts->fOptSet & OPTPROC_NO_ARGS) != 0) {
  134. if (pOpts->origArgCt > pOpts->curOptIdx) {
  135. fprintf(stderr, zNoArgs, pOpts->pzProgName);
  136. return false;
  137. }
  138. }
  139. /*
  140. * ELSE not prohibited, check for being required
  141. */
  142. else if ((pOpts->fOptSet & OPTPROC_ARGS_REQ) != 0) {
  143. if (pOpts->origArgCt <= pOpts->curOptIdx) {
  144. fprintf(stderr, zargs_must, pOpts->pzProgName);
  145. return false;
  146. }
  147. }
  148. }
  149. return true;
  150. }
  151. /** @}
  152. *
  153. * Local Variables:
  154. * mode: C
  155. * c-file-style: "stroustrup"
  156. * indent-tabs-mode: nil
  157. * End:
  158. * end of autoopts/check.c */