gwenhywfar
4.3.1
|
00001 /*************************************************************************** 00002 $RCSfile$ 00003 ------------------- 00004 cvs : $Id$ 00005 begin : Sat Apr 24 2004 00006 copyright : (C) 2004 by Martin Preuss 00007 email : martin@libchipcard.de 00008 00009 *************************************************************************** 00010 * * 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU Lesser General Public * 00013 * License as published by the Free Software Foundation; either * 00014 * version 2.1 of the License, or (at your option) any later version. * 00015 * * 00016 * This library is distributed in the hope that it will be useful, * 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00019 * Lesser General Public License for more details. * 00020 * * 00021 * You should have received a copy of the GNU Lesser General Public * 00022 * License along with this library; if not, write to the Free Software * 00023 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00024 * MA 02111-1307 USA * 00025 * * 00026 ***************************************************************************/ 00027 00028 00029 #ifdef HAVE_CONFIG_H 00030 # include <config.h> 00031 #endif 00032 00033 #include "args_p.h" 00034 #include <gwenhywfar/misc.h> 00035 #include <gwenhywfar/debug.h> 00036 #include <gwenhywfar/text.h> 00037 #include <string.h> 00038 00039 #define DISABLE_DEBUGLOG 00040 00041 00042 00043 00044 int GWEN_Args_Check(int argc, char **argv, 00045 int startAt, 00046 uint32_t mode, 00047 const GWEN_ARGS *args, 00048 GWEN_DB_NODE *db){ 00049 int i; 00050 const char *p; 00051 const GWEN_ARGS *tmpArgs; 00052 GWEN_DB_NODE *counts; 00053 int stop; 00054 00055 i=startAt; 00056 00057 counts=GWEN_DB_Group_new("counts"); 00058 00059 stop=0; 00060 while(i<argc && !stop) { 00061 GWEN_ARGS_ELEMENT_TYPE t; 00062 char *tmpBuf; 00063 const char *v; 00064 int value; 00065 00066 DBG_INFO(GWEN_LOGDOMAIN, "Argument[%d] is \"%s\"", i, argv[i]); 00067 p=argv[i]; 00068 if (*p=='-') { 00069 p++; 00070 if (*p=='-') { 00071 p++; 00072 t=GWEN_ArgsElementTypeLong; 00073 } 00074 else 00075 t=GWEN_ArgsElementTypeShort; 00076 } 00077 else 00078 t=GWEN_ArgsElementTypeFreeParam; 00079 00080 switch(t) { 00081 case GWEN_ArgsElementTypeFreeParam: 00082 if (mode & GWEN_ARGS_MODE_ALLOW_FREEPARAM) { 00083 GWEN_DB_SetCharValue(db, 00084 GWEN_DB_FLAGS_DEFAULT, 00085 "params", p); 00086 i++; 00087 } 00088 else { 00089 DBG_ERROR(GWEN_LOGDOMAIN, "Only options are allowed, but argument \"%s\" was not recognized as a known option.", p); 00090 GWEN_DB_Group_free(counts); 00091 return GWEN_ARGS_RESULT_ERROR; 00092 } 00093 if (mode & GWEN_ARGS_MODE_STOP_AT_FREEPARAM) { 00094 DBG_DEBUG(GWEN_LOGDOMAIN, "Free parameter found, stopping as requested"); 00095 stop=1; 00096 } 00097 break; 00098 00099 case GWEN_ArgsElementTypeShort: 00100 for(tmpArgs=args;;tmpArgs++) { 00101 if (tmpArgs->shortOption) { 00102 if (strcmp(tmpArgs->shortOption, p)==0) { 00103 /* found option */ 00104 GWEN_DB_SetIntValue(counts, GWEN_DB_FLAGS_OVERWRITE_VARS, 00105 tmpArgs->name, 00106 GWEN_DB_GetIntValue(counts, 00107 tmpArgs->name, 0, 0)+1); 00108 break; 00109 } 00110 } /* if shortOption */ 00111 00112 if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) { 00113 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown short option \"%s\"", p); 00114 GWEN_DB_Group_free(counts); 00115 return GWEN_ARGS_RESULT_ERROR; 00116 } 00117 } /* for */ 00118 i++; 00119 00120 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) { 00121 /* argument needed */ 00122 if (i>=argc) { 00123 DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name); 00124 GWEN_DB_Group_free(counts); 00125 return GWEN_ARGS_RESULT_ERROR; 00126 } 00127 switch(tmpArgs->type) { 00128 case GWEN_ArgsType_Char: 00129 GWEN_DB_SetCharValue(db, 00130 GWEN_DB_FLAGS_DEFAULT, 00131 tmpArgs->name, argv[i]); 00132 break; 00133 00134 case GWEN_ArgsType_Int: 00135 if (sscanf(argv[i], "%i", &value)!=1) { 00136 DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for short option \"%s\"", p); 00137 GWEN_DB_Group_free(counts); 00138 return GWEN_ARGS_RESULT_ERROR; 00139 } 00140 GWEN_DB_SetIntValue(db, 00141 GWEN_DB_FLAGS_DEFAULT, 00142 tmpArgs->name, value); 00143 break; 00144 00145 default: 00146 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"", 00147 tmpArgs->type); 00148 GWEN_DB_Group_free(counts); 00149 return GWEN_ARGS_RESULT_ERROR; 00150 } /* switch */ 00151 i++; 00152 } 00153 else { 00154 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) { 00155 GWEN_DB_Group_free(counts); 00156 return GWEN_ARGS_RESULT_HELP; 00157 } 00158 GWEN_DB_SetIntValue(db, 00159 GWEN_DB_FLAGS_OVERWRITE_VARS, 00160 tmpArgs->name, 00161 GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0)); 00162 } 00163 break; 00164 00165 case GWEN_ArgsElementTypeLong: 00166 /* copy option name up to (but excluding) the "=" if any, 00167 * determine the start of possible argument */ 00168 v=p; 00169 while(*v && *v!='=') v++; 00170 tmpBuf=(char*)malloc(v-p+1); 00171 assert(tmpBuf); 00172 memmove(tmpBuf, p, v-p); 00173 tmpBuf[v-p]=0; 00174 00175 for(tmpArgs=args;;tmpArgs++) { 00176 if (tmpArgs->longOption) { 00177 if (strcmp(tmpArgs->longOption, tmpBuf)==0) { 00178 /* found option */ 00179 GWEN_DB_SetIntValue(counts, GWEN_DB_FLAGS_OVERWRITE_VARS, 00180 tmpArgs->name, 00181 GWEN_DB_GetIntValue(counts, 00182 tmpArgs->name, 0, 0)+1); 00183 break; 00184 } 00185 } /* if longOption */ 00186 00187 if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) { 00188 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown long option \"%s\"", tmpBuf); 00189 free(tmpBuf); 00190 GWEN_DB_Group_free(counts); 00191 return GWEN_ARGS_RESULT_ERROR; 00192 } 00193 } /* for */ 00194 i++; 00195 00196 if (*v=='=') { 00197 if (!(tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT)) { 00198 DBG_ERROR(GWEN_LOGDOMAIN, "No argument allowed for option \"%s\"", 00199 tmpArgs->name); 00200 free(tmpBuf); 00201 GWEN_DB_Group_free(counts); 00202 return GWEN_ARGS_RESULT_ERROR; 00203 } 00204 v++; 00205 } 00206 00207 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) { 00208 /* argument needed */ 00209 if (*v==0) { 00210 DBG_ERROR(GWEN_LOGDOMAIN, "Argument needed for option \"%s\"", tmpArgs->name); 00211 free(tmpBuf); 00212 GWEN_DB_Group_free(counts); 00213 return GWEN_ARGS_RESULT_ERROR; 00214 } 00215 switch(tmpArgs->type) { 00216 case GWEN_ArgsType_Char: 00217 GWEN_DB_SetCharValue(db, 00218 GWEN_DB_FLAGS_DEFAULT, 00219 tmpArgs->name, v); 00220 break; 00221 00222 case GWEN_ArgsType_Int: 00223 if (sscanf(v, "%i", &value)!=1) { 00224 DBG_ERROR(GWEN_LOGDOMAIN, "Non-integer argument for long option \"%s\"", 00225 tmpBuf); 00226 free(tmpBuf); 00227 GWEN_DB_Group_free(counts); 00228 return GWEN_ARGS_RESULT_ERROR; 00229 } 00230 GWEN_DB_SetIntValue(db, 00231 GWEN_DB_FLAGS_DEFAULT, 00232 tmpArgs->name, value); 00233 break; 00234 00235 default: 00236 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown option type \"%d\"", tmpArgs->type); 00237 GWEN_DB_Group_free(counts); 00238 return GWEN_ARGS_RESULT_ERROR; 00239 } /* switch */ 00240 } 00241 else { 00242 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HELP) { 00243 GWEN_DB_Group_free(counts); 00244 return GWEN_ARGS_RESULT_HELP; 00245 } 00246 GWEN_DB_SetIntValue(db, 00247 GWEN_DB_FLAGS_OVERWRITE_VARS, 00248 tmpArgs->name, 00249 GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0)); 00250 } 00251 free(tmpBuf); 00252 00253 break; 00254 00255 default: 00256 DBG_ERROR(GWEN_LOGDOMAIN, "Internal error (unknown argv type \"%d\")", 00257 t); 00258 GWEN_DB_Group_free(counts); 00259 return GWEN_ARGS_RESULT_ERROR; 00260 break; 00261 } /* switch */ 00262 } /* while */ 00263 00264 /* check argument counts */ 00265 for(tmpArgs=args;;tmpArgs++) { 00266 const char *s; 00267 int c; 00268 00269 if (tmpArgs->longOption) 00270 s=tmpArgs->longOption; 00271 else 00272 s=tmpArgs->shortOption; 00273 00274 c=GWEN_DB_GetIntValue(counts, tmpArgs->name, 0, 0); 00275 00276 /* check minnum */ 00277 if (tmpArgs->minNum && ((unsigned int)c<tmpArgs->minNum)) { 00278 if (tmpArgs->minNum>1) { 00279 DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed %d times (have %d)", 00280 s, tmpArgs->minNum, c); 00281 } 00282 else { 00283 DBG_ERROR(GWEN_LOGDOMAIN, "Option \"%s\" needed", s); 00284 } 00285 GWEN_DB_Group_free(counts); 00286 return GWEN_ARGS_RESULT_ERROR; 00287 } 00288 00289 /* check maxnum */ 00290 if (tmpArgs->maxNum && ((unsigned int)c>tmpArgs->maxNum)) { 00291 DBG_ERROR(GWEN_LOGDOMAIN, 00292 "Option \"%s\" needed at most %d times (have %d)", 00293 s, tmpArgs->maxNum, c); 00294 GWEN_DB_Group_free(counts); 00295 return GWEN_ARGS_RESULT_ERROR; 00296 } 00297 00298 if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) 00299 break; 00300 } /* for */ 00301 GWEN_DB_Group_free(counts); 00302 00303 return i; 00304 } 00305 00306 00307 int GWEN_Args__AppendTXT(GWEN_BUFFER *ubuf, const char *s, unsigned int ins){ 00308 unsigned int i; 00309 00310 while(*s) { 00311 for (i=0; i<ins; i++) GWEN_Buffer_AppendByte(ubuf, ' '); 00312 while(*s) { 00313 char c; 00314 00315 c=*s; 00316 s++; 00317 GWEN_Buffer_AppendByte(ubuf, c); 00318 if (c=='\n') 00319 break; 00320 } /* while */ 00321 } /* while */ 00322 00323 return 0; 00324 } 00325 00326 00327 00328 int GWEN_Args_UsageTXT(const GWEN_ARGS *args, GWEN_BUFFER *ubuf){ 00329 const GWEN_ARGS *tmpArgs; 00330 00331 for(tmpArgs=args;;tmpArgs++) { 00332 const char *s; 00333 00334 GWEN_Buffer_AppendString(ubuf, "\n"); 00335 if (tmpArgs->shortOption || tmpArgs->longOption) { 00336 if (tmpArgs->shortOption) { 00337 GWEN_Buffer_AppendString(ubuf, " "); 00338 if (tmpArgs->minNum==0) 00339 GWEN_Buffer_AppendString(ubuf, "["); 00340 else 00341 GWEN_Buffer_AppendString(ubuf, " "); 00342 GWEN_Buffer_AppendString(ubuf, "-"); 00343 GWEN_Buffer_AppendString(ubuf, tmpArgs->shortOption); 00344 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) 00345 GWEN_Buffer_AppendString(ubuf, " PARAM"); 00346 if (tmpArgs->minNum==0) 00347 GWEN_Buffer_AppendString(ubuf, "]"); 00348 GWEN_Buffer_AppendString(ubuf, "\n"); 00349 } /* if short option */ 00350 00351 if (tmpArgs->longOption) { 00352 GWEN_Buffer_AppendString(ubuf, " "); 00353 if (tmpArgs->minNum==0) 00354 GWEN_Buffer_AppendString(ubuf, "["); 00355 else 00356 GWEN_Buffer_AppendString(ubuf, " "); 00357 GWEN_Buffer_AppendString(ubuf, "--"); 00358 GWEN_Buffer_AppendString(ubuf, tmpArgs->longOption); 00359 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) 00360 GWEN_Buffer_AppendString(ubuf, "=PARAM"); 00361 if (tmpArgs->minNum==0) 00362 GWEN_Buffer_AppendString(ubuf, "]"); 00363 GWEN_Buffer_AppendString(ubuf, "\n"); 00364 } /* if short option */ 00365 00366 s=tmpArgs->longDescription; 00367 if (!s) 00368 s=tmpArgs->shortDescription; 00369 00370 if (s) { 00371 GWEN_Args__AppendTXT(ubuf, s, 3); 00372 GWEN_Buffer_AppendString(ubuf, "\n"); 00373 } 00374 } /* if any option */ 00375 else { 00376 DBG_ERROR(GWEN_LOGDOMAIN, 00377 "Option \"%s\" has neither a long nor a short name", 00378 tmpArgs->name); 00379 return -1; 00380 } 00381 00382 if (tmpArgs->flags & GWEN_ARGS_FLAGS_LAST) 00383 break; 00384 } /* for */ 00385 00386 return 0; 00387 } 00388 00389 00390 00391 int GWEN_Args_UsageHTML(GWEN_UNUSED const GWEN_ARGS *args, 00392 GWEN_UNUSED GWEN_BUFFER *ubuf){ 00393 return 0; 00394 } 00395 00396 00397 00398 int GWEN_Args_Usage(const GWEN_ARGS *args, GWEN_BUFFER *ubuf, 00399 GWEN_ARGS_OUTTYPE ot){ 00400 int rv; 00401 00402 switch(ot) { 00403 case GWEN_ArgsOutType_Txt: 00404 rv=GWEN_Args_UsageTXT(args, ubuf); 00405 break; 00406 case GWEN_ArgsOutType_Html: 00407 rv=GWEN_Args_UsageHTML(args, ubuf); 00408 break; 00409 default: 00410 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown output type %d", ot); 00411 rv=-1; 00412 } /* switch */ 00413 00414 return rv; 00415 } 00416 00417 00418 00419 int GWEN_Args_ShortUsage(GWEN_UNUSED const GWEN_ARGS *args, 00420 GWEN_UNUSED GWEN_BUFFER *ubuf, 00421 GWEN_UNUSED GWEN_ARGS_OUTTYPE ot){ 00422 return 0; 00423 } 00424 00425 00426 00427 00428 00429 00430