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