Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

clp.c

Go to the documentation of this file.
00001 /* clp.c - Complete source code for CLP.
00002    Copyright (C) 1997-2001 Eddie Kohler, eddietwo@lcs.mit.edu
00003    This file is part of CLP, the command line parser package.
00004 
00005    CLP is free software. It is distributed under the GNU Lesser General Public
00006    License, version 2 or later; you can copy, distribute, or alter it at will,
00007    as long as this notice is kept intact and this source code is made
00008    available. There is no warranty, express or implied. */
00009 
00010 #ifdef HAVE_CONFIG_H
00011 # include "config.h"
00012 #endif
00013 #include "clp.h"
00014 #include <stdlib.h>
00015 #include <string.h>
00016 #include <stdio.h>
00017 #include <assert.h>
00018 #include <stdarg.h>
00019 #include <ctype.h>
00020 
00021 /* By default, assume we have strtoul. */
00022 #if !defined(HAVE_STRTOUL) && !defined(HAVE_CONFIG_H)
00023 # define HAVE_STRTOUL 1
00024 #endif
00025 
00026 #ifdef __cplusplus
00027 extern "C" {
00028 #endif
00029 
00030 /* Option types for Clp_SetOptionChar */
00031 #define Clp_DoubledLong         (Clp_LongImplicit * 2)
00032 
00033 #define Clp_AnyArgument (Clp_Mandatory | Clp_Optional)
00034 
00035 #define MAX_AMBIGUOUS_VALUES    4
00036 
00037 typedef struct {
00038   
00039   Clp_ArgParseFunc func;
00040   int flags;
00041   void *thunk;
00042   
00043 } Clp_ArgType;
00044 
00045 
00046 typedef struct {
00047 
00048   int pos;
00049   int neg;
00050 
00051 } Clp_LongMinMatch;
00052 
00053 
00054 struct Clp_Internal {
00055 
00056   Clp_Option *opt;
00057   Clp_LongMinMatch *long_min_match;
00058   int nopt;
00059   
00060   Clp_ArgType *argtype;
00061   int nargtype;
00062   
00063   char * const *argv;
00064   int argc;
00065   
00066   unsigned char option_class[256];
00067   int both_short_and_long;
00068   
00069   char option_chars[3];
00070   char *text;
00071   
00072   char *program_name;
00073   void (*error_handler)(char *);
00074   
00075   int is_short;
00076   int whole_negated;            /* true if negated by an option character */
00077   int could_be_short;
00078   
00079   int option_processing;
00080   
00081   int ambiguous;
00082   int ambiguous_values[MAX_AMBIGUOUS_VALUES];
00083   
00084   Clp_Option *current_option;
00085   int current_short;
00086   int negated_by_no;
00087   
00088 };
00089 
00090 
00091 struct Clp_ParserState {
00092   
00093   char * const *argv;
00094   int argc;
00095   char option_chars[3];
00096   char *text;
00097   int is_short;
00098   int whole_negated;
00099   
00100 };
00101 
00102 
00103 typedef struct Clp_StringList {
00104 
00105   Clp_Option *items;
00106   Clp_LongMinMatch *long_min_match;
00107   int nitems;
00108   
00109   int allow_int;
00110   int nitems_invalid_report;
00111   
00112 } Clp_StringList;
00113 
00114 
00115 #define TEST(o, f)              (((o)->flags & (f)) != 0)
00116 
00117 
00118 static int calculate_long_min_match(int, Clp_Option *, int, int, int);
00119 
00120 static int parse_string(Clp_Parser *, const char *, int, void *);
00121 static int parse_int(Clp_Parser *, const char *, int, void *);
00122 static int parse_bool(Clp_Parser *, const char *, int, void *);
00123 static int parse_double(Clp_Parser *, const char *, int, void *);
00124 static int parse_string_list(Clp_Parser *, const char *, int, void *);
00125 
00126 static int ambiguity_error(Clp_Parser *, int, int *, Clp_Option *,
00127                            const char *, const char *, ...);
00128 
00129 
00130 /*******
00131  * Clp_NewParser, etc.
00132  **/
00133 
00134 static void
00135 check_duplicated_short_options(int nopt, Clp_Option *opt, int negated)
00136 {
00137   int i;
00138   int check[256];
00139   
00140   for (i = 0; i < 256; i++)
00141     check[i] = -1;
00142   
00143   for (i = 0; i < nopt; i++)
00144     if (opt[i].short_name > 0 && opt[i].short_name < 256
00145         && (negated ? TEST(&opt[i], Clp_Negate)
00146             : !TEST(&opt[i], Clp_OnlyNegated))) {
00147       int sh = opt[i].short_name;
00148       if (check[sh] >= 0 && check[sh] != opt[i].option_id)
00149         fprintf(stderr, "CLP error: more than 1 option has short name `%c'\n",
00150                 sh);
00151       check[sh] = opt[i].option_id;
00152     }
00153 }
00154 
00155 Clp_Parser *
00156 Clp_NewParser(int argc, char * const argv[], int nopt, Clp_Option *opt)
00157      /* Creates and returns a new Clp_Parser using the options in `opt',
00158         or 0 on memory allocation failure */
00159 {
00160   int i;
00161   Clp_Parser *clp = (Clp_Parser *)malloc(sizeof(Clp_Parser));
00162   Clp_Internal *cli = (Clp_Internal *)malloc(sizeof(Clp_Internal));
00163   Clp_LongMinMatch *lmm = (Clp_LongMinMatch *)malloc(sizeof(Clp_LongMinMatch) * nopt);
00164   if (!clp || !cli || !lmm) goto failed;
00165   
00166   clp->internal = cli;
00167   cli->long_min_match = lmm;
00168   
00169   /* Get rid of negative option_ids, which are internal to CLP */
00170   for (i = 0; i < nopt; i++)
00171     if (opt[i].option_id < 0) {
00172       fprintf(stderr, "CLP error: option %d has negative option_id\n", i);
00173       opt[i] = opt[nopt - 1];
00174       nopt--;
00175       i--;
00176     }
00177   
00178   /* Massage the options to make them usable */
00179   for (i = 0; i < nopt; i++) {
00180     /* Enforce invariants */
00181     if (opt[i].arg_type <= 0)
00182       opt[i].flags &= ~Clp_AnyArgument;
00183     if (opt[i].arg_type > 0 && !TEST(&opt[i], Clp_Optional))
00184       opt[i].flags |= Clp_Mandatory;
00185     
00186     /* Nonexistent short options have character 256. We know this won't
00187        equal any character in an argument, even if characters are signed */
00188     if (opt[i].short_name <= 0 || opt[i].short_name > 255)
00189       opt[i].short_name = 256;
00190     
00191     /* Options that start with `no-' should be changed to OnlyNegated */
00192     if (opt[i].long_name && strncmp(opt[i].long_name, "no-", 3) == 0) {
00193       opt[i].long_name += 3;
00194       opt[i].flags |= Clp_Negate | Clp_OnlyNegated;
00195     }
00196   }
00197   
00198   /* Check for duplicated short options */
00199   check_duplicated_short_options(nopt, opt, 0);
00200   check_duplicated_short_options(nopt, opt, 1);
00201   
00202   /* Calculate long options' minimum unambiguous length */
00203   for (i = 0; i < nopt; i++)
00204     if (opt[i].long_name && !TEST(&opt[i], Clp_OnlyNegated))
00205       lmm[i].pos = calculate_long_min_match
00206         (nopt, opt, i, Clp_OnlyNegated, 0);
00207   for (i = 0; i < nopt; i++)
00208     if (opt[i].long_name && TEST(&opt[i], Clp_Negate))
00209       lmm[i].neg = calculate_long_min_match
00210         (nopt, opt, i, Clp_Negate, Clp_Negate);
00211   
00212   /* Set up clp->internal */
00213   cli->opt = opt;
00214   cli->nopt = nopt;
00215   
00216   cli->argtype = (Clp_ArgType *)malloc(sizeof(Clp_ArgType) * 5);
00217   if (!cli->argtype) goto failed;
00218   cli->nargtype = 5;
00219   
00220   cli->argc = argc;
00221   cli->argv = argv;
00222   {
00223     char *slash = strrchr(argv[0], '/');
00224     cli->program_name = slash ? slash + 1 : argv[0];
00225   }
00226   cli->error_handler = 0;
00227   
00228   for (i = 0; i < 256; i++)
00229     cli->option_class[i] = 0;
00230   cli->option_class['-'] = Clp_Short;
00231   cli->both_short_and_long = 0;
00232   
00233   cli->is_short = 0;
00234   cli->whole_negated = 0;
00235   
00236   cli->option_processing = 1;
00237   cli->current_option = 0;
00238   
00239   /* Add default type parsers */
00240   Clp_AddType(clp, Clp_ArgString, 0, parse_string, 0);
00241   Clp_AddType(clp, Clp_ArgStringNotOption, Clp_DisallowOptions, parse_string, 0);
00242   Clp_AddType(clp, Clp_ArgInt, 0, parse_int, 0);
00243   Clp_AddType(clp, Clp_ArgUnsigned, 0, parse_int, (void *)cli);
00244   Clp_AddType(clp, Clp_ArgBool, 0, parse_bool, 0);
00245   Clp_AddType(clp, Clp_ArgDouble, 0, parse_double, 0);
00246   return clp;
00247   
00248  failed:
00249   if (cli && cli->argtype) free(cli->argtype);
00250   if (cli) free(cli);
00251   if (clp) free(clp);
00252   if (lmm) free(lmm);
00253   return 0;
00254 }
00255 
00256 void
00257 Clp_DeleteParser(Clp_Parser *clp)
00258      /* Destroys the Clp_Parser `clp' and any associated memory allocated by
00259         CLP */
00260 {
00261   int i;
00262   Clp_Internal *cli;
00263   if (!clp) return;
00264   
00265   cli = clp->internal;
00266   
00267   /* get rid of any string list types */
00268   for (i = 0; i < cli->nargtype; i++)
00269     if (cli->argtype[i].func == parse_string_list) {
00270       Clp_StringList *clsl = (Clp_StringList *)cli->argtype[i].thunk;
00271       free(clsl->items);
00272       free(clsl->long_min_match);
00273       free(clsl);
00274     }
00275   
00276   free(cli->argtype);
00277   free(cli->long_min_match);
00278   free(cli);
00279   free(clp);
00280 }
00281 
00282 
00283 int
00284 Clp_SetOptionProcessing(Clp_Parser *clp, int option_processing)
00285      /* Sets whether command line arguments are parsed (looking for options)
00286         at all. Each parser starts out with OptionProcessing true. Returns old
00287         value. */
00288 {
00289   Clp_Internal *cli = clp->internal;
00290   int old = cli->option_processing;
00291   cli->option_processing = option_processing;
00292   return old;
00293 }
00294 
00295 
00296 Clp_ErrorHandler
00297 Clp_SetErrorHandler(Clp_Parser *clp, void (*error_handler)(char *))
00298      /* Sets a hook function to be called before Clp_OptionError
00299         prints anything. 0 means nothing will be called. */
00300 {
00301   Clp_Internal *cli = clp->internal;
00302   Clp_ErrorHandler old = cli->error_handler;
00303   cli->error_handler = error_handler;
00304   return old;
00305 }
00306 
00307 
00308 int
00309 Clp_SetOptionChar(Clp_Parser *clp, int c, int option_type)
00310      /* Determines how clp will deal with short options.
00311         option_type must be a sum of:
00312 
00313         0 == Clp_NotOption `character' isn't an option.
00314         Clp_Short       `character' introduces a list of short options.
00315         Clp_Long        `character' introduces a long option.
00316         Clp_ShortNegated `character' introduces a negated list of
00317                         short options.
00318         Clp_LongNegated `character' introduces a negated long option.
00319         Clp_LongImplicit `character' introduces a long option, and *is part
00320                         of the long option itself*.
00321 
00322         Some values are not allowed (Clp_Long | Clp_LongNegated isn't allowed,
00323         for instance). c=0 means ALL characters are that type. Returns 0 on
00324         failure (you gave an illegal option_type), 1 on success. */
00325 {
00326   int i;
00327   Clp_Internal *cli = clp->internal;
00328   
00329   if (option_type < 0 || option_type >= 2*Clp_LongImplicit
00330       || ((option_type & Clp_Short) && (option_type & Clp_ShortNegated))
00331       || ((option_type & Clp_Long) && (option_type & Clp_LongNegated))
00332       || ((option_type & Clp_LongImplicit) && (option_type & (Clp_Short | Clp_ShortNegated | Clp_Long | Clp_LongNegated))))
00333     return 0;
00334   
00335   if (c == 0)
00336     for (i = 1; i < 256; i++)
00337       cli->option_class[i] = option_type;
00338   else
00339     cli->option_class[c] = option_type;
00340 
00341   /* If an option character can introduce either short or long options, then
00342      we need to fix up the long_min_match values. We may have set the
00343      long_min_match for option `--abcde' to 1, if no other option starts with
00344      `a'. But if `-' can introduce either a short option or a long option, AND
00345      a short option `-a' exists, then the long_min_match for `--abcde' must be
00346      set to 2! */
00347   if (!cli->both_short_and_long) {
00348     int either_short = option_type & (Clp_Short | Clp_ShortNegated);
00349     int either_long = option_type & (Clp_Long | Clp_LongNegated);
00350     if (either_short && either_long) {
00351       unsigned char have_short[257];
00352       for (i = 0; i < 256; i++)
00353         have_short[i] = 0;
00354       for (i = 0; i < cli->nopt; i++)
00355         have_short[cli->opt[i].short_name] = 1;
00356       for (i = 0; i < cli->nopt; i++)
00357         if (cli->opt[i].long_name && cli->long_min_match[i].pos == 1) {
00358           /* if `--Cxxxx's short name is `-C', keep long_min_match == 1 */
00359           unsigned char first = (unsigned char)cli->opt[i].long_name[0];
00360           if (have_short[first] && first != cli->opt[i].short_name)
00361             cli->long_min_match[i].pos++;
00362         }
00363       cli->both_short_and_long = 1;
00364     }
00365   }
00366   
00367   return 1;
00368 }
00369 
00370 
00371 /*******
00372  * functions for Clp_Option lists
00373  **/
00374 
00375 static int
00376 min_different_chars(char *s, char *t)
00377      /* Returns the minimum number of characters required to distinguish
00378         s from t.
00379         If s is shorter than t, returns strlen(s). */
00380 {
00381   char *sfirst = s;
00382   while (*s && *t && *s == *t)
00383     s++, t++;
00384   if (!*s)
00385     return s - sfirst;
00386   else
00387     return s - sfirst + 1;
00388 }
00389 
00390 static int
00391 calculate_long_min_match(int nopt, Clp_Option *opt, int which,
00392                          int flags, int flags_value)
00393 {
00394   int j, lmm = 1;
00395   
00396   for (j = 0; j < nopt; j++)
00397     if (opt[j].long_name
00398         && (opt[j].flags & flags) == flags_value
00399         && opt[which].option_id != opt[j].option_id
00400         && strncmp(opt[which].long_name, opt[j].long_name, lmm) == 0)
00401       lmm = min_different_chars(opt[which].long_name, opt[j].long_name);
00402   
00403   return lmm;
00404 }
00405 
00406 /* the ever-glorious argcmp */
00407 
00408 static int
00409 argcmp(const char *ref, const char *arg, int min_match)
00410      /* Returns 0 if ref and arg don't match.
00411         Returns -1 if ref and arg match, but fewer than min_match characters.
00412         Returns len if ref and arg match min_match or more characters;
00413         len is the number of charcters that matched.
00414         
00415         Examples:
00416         argcmp("x", "y", 1)     -->  0  / just plain wrong
00417         argcmp("a", "ax", 1)    -->  0  / ...even though min_match == 1
00418                                         and the 1st chars match
00419         argcmp("box", "bo", 3)  --> -1  / ambiguous
00420         argcmp("cat", "c=3", 1) -->  1  / handles = arguments
00421         */
00422 {
00423   const char *refstart = ref;
00424   while (*ref && *arg && *arg != '=' && *ref == *arg)
00425     ref++, arg++;
00426   if (*arg && *arg != '=')
00427     return 0;
00428   else if (ref - refstart < min_match)
00429     return -1;
00430   else
00431     return ref - refstart;
00432 }
00433 
00434 static int
00435 find_prefix_opt(const char *arg, int nopt, Clp_Option *opt,
00436                 Clp_LongMinMatch *lmmvec,
00437                 int *ambiguous, int *ambiguous_values, int negated)
00438      /* Looks for an unambiguous match of `arg' against one of the long
00439         options in `opt'. Returns positive if it finds one; otherwise, returns
00440         -1 and possibly changes `ambiguous' and `ambiguous_values' to keep
00441         track of at most MAX_AMBIGUOUS_VALUES possibilities. */
00442 {
00443   int i;
00444   for (i = 0; i < nopt; i++) {
00445     int len, lmm;
00446     if (!opt[i].long_name
00447         || (negated && !TEST(&opt[i], Clp_Negate))
00448         || (!negated && TEST(&opt[i], Clp_OnlyNegated)))
00449       continue;
00450     
00451     lmm = (negated ? lmmvec[i].neg : lmmvec[i].pos);
00452     len = argcmp(opt[i].long_name, arg, lmm);
00453     if (len > 0)
00454       return i;
00455     else if (len < 0) {
00456       if (*ambiguous < MAX_AMBIGUOUS_VALUES)
00457         ambiguous_values[*ambiguous] = i;
00458       (*ambiguous)++;
00459     }
00460   }
00461   return -1;
00462 }
00463 
00464 
00465 /*****
00466  * Argument parsing
00467  **/
00468 
00469 int
00470 Clp_AddType(Clp_Parser *clp, int type_id, int flags,
00471             Clp_ArgParseFunc func, void *thunk)
00472      /* Add a argument parser for type_id to the Clp_Parser. When an argument
00473         arg for Clp_Option opt is being processed, the parser routines will
00474         call (*func)(clp, opt, arg, thunk, complain)
00475         where complain is 1 if the routine should report errors, or 0 if it
00476         should fail silently.
00477         Returns 1 on success, 0 if memory allocation fails or the arguments
00478         are bad. */
00479 {
00480   int i;
00481   Clp_Internal *cli = clp->internal;
00482   Clp_ArgType *new_argtype;
00483   int nargtype = cli->nargtype;
00484   assert(nargtype);
00485   
00486   if (type_id <= 0 || !func) return 0;
00487   
00488   while (nargtype <= type_id)
00489     nargtype *= 2;
00490   new_argtype = (Clp_ArgType *)
00491     realloc(cli->argtype, sizeof(Clp_ArgType) * nargtype);
00492   if (!new_argtype) return 0;
00493   cli->argtype = new_argtype;
00494   
00495   for (i = cli->nargtype; i < nargtype; i++)
00496     cli->argtype[i].func = 0;
00497   cli->nargtype = nargtype;
00498   
00499   cli->argtype[type_id].func = func;
00500   cli->argtype[type_id].flags = flags;
00501   cli->argtype[type_id].thunk = thunk;
00502   return 1;
00503 }
00504 
00505 
00506 /*******
00507  * Default argument parsers
00508  **/
00509 
00510 static int
00511 parse_string(Clp_Parser *clp, const char *arg, int complain, void *thunk)
00512 {
00513   clp->val.s = (char *)arg;
00514   return 1;
00515 }
00516 
00517 static int
00518 parse_int(Clp_Parser *clp, const char *arg, int complain, void *thunk)
00519 {
00520   char *val;
00521   int base = 10;
00522   if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) {
00523     base = 16;
00524     arg += 2;
00525   }
00526   
00527   if (thunk != 0) {             /* unsigned */
00528 #if HAVE_STRTOUL
00529     clp->val.u = strtoul(arg, &val, base);
00530 #else
00531     /* don't bother trying to do it right */
00532     clp->val.u = strtol(arg, &val, base);
00533 #endif
00534   } else
00535     clp->val.i = strtol(arg, &val, base);
00536   if (*arg != 0 && *val == 0)
00537     return 1;
00538   else if (complain) {
00539     const char *message = thunk != 0
00540       ? "`%O' expects a nonnegative integer, not `%s'"
00541       : "`%O' expects an integer, not `%s'";
00542     if (base == 16) arg -= 2;
00543     return Clp_OptionError(clp, message, arg);
00544   } else
00545     return 0;
00546 }
00547 
00548 static int
00549 parse_double(Clp_Parser *clp, const char *arg, int complain, void *thunk)
00550 {
00551   char *val;
00552   clp->val.d = strtod(arg, &val);
00553   if (*arg != 0 && *val == 0)
00554     return 1;
00555   else if (complain)
00556     return Clp_OptionError(clp, "`%O' expects a real number, not `%s'", arg);
00557   else
00558     return 0;
00559 }
00560 
00561 static int
00562 parse_bool(Clp_Parser *clp, const char *arg, int complain, void *thunk)
00563 {
00564   int i;
00565   char lcarg[6];
00566   if (strlen(arg) > 5 || strchr(arg, '=') != 0)
00567     goto error;
00568   
00569   for (i = 0; arg[i] != 0; i++)
00570     lcarg[i] = tolower(arg[i]);
00571   lcarg[i] = 0;
00572   
00573   if (argcmp("yes", lcarg, 1) > 0
00574       || argcmp("true", lcarg, 1) > 0
00575       || argcmp("1", lcarg, 1) > 0) {
00576     clp->val.i = 1;
00577     return 1;
00578   } else if (argcmp("no", lcarg, 1) > 0
00579              || argcmp("false", lcarg, 1) > 0
00580              || argcmp("1", lcarg, 1) > 0) {
00581     clp->val.i = 0;
00582     return 1;
00583   }
00584   
00585  error:
00586   if (complain)
00587     Clp_OptionError(clp, "`%O' expects a true-or-false value, not `%s'", arg);
00588   return 0;
00589 }
00590 
00591 
00592 /*****
00593  * Clp_AddStringListType
00594  **/
00595 
00596 static int
00597 parse_string_list(Clp_Parser *clp, const char *arg, int complain, void *thunk)
00598 {
00599   Clp_StringList *sl = (Clp_StringList *)thunk;
00600   int index, ambiguous = 0;
00601   int ambiguous_values[MAX_AMBIGUOUS_VALUES + 1];
00602   
00603   /* actually look for a string value */
00604   index = find_prefix_opt
00605     (arg, sl->nitems, sl->items, sl->long_min_match,
00606      &ambiguous, ambiguous_values, 0);
00607   if (index >= 0) {
00608     clp->val.i = sl->items[index].option_id;
00609     return 1;
00610   }
00611   
00612   if (sl->allow_int) {
00613     if (parse_int(clp, arg, 0, 0))
00614       return 1;
00615   }
00616   
00617   if (complain) {
00618     char *complaint = (ambiguous ? "an ambiguous" : "not a valid");
00619     if (!ambiguous) {
00620       ambiguous = sl->nitems_invalid_report;
00621       for (index = 0; index < ambiguous; index++)
00622         ambiguous_values[index] = index;
00623     }
00624     return ambiguity_error
00625       (clp, ambiguous, ambiguous_values, sl->items, "",
00626        "`%s' is %s argument to `%O'", arg, complaint);
00627   } else
00628     return 0;
00629 }
00630 
00631 
00632 int
00633 finish_string_list(Clp_Parser *clp, int type_id, int flags,
00634                    Clp_Option *items, int nitems, int itemscap)
00635 {
00636   int i;
00637   Clp_StringList *clsl = (Clp_StringList *)malloc(sizeof(Clp_StringList));
00638   Clp_LongMinMatch *lmm = (Clp_LongMinMatch *)malloc(sizeof(Clp_LongMinMatch) * nitems);
00639   if (!clsl || !lmm) goto error;
00640   
00641   clsl->items = items;
00642   clsl->long_min_match = lmm;
00643   clsl->nitems = nitems;
00644   clsl->allow_int = (flags & Clp_AllowNumbers) != 0;
00645   
00646   if (nitems < MAX_AMBIGUOUS_VALUES && nitems < itemscap && clsl->allow_int) {
00647     items[nitems].long_name = "any integer";
00648     clsl->nitems_invalid_report = nitems + 1;
00649   } else if (nitems > MAX_AMBIGUOUS_VALUES + 1)
00650     clsl->nitems_invalid_report = MAX_AMBIGUOUS_VALUES + 1;
00651   else
00652     clsl->nitems_invalid_report = nitems;
00653   
00654   for (i = 0; i < nitems; i++)
00655     lmm[i].pos = calculate_long_min_match(nitems, items, i, 0, 0);
00656   
00657   if (Clp_AddType(clp, type_id, 0, parse_string_list, clsl))
00658     return 1;
00659 
00660  error:
00661   if (clsl) free(clsl);
00662   if (lmm) free(lmm);
00663   return 0;
00664 }
00665 
00666 int
00667 Clp_AddStringListType(Clp_Parser *clp, int type_id, int flags, ...)
00668      /* An easy way to add new types to clp.
00669         Call like this:
00670         Clp_AddStringListType
00671           (clp, type_id, flags,
00672            char *s_1, int value_1, ..., char *s_n, int value_n, 0);
00673 
00674         Defines type_id as a type in clp.
00675         This type accepts any of the strings s_1, ..., s_n
00676         (or unambiguous abbreviations thereof);
00677         if argument s_i is given, value_i is stored in clp->val.i.
00678         If Clp_AllowNumbers is set in flags,
00679         explicit integers are also allowed.
00680 
00681         Returns 1 on success, 0 on memory allocation errors. */
00682 {
00683   int nitems = 0;
00684   int itemscap = 5;
00685   Clp_Option *items = (Clp_Option *)malloc(sizeof(Clp_Option) * itemscap);
00686   
00687   va_list val;
00688   va_start(val, flags);
00689   
00690   if (!items) goto error;
00691   
00692   /* slurp up the arguments */
00693   while (1) {
00694     int value;
00695     char *name = va_arg(val, char *);
00696     if (!name) break;
00697     value = va_arg(val, int);
00698     
00699     if (nitems >= itemscap) {
00700       Clp_Option *new_items;
00701       itemscap *= 2;
00702       new_items = (Clp_Option *)realloc(items, sizeof(Clp_Option) * itemscap);
00703       if (!new_items) goto error;
00704       items = new_items;
00705     }
00706     
00707     items[nitems].long_name = name;
00708     items[nitems].option_id = value;
00709     items[nitems].flags = 0;
00710     nitems++;
00711   }
00712 
00713   va_end(val);
00714   if (finish_string_list(clp, type_id, flags, items, nitems, itemscap))
00715     return 1;
00716   
00717  error:
00718   va_end(val);
00719   if (items) free(items);
00720   return 0;
00721 }
00722 
00723 
00724 int
00725 Clp_AddStringListTypeVec(Clp_Parser *clp, int type_id, int flags,
00726                          int nitems, char **strings, int *values)
00727      /* An alternate way to make a string list type. See Clp_AddStringListType
00728         for the basics; this coalesces the strings and values into two arrays,
00729         rather than spreading them out into a variable argument list. */
00730 {
00731   int i;
00732   int itemscap = (nitems < 5 ? 5 : nitems);
00733   Clp_Option *items = (Clp_Option *)malloc(sizeof(Clp_Option) * itemscap);
00734   if (!items) return 0;
00735   
00736   /* copy over items */
00737   for (i = 0; i < nitems; i++) {
00738     items[i].long_name = strings[i];
00739     items[i].option_id = values[i];
00740     items[i].flags = 0;
00741   }
00742   
00743   if (finish_string_list(clp, type_id, flags, items, nitems, itemscap))
00744     return 1;
00745   else {
00746     free(items);
00747     return 0;
00748   }
00749 }
00750 
00751 
00752 /*******
00753  * Returning information
00754  **/
00755 
00756 char *
00757 Clp_ProgramName(Clp_Parser *clp)
00758 {
00759   return clp->internal->program_name;
00760 }
00761 
00762 
00763 /******
00764  * Clp_ParserStates
00765  **/
00766 
00767 Clp_ParserState *
00768 Clp_NewParserState(void)
00769 {
00770   return (Clp_ParserState *)malloc(sizeof(Clp_ParserState));
00771 }
00772 
00773 void
00774 Clp_DeleteParserState(Clp_ParserState *save)
00775 {
00776   free(save);
00777 }
00778 
00779 
00780 void
00781 Clp_SaveParser(Clp_Parser *clp, Clp_ParserState *save)
00782      /* Saves parser position in save */
00783 {
00784   Clp_Internal *cli = clp->internal;
00785   save->argv = cli->argv;
00786   save->argc = cli->argc;
00787   memcpy(save->option_chars, cli->option_chars, 3);
00788   save->text = cli->text;
00789   save->is_short = cli->is_short;
00790   save->whole_negated = cli->whole_negated;
00791 }
00792 
00793 
00794 void
00795 Clp_RestoreParser(Clp_Parser *clp, Clp_ParserState *save)
00796      /* Restores parser position from save */
00797 {
00798   Clp_Internal *cli = clp->internal;
00799   cli->argv = save->argv;
00800   cli->argc = save->argc;
00801   memcpy(cli->option_chars, save->option_chars, 3);
00802   cli->text = save->text;
00803   cli->is_short = save->is_short;
00804   cli->whole_negated = save->whole_negated;
00805 }
00806 
00807 
00808 /*******
00809  * Clp_Next and its helpers
00810  **/
00811 
00812 static void
00813 set_option_text(Clp_Internal *cli, char *text, int n_option_chars)
00814 {
00815   char *option_chars = cli->option_chars;
00816   assert(n_option_chars < 3);
00817   
00818   while (n_option_chars-- > 0)
00819     *option_chars++ = *text++;
00820   *option_chars = 0;
00821   
00822   cli->text = text;
00823 }
00824 
00825 
00826 static int
00827 next_argument(Clp_Parser *clp, int want_argument)
00828      /* Moves clp to the next argument.
00829         Returns 1 if it finds another option.
00830         Returns 0 if there aren't any more arguments.
00831         Returns 0, sets clp->have_arg = 1, and sets clp->arg to the argument
00832         if the next argument isn't an option.
00833         If want_argument > 0, it'll look for an argument.
00834         want_argument == 1: Accept arguments that start with Clp_NotOption
00835                 or Clp_LongImplicit.
00836         want_argument == 2: Accept ALL arguments.
00837         
00838         Where is the option stored when this returns?
00839         Well, cli->argv[0] holds the whole of the next command line argument.
00840         cli->option_chars holds a string: what characters began the option?
00841         It is generally "-" or "--".
00842         cli->text holds the text of the option:
00843         for short options, cli->text[0] is the relevant character;
00844         for long options, cli->text holds the rest of the option. */
00845 {
00846   Clp_Internal *cli = clp->internal;
00847   char *text;
00848   int option_class;
00849 
00850   /* clear relevant flags */
00851   clp->have_arg = 0;
00852   clp->arg = 0;
00853   cli->could_be_short = 0;
00854   
00855   /* if we're in a string of short options, move up one char in the string */
00856   if (cli->is_short) {
00857     ++cli->text;
00858     if (cli->text[0] == 0)
00859       cli->is_short = 0;
00860     else if (want_argument > 0) {
00861       /* handle -O[=]argument case */
00862       clp->have_arg = 1;
00863       if (cli->text[0] == '=')
00864         clp->arg = cli->text + 1;
00865       else
00866         clp->arg = cli->text;
00867       cli->is_short = 0;
00868       return 0;
00869     }
00870   }
00871   
00872   /* if in short options, we're all set */
00873   if (cli->is_short)
00874     return 1;
00875   
00876   /** if not in short options, move to the next argument **/
00877   cli->whole_negated = 0;
00878   cli->text = 0;
00879   
00880   if (cli->argc <= 1)
00881     return 0;
00882   
00883   cli->argc--;
00884   cli->argv++;
00885   text = cli->argv[0];
00886   
00887   if (want_argument > 1)
00888     goto not_option;
00889   
00890   option_class = cli->option_class[ (unsigned char)text[0] ];
00891   if (text[0] == '-' && text[1] == '-')
00892     option_class = Clp_DoubledLong;
00893   
00894   /* If this character could introduce either a short or a long option,
00895      try a long option first, but remember that short's a possibility for
00896      later. */
00897   if ((option_class & (Clp_Short | Clp_ShortNegated))
00898       && (option_class & (Clp_Long | Clp_LongNegated))) {
00899     option_class &= ~(Clp_Short | Clp_ShortNegated);
00900     if (text[1] != 0) cli->could_be_short = 1;
00901   }
00902   
00903   switch (option_class) {
00904     
00905    case Clp_Short:
00906     cli->is_short = 1;
00907     goto check_singleton;
00908     
00909    case Clp_ShortNegated:
00910     cli->is_short = 1;
00911     cli->whole_negated = 1;
00912     goto check_singleton;
00913     
00914    case Clp_Long:
00915     goto check_singleton;
00916     
00917    case Clp_LongNegated:
00918     cli->whole_negated = 1;
00919     goto check_singleton;
00920     
00921    check_singleton:
00922     /* For options introduced with one character, option-char,
00923        `[option-char]' alone is NOT an option. */
00924     if (text[1] == 0)
00925       goto not_option;
00926     set_option_text(cli, text, 1);
00927     break;
00928     
00929    case Clp_LongImplicit:
00930     /* LongImplict: option_chars == "" (since all chars are part of the
00931        option); restore head -> text of option */
00932     if (want_argument > 0)
00933       goto not_option;
00934     set_option_text(cli, text, 0);
00935     break;
00936     
00937    case Clp_DoubledLong:
00938     set_option_text(cli, text, 2);
00939     break;
00940     
00941    not_option: 
00942    case Clp_NotOption:
00943     cli->is_short = 0;
00944     clp->have_arg = 1;
00945     clp->arg = text;
00946     return 0;
00947     
00948    default:
00949     assert(0 && "misconfiguration");
00950     
00951   }
00952   
00953   return 1;
00954 }
00955 
00956 
00957 static void
00958 switch_to_short_argument(Clp_Parser *clp)
00959 {
00960   Clp_Internal *cli = clp->internal;
00961   const char *text = cli->argv[0];
00962   int option_class = cli->option_class[ (unsigned char)text[0] ];
00963   cli->is_short = 1;
00964   cli->whole_negated = (option_class & Clp_ShortNegated ? 1 : 0);
00965   set_option_text(cli, cli->argv[0], 1);
00966   assert(cli->could_be_short);
00967 }
00968 
00969 
00970 static Clp_Option *
00971 find_long(Clp_Parser *clp, char *arg)
00972      /* If arg corresponds to one of clp's options, finds that option &
00973         returns it. If any argument is given after an = sign in arg, sets
00974         clp->have_arg = 1 and clp->arg to that argument. Sets cli->ambiguous
00975         to 1 iff there was no match because the argument was ambiguous. */
00976 {
00977   Clp_Internal *cli = clp->internal;
00978   int value, len;
00979   Clp_Option *opt = cli->opt;
00980   int first_negative_ambiguous;
00981   
00982   /* Look for a normal option. */
00983   value = find_prefix_opt
00984     (arg, cli->nopt, opt, cli->long_min_match,
00985      &cli->ambiguous, cli->ambiguous_values, clp->negated);
00986   if (value >= 0)
00987     goto worked;
00988   
00989   /* If we can't find it, look for a negated option. */
00990   /* I know this is silly, but it makes me happy to accept
00991      --no-no-option as a double negative synonym for --option. :) */
00992   first_negative_ambiguous = cli->ambiguous;
00993   while (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-') {
00994     arg += 3;
00995     clp->negated = !clp->negated;
00996     value = find_prefix_opt
00997       (arg, cli->nopt, opt, cli->long_min_match,
00998        &cli->ambiguous, cli->ambiguous_values, clp->negated);
00999     if (value >= 0)
01000       goto worked;
01001   }
01002   
01003   /* No valid option was found; return 0. Mark the ambiguous values found
01004      through `--no' by making them negative. */
01005   {
01006     int i, max = cli->ambiguous;
01007     if (max > MAX_AMBIGUOUS_VALUES) max = MAX_AMBIGUOUS_VALUES;
01008     for (i = first_negative_ambiguous; i < max; i++)
01009       cli->ambiguous_values[i] = -cli->ambiguous_values[i] - 1;
01010     return 0;
01011   }
01012   
01013  worked:
01014   len = argcmp(opt[value].long_name, arg, cli->long_min_match[value].pos);
01015   if (arg[len] == '=') {
01016     clp->have_arg = 1;
01017     clp->arg = arg + len + 1;
01018   }
01019   return &opt[value];
01020 }
01021 
01022 
01023 static Clp_Option *
01024 find_short(Clp_Parser *clp, int short_name)
01025      /* If short_name corresponds to one of clp's options, returns it. */
01026 {
01027   Clp_Internal *cli = clp->internal;
01028   Clp_Option *opt = cli->opt;
01029   int i;
01030   
01031   for (i = 0; i < cli->nopt; i++)
01032     if (opt[i].short_name == short_name
01033         && (clp->negated ? TEST(&opt[i], Clp_Negate)
01034             : !TEST(&opt[i], Clp_OnlyNegated)))
01035       return &opt[i];
01036   
01037   return 0;
01038 }
01039 
01040 
01041 int
01042 Clp_Next(Clp_Parser *clp)
01043      /* Gets and parses the next argument from the argument list.
01044         
01045         If there are no more arguments, returns Clp_Done.
01046         If the next argument isn't an option, returns Clp_NotOption;
01047         the argument is stored in clp->arg.
01048         If the next argument is an option, returns that option's option_id.
01049         
01050         If the next argument is an unrecognizable or ambiguous option,
01051         an error message is given and Clp_BadOption is returned.
01052         
01053         If an option has an argument, that argument is stored in clp->arg
01054         and clp->have_arg is set to 1.
01055         Furthermore, that argument's parsed value (according to its type)
01056         is stored in the clp->val union.
01057         
01058         If an option needs an argument but isn't given one;
01059         if it doesn't need an argument but IS given one;
01060         or if the argument is the wrong type,
01061         an error message is given and Clp_BadOption is returned. */
01062 {
01063   Clp_Internal *cli = clp->internal;
01064   Clp_Option *opt;
01065   Clp_ParserState clpsave;
01066   int complain;
01067   
01068   /** Set up clp **/
01069   cli->current_option = 0;
01070   cli->ambiguous = 0;
01071   
01072   /** Get the next argument or option **/
01073   if (!next_argument(clp, cli->option_processing ? 0 : 2))
01074     return clp->have_arg ? Clp_NotOption : Clp_Done;
01075   
01076   clp->negated = cli->whole_negated;
01077   if (cli->is_short)
01078     opt = find_short(clp, cli->text[0]);
01079   else
01080     opt = find_long(clp, cli->text);
01081   
01082   /** If there's ambiguity between long & short options, and we couldn't find
01083       a long option, look for a short option **/
01084   if (!opt && cli->could_be_short) {
01085     switch_to_short_argument(clp);
01086     opt = find_short(clp, cli->text[0]);
01087   }
01088   
01089   /** If we didn't find an option... **/
01090   if (!opt || (clp->negated && !TEST(opt, Clp_Negate))) {
01091     
01092     /* default processing for the "--" option: turn off option processing
01093        and return the next argument */
01094     if (strcmp(cli->argv[0], "--") == 0) {
01095       Clp_SetOptionProcessing(clp, 0);
01096       return Clp_Next(clp);
01097     }
01098     
01099     /* otherwise, report some error or other */
01100     if (cli->ambiguous)
01101       ambiguity_error(clp, cli->ambiguous, cli->ambiguous_values,
01102                       cli->opt, cli->option_chars,
01103                       "option `%s%s' is ambiguous",
01104                       cli->option_chars, cli->text);
01105     else if (cli->is_short && !cli->could_be_short)
01106       Clp_OptionError(clp, "unrecognized option `%s%c'",
01107                       cli->option_chars, cli->text[0]);
01108     else
01109       Clp_OptionError(clp, "unrecognized option `%s%s'",
01110                       cli->option_chars, cli->text);
01111     return Clp_BadOption;
01112   }
01113   
01114   /** Set the current option **/
01115   cli->current_option = opt;
01116   cli->current_short = cli->is_short;
01117   cli->negated_by_no = clp->negated && !cli->whole_negated;
01118   
01119   /** The no-argument (or should-have-no-argument) case **/
01120   if (clp->negated || !TEST(opt, Clp_AnyArgument)) {
01121     if (clp->have_arg) {
01122       Clp_OptionError(clp, "`%O' can't take an argument");
01123       return Clp_BadOption;
01124     } else
01125       return opt->option_id;
01126   }
01127   
01128   /** Get an argument if we need one, or if it's optional **/
01129   /* Sanity-check the argument type. */
01130   if (opt->arg_type <= 0 || opt->arg_type >= cli->nargtype
01131       || cli->argtype[ opt->arg_type ].func == 0)
01132     return Clp_Error;
01133   
01134   /* complain == 1 only if the argument was explicitly given,
01135      or it is mandatory. */
01136   complain = (clp->have_arg != 0) || TEST(opt, Clp_Mandatory);
01137   Clp_SaveParser(clp, &clpsave);
01138   
01139   if (TEST(opt, Clp_Mandatory) && !clp->have_arg) {
01140     /* Mandatory argument case */
01141     /* Allow arguments to options to start with a dash, but only if the
01142        argument type allows it by not setting Clp_DisallowOptions */
01143     int disallow = TEST(&cli->argtype[opt->arg_type], Clp_DisallowOptions);
01144     next_argument(clp, disallow ? 1 : 2);
01145     if (!clp->have_arg) {
01146       int got_option = cli->text != 0;
01147       Clp_RestoreParser(clp, &clpsave);
01148       if (got_option)
01149         Clp_OptionError(clp, "`%O' requires a non-option argument");
01150       else
01151         Clp_OptionError(clp, "`%O' requires an argument");
01152       return Clp_BadOption;
01153     }
01154     
01155   } else if (cli->is_short && !clp->have_arg && cli->text[1] != 0)
01156     /* The -[option]argument case:
01157        Assume that the rest of the current string is the argument. */
01158     next_argument(clp, 1);
01159   
01160   /** Parse the argument **/
01161   if (clp->have_arg) {
01162     Clp_ArgType *atr = &cli->argtype[ opt->arg_type ];
01163     if (atr->func(clp, clp->arg, complain, atr->thunk) <= 0) {
01164       /* parser failed */
01165       clp->have_arg = 0;
01166       if (TEST(opt, Clp_Mandatory))
01167         return Clp_BadOption;
01168       else
01169         Clp_RestoreParser(clp, &clpsave);
01170     }
01171   }
01172   
01173   return opt->option_id;
01174 }
01175 
01176 
01177 char *
01178 Clp_Shift(Clp_Parser *clp, int allow_dashes)
01179      /* Returns the next argument from the argument list without parsing it.
01180         If there are no more arguments, returns 0. */
01181 {
01182   Clp_ParserState clpsave;
01183   Clp_SaveParser(clp, &clpsave);
01184   next_argument(clp, allow_dashes ? 2 : 1);
01185   if (!clp->have_arg)
01186     Clp_RestoreParser(clp, &clpsave);
01187   return clp->arg;
01188 }
01189 
01190 
01191 /*******
01192  * Clp_OptionError
01193  **/
01194 
01195 typedef struct Clp_BuildString {
01196   char *text;
01197   char *pos;
01198   int capacity;
01199   int bad;
01200 } Clp_BuildString;
01201 
01202 static Clp_BuildString *
01203 new_build_string(void)
01204 {
01205   Clp_BuildString *bs = (Clp_BuildString *)malloc(sizeof(Clp_BuildString));
01206   if (!bs) goto bad;
01207   bs->text = (char *)malloc(256);
01208   if (!bs->text) goto bad;
01209   bs->pos = bs->text;
01210   bs->capacity = 256;
01211   bs->bad = 0;
01212   return bs;
01213   
01214  bad:
01215   if (bs) free(bs);
01216   return 0;
01217 }
01218 
01219 static void
01220 free_build_string(Clp_BuildString *bs)
01221 {
01222   if (bs) free(bs->text);
01223   free(bs);
01224 }
01225 
01226 static int
01227 grow_build_string(Clp_BuildString *bs, int want)
01228 {
01229   char *new_text;
01230   int ipos = bs->pos - bs->text;
01231   int new_capacity = bs->capacity;
01232   while (want >= new_capacity)
01233     new_capacity *= 2;
01234   new_text = (char *)realloc(bs->text, new_capacity);
01235   if (!new_text) {
01236     bs->bad = 1;
01237     return 0;
01238   } else {
01239     bs->text = new_text;
01240     bs->pos = bs->text + ipos;
01241     bs->capacity = new_capacity;
01242     return 1;
01243   }
01244 }
01245 
01246 #define ENSURE_BUILD_STRING(bs, space) \
01247   ((((bs)->pos - (bs)->text) + (space) >= (bs)->capacity)               \
01248    || grow_build_string((bs), ((bs)->pos - (bs)->text) + (space)))
01249 
01250 static void
01251 append_build_string(Clp_BuildString *bs, const char *s, int l)
01252 {
01253   if (l < 0) l = strlen(s);
01254   if (ENSURE_BUILD_STRING(bs, l)) {
01255     memcpy(bs->pos, s, l);
01256     bs->pos += l;
01257   }
01258 }
01259 
01260 
01261 static Clp_BuildString *
01262 Clp_VaOptionError(Clp_Parser *clp, Clp_BuildString *bs,
01263                   const char *fmt, va_list val)
01264      /* Reports an error for parser clp. Allowable % format characters are:
01265         
01266         s       Print a string from the argument list.
01267         c       Print an int from the argument list as a character.
01268         d       Print an int from the argument list.
01269         O       Print the name of the current option;
01270                 take nothing from the argument list.
01271                 
01272         No field specifications or flags are allowed. Always returns 0. */
01273 {
01274   Clp_Internal *cli = clp->internal;
01275   const char *percent;
01276   
01277   if (!bs) bs = new_build_string();
01278   if (!bs) return 0;
01279   append_build_string(bs, cli->program_name, -1);
01280   append_build_string(bs, ": ", 2);
01281   
01282   for (percent = strchr(fmt, '%'); percent; percent = strchr(fmt, '%')) {
01283     append_build_string(bs, fmt, percent - fmt);
01284     switch (*++percent) {
01285       
01286      case 's': {
01287        char *s = va_arg(val, char *);
01288        if (s) append_build_string(bs, s, -1);
01289        else append_build_string(bs, "(null)", 6);
01290        break;
01291      }
01292      
01293      case 'c': {
01294        int c = va_arg(val, int);
01295        if (ENSURE_BUILD_STRING(bs, 4)) {
01296          if (c >= 32 && c <= 126)
01297            *bs->pos++ = c;
01298          else if (c < 32) {
01299            *bs->pos++ = '^';
01300            *bs->pos++ = c + 64;
01301          } else {
01302            sprintf(bs->pos, "\\%03o", c);
01303            bs->pos += 4;
01304          }
01305        }
01306        break;
01307      }
01308      
01309      case 'd': {
01310        int d = va_arg(val, int);
01311        if (ENSURE_BUILD_STRING(bs, 32)) {
01312          sprintf(bs->pos, "%d", d);
01313          bs->pos = strchr(bs->pos, 0);
01314        }
01315        break;
01316      }
01317      
01318      case 'O': {
01319        Clp_Option *opt = cli->current_option;
01320        if (!opt)
01321          append_build_string(bs, "(no current option!)", -1);
01322        else if (cli->current_short) {
01323          append_build_string(bs, cli->option_chars, -1);
01324          if (ENSURE_BUILD_STRING(bs, 1))
01325            *bs->pos++ = opt->short_name;
01326        } else if (cli->negated_by_no) {
01327          append_build_string(bs, cli->option_chars, -1);
01328          append_build_string(bs, "no-", 3);
01329          append_build_string(bs, opt->long_name, -1);
01330        } else {
01331          append_build_string(bs, cli->option_chars, -1);
01332          append_build_string(bs, opt->long_name, -1);
01333        }
01334        break;
01335      }
01336      
01337      case '%':
01338       if (ENSURE_BUILD_STRING(bs, 1))
01339         *bs->pos++ = '%';
01340       break;
01341       
01342      default:
01343       if (ENSURE_BUILD_STRING(bs, 2)) {
01344         *bs->pos++ = '%';
01345         *bs->pos++ = *percent;
01346       }
01347       break;
01348       
01349     }
01350     fmt = ++percent;
01351   }
01352   
01353   append_build_string(bs, fmt, -1);
01354   append_build_string(bs, "\n", 1);
01355   
01356   return bs;
01357 }
01358 
01359 static void
01360 do_error(Clp_Parser *clp, Clp_BuildString *bs)
01361 {
01362   char *text;
01363   if (bs && !bs->bad) {
01364     *bs->pos = 0;
01365     text = bs->text;
01366   } else
01367     text = "out of memory\n";
01368   
01369   if (clp->internal->error_handler != 0)
01370     (*clp->internal->error_handler)(text);
01371   else
01372     fputs(text, stderr);
01373 }
01374 
01375 int
01376 Clp_OptionError(Clp_Parser *clp, const char *fmt, ...)
01377 {
01378   Clp_BuildString *bs;
01379   va_list val;
01380   va_start(val, fmt);
01381   bs = Clp_VaOptionError(clp, 0, fmt, val);
01382   va_end(val);
01383   do_error(clp, bs);
01384   free_build_string(bs);
01385   return 0;
01386 }
01387 
01388 static int
01389 ambiguity_error(Clp_Parser *clp, int ambiguous, int *ambiguous_values,
01390                 Clp_Option *opt, const char *prefix,
01391                 const char *fmt, ...)
01392 {
01393   Clp_BuildString *bs;
01394   int i;
01395   va_list val;
01396   va_start(val, fmt);
01397   bs = Clp_VaOptionError(clp, 0, fmt, val);
01398   if (!bs) goto done;
01399   
01400   append_build_string(bs, clp->internal->program_name, -1);
01401   append_build_string(bs, ": (Possibilities are", -1);
01402   
01403   for (i = 0; i < ambiguous && i < MAX_AMBIGUOUS_VALUES; i++) {
01404     int val = ambiguous_values[i];
01405     const char *no_dash = "";
01406     if (val < 0) val = -(val + 1), no_dash = "no-";
01407     if (i == 0)
01408       append_build_string(bs, " ", 1);
01409     else if (i == ambiguous - 1)
01410       append_build_string(bs, (i == 1 ? " and " : ", and "), -1);
01411     else
01412       append_build_string(bs, ", ", 2);
01413     append_build_string(bs, prefix, -1);
01414     append_build_string(bs, no_dash, -1);
01415     append_build_string(bs, opt[val].long_name, -1);
01416   }
01417   
01418   if (ambiguous > MAX_AMBIGUOUS_VALUES)
01419     append_build_string(bs, ", and others", -1);
01420   append_build_string(bs, ".)\n", -1);
01421   va_end(val);
01422   
01423  done:
01424   do_error(clp, bs);
01425   free_build_string(bs);
01426   return 0;
01427 }
01428 
01429 #ifdef __cplusplus
01430 }
01431 #endif
 

Powered by Plone

This site conforms to the following standards: