00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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 }
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 }
00118 i++;
00119
00120 if (tmpArgs->flags & GWEN_ARGS_FLAGS_HAS_ARGUMENT) {
00121
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 }
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
00167
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
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 }
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 }
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
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 }
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 }
00262 }
00263
00264
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
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
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 }
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 }
00321 }
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 }
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 }
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 }
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 }
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 }
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