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