gifsicle  1.92
About: Gifsicle is a UNIX command-line tool for creating, editing, and getting information about GIF images and animations.
  Fossies Dox: gifsicle-1.92.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

clp.c
Go to the documentation of this file.
1 /* -*- related-file-name: "../include/lcdf/clp.h" -*- */
2 /* clp.c - Complete source code for CLP.
3  * This file is part of CLP, the command line parser package.
4  *
5  * Copyright (c) 1997-2019 Eddie Kohler, ekohler@gmail.com
6  *
7  * CLP is free software. It is distributed under the GNU General Public
8  * License, Version 2, or, alternatively and at your discretion, under the
9  * more permissive (BSD-like) Click LICENSE file as described below.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a
12  * copy of this software and associated documentation files (the
13  * "Software"), to deal in the Software without restriction, subject to the
14  * conditions listed in the Click LICENSE file, which is available in full at
15  * http://github.com/kohler/click/blob/master/LICENSE. The conditions
16  * include: you must preserve this copyright notice, and you cannot mention
17  * the copyright holders in advertising related to the Software without
18  * their permission. The Software is provided WITHOUT ANY WARRANTY, EXPRESS
19  * OR IMPLIED. This notice is a summary of the Click LICENSE file; the
20  * license in that file is binding. */
21 
22 #if HAVE_CONFIG_H
23 # include <config.h>
24 #endif
25 #include <lcdf/clp.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29 #include <assert.h>
30 #include <stdarg.h>
31 #include <ctype.h>
32 #if HAVE_SYS_TYPES_H
33 # include <sys/types.h>
34 #endif
35 #if HAVE_INTTYPES_H || !defined(HAVE_CONFIG_H)
36 # include <inttypes.h>
37 #endif
38 
39 /* By default, assume we have inttypes.h, strtoul, and uintptr_t. */
40 #if !defined(HAVE_STRTOUL) && !defined(HAVE_CONFIG_H)
41 # define HAVE_STRTOUL 1
42 #endif
43 #if defined(HAVE_INTTYPES_H) || !defined(HAVE_CONFIG_H)
44 # include <inttypes.h>
45 #endif
46 #if !defined(HAVE_UINTPTR_T) && defined(HAVE_CONFIG_H)
47 typedef unsigned long uintptr_t;
48 #endif
49 
50 #ifdef __cplusplus
51 extern "C" {
52 #endif
53 
54 
147 /* Option types for Clp_SetOptionChar */
148 #define Clp_DoubledLong (Clp_LongImplicit * 2)
149 
150 #define Clp_InitialValType 8
151 #define MAX_AMBIGUOUS_VALUES 4
152 
153 typedef struct {
154  int val_type;
156  int flags;
157  void *user_data;
158 } Clp_ValType;
159 
160 typedef struct {
161  unsigned ilong : 1;
162  unsigned ishort : 1;
163  unsigned imandatory : 1;
164  unsigned ioptional : 1;
165  unsigned ipos : 1;
166  unsigned ineg : 1;
167  unsigned iprefmatch : 1;
168  unsigned lmmpos_short : 1;
169  unsigned lmmneg_short : 1;
170  unsigned char ilongoff;
171  int lmmpos;
172  int lmmneg;
174 
175 
176 #define Clp_OptionCharsSize 5
177 
178 typedef struct {
179  int c;
180  int type;
181 } Clp_Oclass;
182 #define Clp_OclassSize 10
183 
184 typedef struct Clp_Internal {
185  const Clp_Option *opt;
187  int nopt;
188  unsigned opt_generation;
189 
191  int nvaltype;
192 
193  const char * const *argv;
194  int argc;
195 
197  int noclass;
198  int long1pos;
199  int long1neg;
200  int utf8;
201 
203  const char *xtext;
204 
205  const char *program_name;
206  void (*error_handler)(Clp_Parser *, const char *);
207 
210 
211  unsigned char is_short;
212  unsigned char whole_negated; /* true if negated by an option character */
213  unsigned char could_be_short;
214  unsigned char current_short;
215  unsigned char negated_by_no;
216 
219 } Clp_Internal;
220 
221 
223  const char * const *argv;
224  int argc;
225 
227  const char *xtext;
228 
230 
231  unsigned opt_generation;
233  unsigned char is_short;
234  unsigned char whole_negated;
235  unsigned char current_short;
236  unsigned char negated_by_no;
237 };
238 
239 
240 typedef struct Clp_StringList {
243  int nitems;
244 
245  unsigned char allow_int;
246  unsigned char val_long;
249 
250 
251 static const Clp_Option clp_option_sentinel[] = {
252  {"", 0, Clp_NotOption, 0, 0},
253  {"", 0, Clp_Done, 0, 0},
254  {"", 0, Clp_BadOption, 0, 0},
255  {"", 0, Clp_Error, 0, 0}
256 };
257 
258 
259 static int parse_string(Clp_Parser *, const char *, int, void *);
260 static int parse_int(Clp_Parser *, const char *, int, void *);
261 static int parse_bool(Clp_Parser *, const char *, int, void *);
262 static int parse_double(Clp_Parser *, const char *, int, void *);
263 static int parse_string_list(Clp_Parser *, const char *, int, void *);
264 
265 static int ambiguity_error(Clp_Parser *, int, int *, const Clp_Option *,
266  const Clp_InternOption *, const char *, const char *,
267  ...);
268 
269 
270 /*******
271  * utf8
272  **/
273 
274 #define U_REPLACEMENT 0xFFFD
275 
276 static char *
277 encode_utf8(char *s, int n, int c)
278 {
279  if (c < 0 || c >= 0x110000 || (c >= 0xD800 && c <= 0xDFFF))
280  c = U_REPLACEMENT;
281  if (c <= 0x7F && n >= 1)
282  *s++ = c;
283  else if (c <= 0x7FF && n >= 2) {
284  *s++ = 0xC0 | (c >> 6);
285  goto char1;
286  } else if (c <= 0xFFFF && n >= 3) {
287  *s++ = 0xE0 | (c >> 12);
288  goto char2;
289  } else if (n >= 4) {
290  *s++ = 0xF0 | (c >> 18);
291  *s++ = 0x80 | ((c >> 12) & 0x3F);
292  char2:
293  *s++ = 0x80 | ((c >> 6) & 0x3F);
294  char1:
295  *s++ = 0x80 | (c & 0x3F);
296  }
297  return s;
298 }
299 
300 static int
301 decode_utf8(const char *s, const char **cp)
302 {
303  int c;
304  if ((unsigned char) *s <= 0x7F) /* 1 byte: 0x000000-0x00007F */
305  c = *s++;
306  else if ((unsigned char) *s <= 0xC1) /* bad/overlong encoding */
307  goto replacement;
308  else if ((unsigned char) *s <= 0xDF) { /* 2 bytes: 0x000080-0x0007FF */
309  if ((s[1] & 0xC0) != 0x80) /* bad encoding */
310  goto replacement;
311  c = (*s++ & 0x1F) << 6;
312  goto char1;
313  } else if ((unsigned char) *s <= 0xEF) { /* 3 bytes: 0x000800-0x00FFFF */
314  if ((s[1] & 0xC0) != 0x80 /* bad encoding */
315  || (s[2] & 0xC0) != 0x80 /* bad encoding */
316  || ((unsigned char) *s == 0xE0 /* overlong encoding */
317  && (s[1] & 0xE0) == 0x80)
318  || ((unsigned char) *s == 0xED /* encoded surrogate */
319  && (s[1] & 0xE0) == 0xA0))
320  goto replacement;
321  c = (*s++ & 0x0F) << 12;
322  goto char2;
323  } else if ((unsigned char) *s <= 0xF4) { /* 4 bytes: 0x010000-0x10FFFF */
324  if ((s[1] & 0xC0) != 0x80 /* bad encoding */
325  || (s[2] & 0xC0) != 0x80 /* bad encoding */
326  || (s[3] & 0xC0) != 0x80 /* bad encoding */
327  || ((unsigned char) *s == 0xF0 /* overlong encoding */
328  && (s[1] & 0xF0) == 0x80)
329  || ((unsigned char) *s == 0xF4 /* encoded value > 0x10FFFF */
330  && (unsigned char) s[1] >= 0x90))
331  goto replacement;
332  c = (*s++ & 0x07) << 18;
333  c += (*s++ & 0x3F) << 12;
334  char2:
335  c += (*s++ & 0x3F) << 6;
336  char1:
337  c += (*s++ & 0x3F);
338  } else {
339  replacement:
340  c = U_REPLACEMENT;
341  for (s++; (*s & 0xC0) == 0x80; s++)
342  /* nothing */;
343  }
344  if (cp)
345  *cp = s;
346  return c;
347 }
348 
349 static int
350 utf8_charlen(const char *s)
351 {
352  const char *sout;
353  (void) decode_utf8(s, &sout);
354  return sout - s;
355 }
356 
357 static int
358 clp_utf8_charlen(const Clp_Internal *cli, const char *s)
359 {
360  return (cli->utf8 ? utf8_charlen(s) : 1);
361 }
362 
363 
364 /*******
365  * Clp_NewParser, etc.
366  **/
367 
368 static int
369 min_different_chars(const char *s, const char *t)
370  /* Returns the minimum number of bytes required to distinguish
371  s from t.
372  If s is shorter than t, returns strlen(s). */
373 {
374  const char *sfirst = s;
375  while (*s && *t && *s == *t)
376  s++, t++;
377  if (!*s)
378  return s - sfirst;
379  else
380  return s - sfirst + 1;
381 }
382 
383 static int
384 long_as_short(const Clp_Internal *cli, const Clp_Option *o,
385  Clp_InternOption *io, int failure)
386 {
387  if ((cli->long1pos || cli->long1neg) && io->ilong) {
388  const char *name = o->long_name + io->ilongoff;
389  if (cli->utf8) {
390  int c = decode_utf8(name, &name);
391  if (!*name && c && c != U_REPLACEMENT)
392  return c;
393  } else if (name[0] && !name[1])
394  return (unsigned char) name[0];
395  }
396  return failure;
397 }
398 
399 static void
401  const Clp_Option *o2, Clp_InternOption *io2)
402 {
403  Clp_Internal *cli = clp->internal;
404  int short1, shortx1;
405 
406  /* ignore meaningless combinations */
407  if ((!io1->ishort && !io1->ilong) || (!io2->ishort && !io2->ilong)
408  || !((io1->ipos && io2->ipos) || (io1->ineg && io2->ineg))
409  || o1->option_id == o2->option_id)
410  return;
411 
412  /* look for duplication of short options */
413  short1 = (io1->ishort ? o1->short_name : -1);
414  shortx1 = long_as_short(cli, o1, io1, -2);
415  if (short1 >= 0 || shortx1 >= 0) {
416  int short2 = (io2->ishort ? o2->short_name : -3);
417  int shortx2 = long_as_short(cli, o2, io2, -4);
418  if (short1 == short2)
419  Clp_OptionError(clp, "CLP internal error: more than 1 option has short name %<%c%>", short1);
420  else if ((short1 == shortx2 || shortx1 == short2 || shortx1 == shortx2)
421  && ((io1->ipos && io2->ipos && cli->long1pos)
422  || (io1->ineg && io2->ineg && cli->long1neg)))
423  Clp_OptionError(clp, "CLP internal error: 1-char long name conflicts with short name %<%c%>", (short1 == shortx2 ? shortx2 : shortx1));
424  }
425 
426  /* analyze longest minimum match */
427  if (io1->ilong) {
428  const char *name1 = o1->long_name + io1->ilongoff;
429 
430  /* long name's first character matches short name */
431  if (io2->ishort && !io1->iprefmatch) {
432  int name1char = (cli->utf8 ? decode_utf8(name1, 0) : (unsigned char) *name1);
433  if (name1char == o2->short_name) {
434  if (io1->ipos && io2->ipos)
435  io1->lmmpos_short = 1;
436  if (io1->ineg && io2->ineg)
437  io1->lmmneg_short = 1;
438  }
439  }
440 
441  /* match long name to long name */
442  if (io2->ilong) {
443  const char *name2 = o2->long_name + io2->ilongoff;
444  if (strcmp(name1, name2) == 0)
445  Clp_OptionError(clp, "CLP internal error: duplicate long name %<%s%>", name1);
446  if (io1->ipos && io2->ipos && !strncmp(name1, name2, io1->lmmpos)
447  && (!io1->iprefmatch || strncmp(name1, name2, strlen(name1))))
448  io1->lmmpos = min_different_chars(name1, name2);
449  if (io1->ineg && io2->ineg && !strncmp(name1, name2, io1->lmmneg)
450  && (!io1->iprefmatch || strncmp(name1, name2, strlen(name1))))
451  io1->lmmneg = min_different_chars(name1, name2);
452  }
453  }
454 }
455 
456 static void
457 calculate_lmm(Clp_Parser *clp, const Clp_Option *opt, Clp_InternOption *iopt, int nopt)
458 {
459  int i, j;
460  for (i = 0; i < nopt; ++i) {
461  iopt[i].lmmpos = iopt[i].lmmneg = 1;
462  iopt[i].lmmpos_short = iopt[i].lmmneg_short = 0;
463  for (j = 0; j < nopt; ++j)
464  compare_options(clp, &opt[i], &iopt[i], &opt[j], &iopt[j]);
465  }
466 }
467 
504 Clp_Parser *
505 Clp_NewParser(int argc, const char * const *argv, int nopt, const Clp_Option *opt)
506 {
507  Clp_Parser *clp = (Clp_Parser *)malloc(sizeof(Clp_Parser));
508  Clp_Internal *cli = (Clp_Internal *)malloc(sizeof(Clp_Internal));
509  Clp_InternOption *iopt = (Clp_InternOption *)malloc(sizeof(Clp_InternOption) * nopt);
510  if (cli)
511  cli->valtype = (Clp_ValType *)malloc(sizeof(Clp_ValType) * Clp_InitialValType);
512  if (!clp || !cli || !iopt || !cli->valtype)
513  goto failed;
514 
516  clp->negated = 0;
517  clp->have_val = 0;
518  clp->vstr = 0;
519  clp->user_data = 0;
520  clp->internal = cli;
521 
522  cli->opt = opt;
523  cli->nopt = nopt;
524  cli->iopt = iopt;
525  cli->opt_generation = 0;
526  cli->error_handler = 0;
527 
528  /* Assign program name (now so we can call Clp_OptionError) */
529  if (argc > 0) {
530  const char *slash = strrchr(argv[0], '/');
531  cli->program_name = slash ? slash + 1 : argv[0];
532  } else
533  cli->program_name = 0;
534 
535  /* Assign arguments, skipping program name */
536  Clp_SetArguments(clp, argc - 1, argv + 1);
537 
538  /* Initialize UTF-8 status and option classes */
539  {
540  char *s = getenv("LANG");
541  cli->utf8 = (s && (strstr(s, "UTF-8") != 0 || strstr(s, "UTF8") != 0
542  || strstr(s, "utf8") != 0));
543  }
544  cli->oclass[0].c = '-';
545  cli->oclass[0].type = Clp_Short;
546  cli->noclass = 1;
547  cli->long1pos = cli->long1neg = 0;
548 
549  /* Add default type parsers */
550  cli->nvaltype = 0;
553  Clp_AddType(clp, Clp_ValInt, 0, parse_int, (void*) (uintptr_t) 0);
555  Clp_AddType(clp, Clp_ValLong, 0, parse_int, (void*) (uintptr_t) 2);
559 
560  /* Set options */
561  Clp_SetOptions(clp, nopt, opt);
562 
563  return clp;
564 
565  failed:
566  if (cli && cli->valtype)
567  free(cli->valtype);
568  if (cli)
569  free(cli);
570  if (clp)
571  free(clp);
572  if (iopt)
573  free(iopt);
574  return 0;
575 }
576 
580 void
582 {
583  int i;
584  Clp_Internal *cli;
585  if (!clp)
586  return;
587 
588  cli = clp->internal;
589 
590  /* get rid of any string list types */
591  for (i = 0; i < cli->nvaltype; i++)
592  if (cli->valtype[i].func == parse_string_list) {
593  Clp_StringList *clsl = (Clp_StringList *)cli->valtype[i].user_data;
594  free(clsl->items);
595  free(clsl->iopt);
596  free(clsl);
597  }
598 
599  free(cli->valtype);
600  free(cli->iopt);
601  free(cli);
602  free(clp);
603 }
604 
605 
616 Clp_SetErrorHandler(Clp_Parser *clp, void (*errh)(Clp_Parser *, const char *))
617 {
618  Clp_Internal *cli = clp->internal;
619  Clp_ErrorHandler old = cli->error_handler;
620  cli->error_handler = errh;
621  return old;
622 }
623 
636 int
637 Clp_SetUTF8(Clp_Parser *clp, int utf8)
638 {
639  Clp_Internal *cli = clp->internal;
640  int old_utf8 = cli->utf8;
641  cli->utf8 = utf8;
642  calculate_lmm(clp, cli->opt, cli->iopt, cli->nopt);
643  return old_utf8;
644 }
645 
653 int
655 {
656  Clp_Internal *cli = clp->internal;
657  int i, oclass = 0;
658  if (cli->noclass > 0 && cli->oclass[0].c == 0)
659  oclass = cli->oclass[0].type;
660  for (i = 0; i < cli->noclass; ++i)
661  if (cli->oclass[i].c == c)
662  oclass = cli->oclass[i].type;
663  return oclass;
664 }
665 
711 int
712 Clp_SetOptionChar(Clp_Parser *clp, int c, int type)
713 {
714  int i, long1pos, long1neg;
715  int old = Clp_OptionChar(clp, c);
716  Clp_Internal *cli = clp->internal;
717 
718  if (type != Clp_NotOption && type != Clp_Short && type != Clp_Long
719  && type != Clp_ShortNegated && type != Clp_LongNegated
720  && type != Clp_LongImplicit && type != (Clp_Short | Clp_Long)
721  && type != (Clp_ShortNegated | Clp_LongNegated))
722  return -1;
723  if (c < 0 || c >= (cli->utf8 ? 0x110000 : 256))
724  return -1;
725 
726  if (c == 0)
727  cli->noclass = 0;
728  for (i = 0; i < cli->noclass; ++i)
729  if (cli->oclass[i].c == c)
730  break;
731  if (i == Clp_OclassSize)
732  return -1;
733 
734  cli->oclass[i].c = c;
735  cli->oclass[i].type = type;
736  if (cli->noclass == i)
737  cli->noclass = i + 1;
738 
739  long1pos = long1neg = 0;
740  for (i = 0; i < cli->noclass; ++i) {
741  if ((cli->oclass[i].type & Clp_Short)
742  && (cli->oclass[i].type & Clp_Long))
743  long1pos = 1;
744  if ((cli->oclass[i].type & Clp_ShortNegated)
745  && (cli->oclass[i].type & Clp_LongNegated))
746  long1neg = 1;
747  }
748 
749  if (long1pos != cli->long1pos || long1neg != cli->long1neg) {
750  /* Must recheck option set */
751  cli->long1pos = long1pos;
752  cli->long1neg = long1neg;
753  calculate_lmm(clp, cli->opt, cli->iopt, cli->nopt);
754  }
755 
756  return old;
757 }
758 
786 int
787 Clp_SetOptions(Clp_Parser *clp, int nopt, const Clp_Option *opt)
788 {
789  Clp_Internal *cli = clp->internal;
790  Clp_InternOption *iopt;
791  int i;
792  static unsigned opt_generation = 0;
793 
794  if (nopt > cli->nopt) {
795  iopt = (Clp_InternOption *)malloc(sizeof(Clp_InternOption) * nopt);
796  if (!iopt)
797  return -1;
798  free(cli->iopt);
799  cli->iopt = iopt;
800  }
801 
802  cli->opt = opt;
803  cli->nopt = nopt;
804  cli->opt_generation = ++opt_generation;
805  iopt = cli->iopt;
806  cli->current_option = -1;
807 
808  /* Massage the options to make them usable */
809  for (i = 0; i < nopt; ++i) {
810  memset(&iopt[i], 0, sizeof(iopt[i]));
811 
812  /* Ignore negative option_ids, which are internal to CLP */
813  if (opt[i].option_id < 0) {
814  Clp_OptionError(clp, "CLP internal error: option %d has negative option_id", i);
815  iopt[i].ilong = iopt[i].ishort = iopt[i].ipos = iopt[i].ineg = 0;
816  continue;
817  }
818 
819  /* Set flags based on input flags */
820  iopt[i].ilong = (opt[i].long_name != 0 && opt[i].long_name[0] != 0);
821  iopt[i].ishort = (opt[i].short_name > 0
822  && opt[i].short_name < (cli->utf8 ? 0x110000 : 256));
823  iopt[i].ipos = 1;
824  iopt[i].ineg = (opt[i].flags & Clp_Negate) != 0;
825  iopt[i].imandatory = (opt[i].flags & Clp_Mandatory) != 0;
826  iopt[i].ioptional = (opt[i].flags & Clp_Optional) != 0;
827  iopt[i].iprefmatch = (opt[i].flags & Clp_PreferredMatch) != 0;
828  iopt[i].ilongoff = 0;
829 
830  /* Enforce invariants */
831  if (opt[i].val_type <= 0)
832  iopt[i].imandatory = iopt[i].ioptional = 0;
833  if (opt[i].val_type > 0 && !iopt[i].ioptional)
834  iopt[i].imandatory = 1;
835 
836  /* Options that start with 'no-' should be changed to OnlyNegated */
837  if (iopt[i].ilong && strncmp(opt[i].long_name, "no-", 3) == 0) {
838  iopt[i].ipos = 0;
839  iopt[i].ineg = 1;
840  iopt[i].ilongoff = 3;
841  if (strncmp(opt[i].long_name + 3, "no-", 3) == 0)
842  Clp_OptionError(clp, "CLP internal error: option %d begins with \"no-no-\"", i);
843  } else if (opt[i].flags & Clp_OnlyNegated) {
844  iopt[i].ipos = 0;
845  iopt[i].ineg = 1;
846  }
847  }
848 
849  /* Check option set */
850  calculate_lmm(clp, opt, iopt, nopt);
851 
852  return 0;
853 }
854 
872 void
873 Clp_SetArguments(Clp_Parser *clp, int argc, const char * const *argv)
874 {
875  Clp_Internal *cli = clp->internal;
876 
877  cli->argc = argc + 1;
878  cli->argv = argv - 1;
879 
880  cli->is_short = 0;
881  cli->whole_negated = 0;
882  cli->option_processing = 1;
883  cli->current_option = -1;
884 }
885 
886 
895 int
897 {
898  Clp_Internal *cli = clp->internal;
899  int old = cli->option_processing;
900  cli->option_processing = on;
901  return old;
902 }
903 
904 
905 /*******
906  * functions for Clp_Option lists
907  **/
908 
909 /* the ever-glorious argcmp */
910 
911 static int
912 argcmp(const char *ref, const char *arg, int min_match, int fewer_dashes)
913  /* Returns 0 if ref and arg don't match.
914  Returns -1 if ref and arg match, but fewer than min_match characters.
915  Returns len if ref and arg match min_match or more characters;
916  len is the number of characters that matched in arg.
917  Allows arg to contain fewer dashes than ref iff fewer_dashes != 0.
918 
919  Examples:
920  argcmp("x", "y", 1, 0) --> 0 / just plain wrong
921  argcmp("a", "ax", 1, 0) --> 0 / ...even though min_match == 1
922  and the 1st chars match
923  argcmp("box", "bo", 3, 0) --> -1 / ambiguous
924  argcmp("cat", "c=3", 1, 0) --> 1 / handles = arguments
925  */
926 {
927  const char *refstart = ref;
928  const char *argstart = arg;
929  assert(min_match > 0);
930 
931  compare:
932  while (*ref && *arg && *arg != '=' && *ref == *arg)
933  ref++, arg++;
934 
935  /* Allow arg to contain fewer dashes than ref */
936  if (fewer_dashes && *ref == '-' && ref[1] && ref[1] == *arg) {
937  ref++;
938  goto compare;
939  }
940 
941  if (*arg && *arg != '=')
942  return 0;
943  else if (ref - refstart < min_match)
944  return -1;
945  else
946  return arg - argstart;
947 }
948 
949 static int
950 find_prefix_opt(Clp_Parser *clp, const char *arg,
951  int nopt, const Clp_Option *opt,
952  const Clp_InternOption *iopt,
953  int *ambiguous, int *ambiguous_values)
954  /* Looks for an unambiguous match of 'arg' against one of the long
955  options in 'opt'. Returns positive if it finds one; otherwise, returns
956  -1 and possibly changes 'ambiguous' and 'ambiguous_values' to keep
957  track of at most MAX_AMBIGUOUS_VALUES possibilities. */
958 {
959  int i, fewer_dashes = 0, first_ambiguous = *ambiguous;
960  int negated = clp && clp->negated;
961  int first_charlen = (clp ? clp_utf8_charlen(clp->internal, arg) : 1);
962 
963  retry:
964  for (i = 0; i < nopt; i++) {
965  int len, lmm;
966  if (!iopt[i].ilong || (negated ? !iopt[i].ineg : !iopt[i].ipos))
967  continue;
968 
969  lmm = (negated ? iopt[i].lmmneg : iopt[i].lmmpos);
970  if (clp && clp->internal->could_be_short
971  && (negated ? iopt[i].lmmneg_short : iopt[i].lmmpos_short))
972  lmm = (first_charlen >= lmm ? first_charlen + 1 : lmm);
973  len = argcmp(opt[i].long_name + iopt[i].ilongoff, arg, lmm, fewer_dashes);
974  if (len > 0)
975  return i;
976  else if (len < 0) {
977  if (*ambiguous < MAX_AMBIGUOUS_VALUES)
978  ambiguous_values[*ambiguous] = i;
979  (*ambiguous)++;
980  }
981  }
982 
983  /* If there were no partial matches, try again with fewer_dashes true */
984  if (*ambiguous == first_ambiguous && !fewer_dashes) {
985  fewer_dashes = 1;
986  goto retry;
987  }
988 
989  return -1;
990 }
991 
992 
993 /*****
994  * Argument parsing
995  **/
996 
997 static int
998 val_type_binsearch(Clp_Internal *cli, int val_type)
999 {
1000  unsigned l = 0, r = cli->nvaltype;
1001  while (l < r) {
1002  unsigned m = l + (r - l) / 2;
1003  if (cli->valtype[m].val_type == val_type)
1004  return m;
1005  else if (cli->valtype[m].val_type < val_type)
1006  l = m + 1;
1007  else
1008  r = m;
1009  }
1010  return l;
1011 }
1012 
1044 int
1045 Clp_AddType(Clp_Parser *clp, int val_type, int flags,
1046  Clp_ValParseFunc parser, void *user_data)
1047 {
1048  Clp_Internal *cli = clp->internal;
1049  int vtpos;
1050 
1051  if (val_type <= 0 || !parser)
1052  return -1;
1053 
1054  vtpos = val_type_binsearch(cli, val_type);
1055 
1056  if (vtpos == cli->nvaltype || cli->valtype[vtpos].val_type != val_type) {
1057  if (cli->nvaltype != 0 && (cli->nvaltype % Clp_InitialValType) == 0) {
1058  Clp_ValType *new_valtype =
1059  (Clp_ValType *) realloc(cli->valtype, sizeof(Clp_ValType) * (cli->nvaltype + Clp_InitialValType));
1060  if (!new_valtype)
1061  return -1;
1062  cli->valtype = new_valtype;
1063  }
1064  memmove(&cli->valtype[vtpos + 1], &cli->valtype[vtpos],
1065  sizeof(Clp_ValType) * (cli->nvaltype - vtpos));
1066  cli->nvaltype++;
1067  cli->valtype[vtpos].func = 0;
1068  }
1069 
1070  if (cli->valtype[vtpos].func == parse_string_list) {
1071  Clp_StringList *clsl = (Clp_StringList *) cli->valtype[vtpos].user_data;
1072  free(clsl->items);
1073  free(clsl->iopt);
1074  free(clsl);
1075  }
1076 
1077  cli->valtype[vtpos].val_type = val_type;
1078  cli->valtype[vtpos].func = parser;
1079  cli->valtype[vtpos].flags = flags;
1080  cli->valtype[vtpos].user_data = user_data;
1081  return 0;
1082 }
1083 
1084 
1085 /*******
1086  * Default argument parsers
1087  **/
1088 
1089 static int
1090 parse_string(Clp_Parser *clp, const char *arg, int complain, void *user_data)
1091 {
1092  (void)complain, (void)user_data;
1093  clp->val.s = arg;
1094  return 1;
1095 }
1096 
1097 static int
1098 parse_int(Clp_Parser* clp, const char* arg, int complain, void* user_data)
1099 {
1100  const char *val;
1101  uintptr_t type = (uintptr_t) user_data;
1102  if (*arg == 0 || isspace((unsigned char) *arg)
1103  || ((type & 1) && *arg == '-'))
1104  val = arg;
1105  else if (type & 1) { /* unsigned */
1106 #if HAVE_STRTOUL
1107  clp->val.ul = strtoul(arg, (char **) &val, 0);
1108 #else
1109  /* don't bother really trying to do it right */
1110  if (arg[0] == '-')
1111  val = arg;
1112  else
1113  clp->val.l = strtol(arg, (char **) &val, 0);
1114 #endif
1115  } else
1116  clp->val.l = strtol(arg, (char **) &val, 0);
1117  if (type <= 1)
1118  clp->val.u = (unsigned) clp->val.ul;
1119  if (*arg != 0 && *val == 0)
1120  return 1;
1121  else {
1122  if (complain) {
1123  const char *message = (type & 1)
1124  ? "%<%O%> expects a nonnegative integer, not %<%s%>"
1125  : "%<%O%> expects an integer, not %<%s%>";
1126  Clp_OptionError(clp, message, arg);
1127  }
1128  return 0;
1129  }
1130 }
1131 
1132 static int
1133 parse_double(Clp_Parser *clp, const char *arg, int complain, void *user_data)
1134 {
1135  const char *val;
1136  (void)user_data;
1137  if (*arg == 0 || isspace((unsigned char) *arg))
1138  val = arg;
1139  else
1140  clp->val.d = strtod(arg, (char **) &val);
1141  if (*arg != 0 && *val == 0)
1142  return 1;
1143  else {
1144  if (complain)
1145  Clp_OptionError(clp, "%<%O%> expects a real number, not %<%s%>", arg);
1146  return 0;
1147  }
1148 }
1149 
1150 static int
1151 parse_bool(Clp_Parser *clp, const char *arg, int complain, void *user_data)
1152 {
1153  int i;
1154  char lcarg[6];
1155  (void)user_data;
1156  if (strlen(arg) > 5 || strchr(arg, '=') != 0)
1157  goto error;
1158 
1159  for (i = 0; arg[i] != 0; i++)
1160  lcarg[i] = tolower((unsigned char) arg[i]);
1161  lcarg[i] = 0;
1162 
1163  if (argcmp("yes", lcarg, 1, 0) > 0
1164  || argcmp("true", lcarg, 1, 0) > 0
1165  || argcmp("1", lcarg, 1, 0) > 0) {
1166  clp->val.i = 1;
1167  return 1;
1168  } else if (argcmp("no", lcarg, 1, 0) > 0
1169  || argcmp("false", lcarg, 1, 0) > 0
1170  || argcmp("1", lcarg, 1, 0) > 0) {
1171  clp->val.i = 0;
1172  return 1;
1173  }
1174 
1175  error:
1176  if (complain)
1177  Clp_OptionError(clp, "%<%O%> expects a true-or-false value, not %<%s%>", arg);
1178  return 0;
1179 }
1180 
1182 /*****
1183  * Clp_AddStringListType
1184  **/
1185 
1186 static int
1187 parse_string_list(Clp_Parser *clp, const char *arg, int complain, void *user_data)
1188 {
1189  Clp_StringList *sl = (Clp_StringList *)user_data;
1190  int idx, ambiguous = 0;
1191  int ambiguous_values[MAX_AMBIGUOUS_VALUES + 1];
1192 
1193  /* actually look for a string value */
1194  idx = find_prefix_opt
1195  (0, arg, sl->nitems, sl->items, sl->iopt,
1196  &ambiguous, ambiguous_values);
1197  if (idx >= 0) {
1198  clp->val.i = sl->items[idx].option_id;
1199  if (sl->val_long)
1200  clp->val.l = clp->val.i;
1201  return 1;
1202  }
1203 
1204  if (sl->allow_int) {
1205  if (parse_int(clp, arg, 0, (void*) (uintptr_t) (sl->val_long ? 2 : 0)))
1206  return 1;
1207  }
1208 
1209  if (complain) {
1210  const char *complaint = (ambiguous ? "ambiguous" : "invalid");
1211  if (!ambiguous) {
1212  ambiguous = sl->nitems_invalid_report;
1213  for (idx = 0; idx < ambiguous; idx++)
1214  ambiguous_values[idx] = idx;
1215  }
1216  return ambiguity_error
1217  (clp, ambiguous, ambiguous_values, sl->items, sl->iopt,
1218  "", "option %<%V%> is %s", complaint);
1219  } else
1220  return 0;
1221 }
1222 
1223 
1224 static int
1225 finish_string_list(Clp_Parser *clp, int val_type, int flags,
1226  Clp_Option *items, int nitems, int itemscap)
1227 {
1228  int i;
1229  Clp_StringList *clsl = (Clp_StringList *)malloc(sizeof(Clp_StringList));
1230  Clp_InternOption *iopt = (Clp_InternOption *)malloc(sizeof(Clp_InternOption) * nitems);
1231  if (!clsl || !iopt)
1232  goto error;
1233 
1234  clsl->items = items;
1235  clsl->iopt = iopt;
1236  clsl->nitems = nitems;
1237  clsl->allow_int = (flags & Clp_AllowNumbers) != 0;
1238  clsl->val_long = (flags & Clp_StringListLong) != 0;
1239 
1240  if (nitems < MAX_AMBIGUOUS_VALUES && nitems < itemscap && clsl->allow_int) {
1241  items[nitems].long_name = "any integer";
1242  clsl->nitems_invalid_report = nitems + 1;
1243  } else if (nitems > MAX_AMBIGUOUS_VALUES + 1)
1245  else
1246  clsl->nitems_invalid_report = nitems;
1247 
1248  for (i = 0; i < nitems; i++) {
1249  iopt[i].ilong = iopt[i].ipos = 1;
1250  iopt[i].ishort = iopt[i].ineg = iopt[i].ilongoff = iopt[i].iprefmatch = 0;
1251  }
1252  calculate_lmm(clp, items, iopt, nitems);
1253 
1254  if (Clp_AddType(clp, val_type, 0, parse_string_list, clsl) >= 0)
1255  return 0;
1256 
1257  error:
1258  if (clsl)
1259  free(clsl);
1260  if (iopt)
1261  free(iopt);
1262  return -1;
1263 }
1264 
1290 int
1291 Clp_AddStringListType(Clp_Parser *clp, int val_type, int flags, ...)
1292 {
1293  int nitems = 0;
1294  int itemscap = 5;
1295  Clp_Option *items = (Clp_Option *)malloc(sizeof(Clp_Option) * itemscap);
1296 
1297  va_list val;
1298  va_start(val, flags);
1299 
1300  if (!items)
1301  goto error;
1302 
1303  /* slurp up the arguments */
1304  while (1) {
1305  int value;
1306  char *name = va_arg(val, char *);
1307  if (!name)
1308  break;
1309  if (flags & Clp_StringListLong) {
1310  long lvalue = va_arg(val, long);
1311  value = (int) lvalue;
1312  assert(value == lvalue);
1313  } else
1314  value = va_arg(val, int);
1315 
1316  if (nitems >= itemscap) {
1317  Clp_Option *new_items;
1318  itemscap *= 2;
1319  new_items = (Clp_Option *)realloc(items, sizeof(Clp_Option) * itemscap);
1320  if (!new_items)
1321  goto error;
1322  items = new_items;
1323  }
1324 
1325  items[nitems].long_name = name;
1326  items[nitems].option_id = value;
1327  items[nitems].flags = 0;
1328  nitems++;
1329  }
1330 
1331  va_end(val);
1332  if (finish_string_list(clp, val_type, flags, items, nitems, itemscap) >= 0)
1333  return 0;
1334 
1335  error:
1336  va_end(val);
1337  if (items)
1338  free(items);
1339  return -1;
1340 }
1341 
1379 int
1380 Clp_AddStringListTypeVec(Clp_Parser *clp, int val_type, int flags,
1381  int nstrs, const char * const *strs,
1382  const int *vals)
1383  /* An alternate way to make a string list type. See Clp_AddStringListType
1384  for the basics; this coalesces the strings and values into two arrays,
1385  rather than spreading them out into a variable argument list. */
1386 {
1387  int i;
1388  int itemscap = (nstrs < 5 ? 5 : nstrs);
1389  Clp_Option *items = (Clp_Option *)malloc(sizeof(Clp_Option) * itemscap);
1390  if (!items)
1391  return -1;
1392 
1393  /* copy over items */
1394  for (i = 0; i < nstrs; i++) {
1395  items[i].long_name = strs[i];
1396  items[i].option_id = vals[i];
1397  items[i].flags = 0;
1398  }
1399 
1400  if (finish_string_list(clp, val_type, flags, items, nstrs, itemscap) >= 0)
1401  return 0;
1402  else {
1403  free(items);
1404  return -1;
1405  }
1406 }
1408 
1409 /*******
1410  * Returning information
1411  **/
1412 
1413 const char *
1415 {
1416  return clp->internal->program_name;
1417 }
1418 
1425 const char *
1426 Clp_SetProgramName(Clp_Parser *clp, const char *name)
1427 {
1428  const char *old = clp->internal->program_name;
1429  clp->internal->program_name = name;
1430  return old;
1431 }
1432 
1433 
1434 /******
1435  * Clp_ParserStates
1436  **/
1437 
1454 Clp_NewParserState(void)
1455 {
1456  Clp_ParserState *state = (Clp_ParserState *)malloc(sizeof(Clp_ParserState));
1457  if (state) {
1458  state->argv = 0;
1459  state->argc = 0;
1460  state->option_chars[0] = 0;
1461  state->xtext = 0;
1462  state->option_processing = 0;
1463  state->opt_generation = 0;
1464  state->current_option = -1;
1465  state->is_short = 0;
1466  state->whole_negated = 0;
1467  state->current_short = 0;
1468  state->negated_by_no = 0;
1469  }
1470  return state;
1471 }
1472 
1477 void
1479 {
1480  free(state);
1481 }
1482 
1487 void
1489 {
1490  Clp_Internal *cli = clp->internal;
1491  state->argv = cli->argv;
1492  state->argc = cli->argc;
1493  memcpy(state->option_chars, cli->option_chars, Clp_OptionCharsSize);
1494  state->xtext = cli->xtext;
1495 
1496  state->option_processing = cli->option_processing;
1497  state->opt_generation = cli->opt_generation;
1498  state->current_option = cli->current_option;
1499  state->is_short = cli->is_short;
1500  state->whole_negated = cli->whole_negated;
1501  state->current_short = cli->current_short;
1502  state->negated_by_no = cli->negated_by_no;
1503 }
1504 
1505 
1520 void
1522 {
1523  Clp_Internal *cli = clp->internal;
1524  cli->argv = state->argv;
1525  cli->argc = state->argc;
1526  memcpy(cli->option_chars, state->option_chars, Clp_OptionCharsSize);
1527  cli->xtext = state->xtext;
1528  cli->option_processing = state->option_processing;
1529  cli->is_short = state->is_short;
1530  cli->whole_negated = state->whole_negated;
1531  cli->current_short = state->current_short;
1532  cli->negated_by_no = state->negated_by_no;
1533  if (cli->opt_generation == state->opt_generation)
1534  cli->current_option = state->current_option;
1535  else
1536  cli->current_option = -1;
1537 }
1538 
1539 
1540 /*******
1541  * Clp_Next and its helpers
1542  **/
1543 
1544 static void
1545 set_option_text(Clp_Internal *cli, const char *text, int n_option_chars)
1546 {
1547  assert(n_option_chars < Clp_OptionCharsSize);
1548  memcpy(cli->option_chars, text, n_option_chars);
1549  cli->option_chars[n_option_chars] = 0;
1550  cli->xtext = text + n_option_chars;
1551 }
1552 
1553 static int
1554 get_oclass(Clp_Parser *clp, const char *text, int *ocharskip)
1555 {
1556  int c;
1557  if (clp->internal->utf8) {
1558  const char *s;
1559  c = decode_utf8(text, &s);
1560  *ocharskip = s - text;
1561  } else {
1562  c = (unsigned char) text[0];
1563  *ocharskip = 1;
1564  }
1565  return Clp_OptionChar(clp, c);
1566 }
1567 
1568 static int
1569 next_argument(Clp_Parser *clp, int want_argument)
1570  /* Moves clp to the next argument.
1571  Returns 1 if it finds another option.
1572  Returns 0 if there aren't any more arguments.
1573  Returns 0, sets clp->have_val = 1, and sets clp->vstr to the argument
1574  if the next argument isn't an option.
1575  If want_argument > 0, it'll look for an argument.
1576  want_argument == 1: Accept arguments that start with Clp_NotOption
1577  or Clp_LongImplicit.
1578  want_argument == 2: Accept ALL arguments.
1579 
1580  Where is the option stored when this returns?
1581  Well, cli->argv[0] holds the whole of the next command line argument.
1582  cli->option_chars holds a string: what characters began the option?
1583  It is generally "-" or "--".
1584  cli->text holds the text of the option:
1585  for short options, cli->text[0] is the relevant character;
1586  for long options, cli->text holds the rest of the option. */
1587 {
1588  Clp_Internal *cli = clp->internal;
1589  const char *text;
1590  int oclass, ocharskip;
1591 
1592  /* clear relevant flags */
1593  clp->have_val = 0;
1594  clp->vstr = 0;
1595  cli->could_be_short = 0;
1596 
1597  /* if we're in a string of short options, move up one char in the string */
1598  if (cli->is_short) {
1599  cli->xtext += clp_utf8_charlen(cli, cli->xtext);
1600  if (cli->xtext[0] == 0)
1601  cli->is_short = 0;
1602  else if (want_argument > 0) {
1603  /* handle -O[=]argument case */
1604  clp->have_val = 1;
1605  if (cli->xtext[0] == '=')
1606  clp->vstr = cli->xtext + 1;
1607  else
1608  clp->vstr = cli->xtext;
1609  cli->is_short = 0;
1610  return 0;
1611  }
1612  }
1613 
1614  /* if in short options, we're all set */
1615  if (cli->is_short)
1616  return 1;
1617 
1619  cli->whole_negated = 0;
1620  cli->xtext = 0;
1621 
1622  if (cli->argc <= 1)
1623  return 0;
1624 
1625  cli->argc--;
1626  cli->argv++;
1627  text = cli->argv[0];
1628 
1629  if (want_argument > 1)
1630  goto not_option;
1631 
1632  if (text[0] == '-' && text[1] == '-') {
1633  oclass = Clp_DoubledLong;
1634  ocharskip = 2;
1635  } else
1636  oclass = get_oclass(clp, text, &ocharskip);
1637 
1638  /* If this character could introduce either a short or a long option,
1639  try a long option first, but remember that short's a possibility for
1640  later. */
1641  if ((oclass & (Clp_Short | Clp_ShortNegated))
1642  && (oclass & (Clp_Long | Clp_LongNegated))) {
1643  oclass &= ~(Clp_Short | Clp_ShortNegated);
1644  if (text[ocharskip])
1645  cli->could_be_short = 1;
1646  }
1647 
1648  switch (oclass) {
1649 
1650  case Clp_Short:
1651  cli->is_short = 1;
1652  goto check_singleton;
1653 
1654  case Clp_ShortNegated:
1655  cli->is_short = 1;
1656  cli->whole_negated = 1;
1657  goto check_singleton;
1658 
1659  case Clp_Long:
1660  goto check_singleton;
1661 
1662  case Clp_LongNegated:
1663  cli->whole_negated = 1;
1664  goto check_singleton;
1665 
1666  check_singleton:
1667  /* For options introduced with one character, option-char,
1668  '[option-char]' alone is NOT an option. */
1669  if (!text[ocharskip])
1670  goto not_option;
1671  set_option_text(cli, text, ocharskip);
1672  break;
1673 
1674  case Clp_LongImplicit:
1675  /* LongImplict: option_chars == "" (since all chars are part of the
1676  option); restore head -> text of option */
1677  if (want_argument > 0)
1678  goto not_option;
1679  set_option_text(cli, text, 0);
1680  break;
1681 
1682  case Clp_DoubledLong:
1683  set_option_text(cli, text, ocharskip);
1684  break;
1685 
1686  not_option:
1687  case Clp_NotOption:
1688  cli->is_short = 0;
1689  clp->have_val = 1;
1690  clp->vstr = text;
1691  return 0;
1692 
1693  default:
1694  assert(0 /* CLP misconfiguration: bad option type */);
1695 
1696  }
1697 
1698  return 1;
1699 }
1700 
1701 
1702 static void
1704 {
1705  Clp_Internal *cli = clp->internal;
1706  const char *text = cli->argv[0];
1707  int ocharskip, oclass = get_oclass(clp, text, &ocharskip);
1708  assert(cli->could_be_short);
1709  cli->is_short = 1;
1710  cli->whole_negated = !!(oclass & Clp_ShortNegated);
1711  set_option_text(cli, cli->argv[0], ocharskip);
1712 }
1713 
1714 
1715 static int
1716 find_long(Clp_Parser *clp, const char *arg)
1717  /* If arg corresponds to one of clp's options, finds that option &
1718  returns it. If any argument is given after an = sign in arg, sets
1719  clp->have_val = 1 and clp->vstr to that argument. Sets cli->ambiguous
1720  to 1 iff there was no match because the argument was ambiguous. */
1721 {
1722  Clp_Internal *cli = clp->internal;
1723  int optno, len, lmm;
1724  const Clp_Option *opt = cli->opt;
1725  const Clp_InternOption *iopt;
1726  int first_negative_ambiguous;
1727 
1728  /* Look for a normal option. */
1729  optno = find_prefix_opt
1730  (clp, arg, cli->nopt, opt, cli->iopt,
1731  &cli->ambiguous, cli->ambiguous_values);
1732  if (optno >= 0)
1733  goto worked;
1734 
1735  /* If we can't find it, look for a negated option. */
1736  /* I know this is silly, but it makes me happy to accept
1737  --no-no-option as a double negative synonym for --option. :) */
1738  first_negative_ambiguous = cli->ambiguous;
1739  while (arg[0] == 'n' && arg[1] == 'o' && arg[2] == '-') {
1740  arg += 3;
1741  clp->negated = !clp->negated;
1742  optno = find_prefix_opt
1743  (clp, arg, cli->nopt, opt, cli->iopt,
1744  &cli->ambiguous, cli->ambiguous_values);
1745  if (optno >= 0)
1746  goto worked;
1747  }
1748 
1749  /* No valid option was found; return 0. Mark the ambiguous values found
1750  through '--no' by making them negative. */
1751  {
1752  int i, max = cli->ambiguous;
1754  for (i = first_negative_ambiguous; i < max; i++)
1755  cli->ambiguous_values[i] = -cli->ambiguous_values[i] - 1;
1756  }
1757  return -1;
1758 
1759  worked:
1760  iopt = &cli->iopt[optno];
1761  lmm = (clp->negated ? iopt->lmmneg : iopt->lmmpos);
1762  if (cli->could_be_short
1763  && (clp->negated ? iopt->lmmneg_short : iopt->lmmpos_short)) {
1764  int first_charlen = clp_utf8_charlen(cli, arg);
1765  lmm = (first_charlen >= lmm ? first_charlen + 1 : lmm);
1766  }
1767  len = argcmp(opt[optno].long_name + iopt->ilongoff, arg, lmm, 1);
1768  assert(len > 0);
1769  if (arg[len] == '=') {
1770  clp->have_val = 1;
1771  clp->vstr = arg + len + 1;
1772  }
1773  return optno;
1774 }
1775 
1776 
1777 static int
1778 find_short(Clp_Parser *clp, const char *text)
1779  /* If short_name corresponds to one of clp's options, returns it. */
1780 {
1781  Clp_Internal *cli = clp->internal;
1782  const Clp_Option *opt = cli->opt;
1783  const Clp_InternOption *iopt = cli->iopt;
1784  int i, c;
1785  if (clp->internal->utf8)
1786  c = decode_utf8(text, 0);
1787  else
1788  c = (unsigned char) *text;
1789 
1790  for (i = 0; i < cli->nopt; i++)
1791  if (iopt[i].ishort && opt[i].short_name == c
1792  && (!clp->negated || iopt[i].ineg)) {
1793  clp->negated = clp->negated || !iopt[i].ipos;
1794  return i;
1795  }
1796 
1797  return -1;
1798 }
1799 
1800 
1843 int
1845 {
1846  Clp_Internal *cli = clp->internal;
1847  int optno;
1848  const Clp_Option *opt;
1849  Clp_ParserState clpsave;
1850  int vtpos, complain;
1851 
1852  /* Set up clp */
1853  cli->current_option = -1;
1854  cli->ambiguous = 0;
1855 
1856  /* Get the next argument or option */
1857  if (!next_argument(clp, cli->option_processing ? 0 : 2)) {
1858  clp->val.s = clp->vstr;
1859  optno = clp->have_val ? Clp_NotOption : Clp_Done;
1860  clp->option = &clp_option_sentinel[-optno];
1861  return optno;
1862  }
1863 
1864  clp->negated = cli->whole_negated;
1865  if (cli->is_short)
1866  optno = find_short(clp, cli->xtext);
1867  else
1868  optno = find_long(clp, cli->xtext);
1869 
1870  /* If there's ambiguity between long & short options, and we couldn't
1871  find a long option, look for a short option */
1872  if (optno < 0 && cli->could_be_short) {
1874  optno = find_short(clp, cli->xtext);
1875  }
1876 
1877  /* If we didn't find an option... */
1878  if (optno < 0 || (clp->negated && !cli->iopt[optno].ineg)) {
1879  /* default processing for the "--" option: turn off option processing
1880  and return the next argument */
1881  if (strcmp(cli->argv[0], "--") == 0) {
1883  return Clp_Next(clp);
1884  }
1885 
1886  /* otherwise, report some error or other */
1887  if (cli->ambiguous)
1889  cli->opt, cli->iopt, cli->option_chars,
1890  "option %<%s%s%> is ambiguous",
1891  cli->option_chars, cli->xtext);
1892  else if (cli->is_short && !cli->could_be_short)
1893  Clp_OptionError(clp, "unrecognized option %<%s%C%>",
1894  cli->option_chars, cli->xtext);
1895  else
1896  Clp_OptionError(clp, "unrecognized option %<%s%s%>",
1897  cli->option_chars, cli->xtext);
1898 
1900  return Clp_BadOption;
1901  }
1902 
1903  /* Set the current option */
1904  cli->current_option = optno;
1905  cli->current_short = cli->is_short;
1906  cli->negated_by_no = clp->negated && !cli->whole_negated;
1907 
1908  /* The no-argument (or should-have-no-argument) case */
1909  if (clp->negated
1910  || (!cli->iopt[optno].imandatory && !cli->iopt[optno].ioptional)) {
1911  if (clp->have_val) {
1912  Clp_OptionError(clp, "%<%O%> can%,t take an argument");
1914  return Clp_BadOption;
1915  } else {
1916  clp->option = &cli->opt[optno];
1917  return cli->opt[optno].option_id;
1918  }
1919  }
1920 
1921  /* Get an argument if we need one, or if it's optional */
1922  /* Sanity-check the argument type. */
1923  opt = &cli->opt[optno];
1924  if (opt->val_type <= 0) {
1926  return Clp_Error;
1927  }
1928  vtpos = val_type_binsearch(cli, opt->val_type);
1929  if (vtpos == cli->nvaltype
1930  || cli->valtype[vtpos].val_type != opt->val_type) {
1932  return Clp_Error;
1933  }
1934 
1935  /* complain == 1 only if the argument was explicitly given,
1936  or it is mandatory. */
1937  complain = (clp->have_val != 0) || cli->iopt[optno].imandatory;
1938  Clp_SaveParser(clp, &clpsave);
1939 
1940  if (cli->iopt[optno].imandatory && !clp->have_val) {
1941  /* Mandatory argument case */
1942  /* Allow arguments to options to start with a dash, but only if the
1943  argument type allows it by not setting Clp_DisallowOptions */
1944  int disallow = (cli->valtype[vtpos].flags & Clp_DisallowOptions) != 0;
1945  next_argument(clp, disallow ? 1 : 2);
1946  if (!clp->have_val) {
1947  int got_option = cli->xtext != 0;
1948  Clp_RestoreParser(clp, &clpsave);
1949  if (got_option)
1950  Clp_OptionError(clp, "%<%O%> requires a non-option argument");
1951  else
1952  Clp_OptionError(clp, "%<%O%> requires an argument");
1954  return Clp_BadOption;
1955  }
1956 
1957  } else if (cli->is_short && !clp->have_val
1958  && cli->xtext[clp_utf8_charlen(cli, cli->xtext)])
1959  /* The -[option]argument case:
1960  Assume that the rest of the current string is the argument. */
1961  next_argument(clp, 1);
1962 
1963  /* Parse the argument */
1964  clp->option = opt;
1965  if (clp->have_val) {
1966  Clp_ValType *atr = &cli->valtype[vtpos];
1967  if (atr->func(clp, clp->vstr, complain, atr->user_data) <= 0) {
1968  /* parser failed */
1969  clp->have_val = 0;
1970  if (complain) {
1972  return Clp_BadOption;
1973  } else {
1974  Clp_RestoreParser(clp, &clpsave);
1975  clp->option = opt;
1976  }
1977  }
1978  }
1979 
1980  return opt->option_id;
1981 }
1982 
1991 const char *
1992 Clp_Shift(Clp_Parser *clp, int allow_options)
1993  /* Returns the next argument from the argument list without parsing it.
1994  If there are no more arguments, returns 0. */
1995 {
1996  Clp_ParserState clpsave;
1997  Clp_SaveParser(clp, &clpsave);
1998  next_argument(clp, allow_options ? 2 : 1);
1999  if (!clp->have_val)
2000  Clp_RestoreParser(clp, &clpsave);
2001  return clp->vstr;
2005 /*******
2006  * Clp_OptionError
2007  **/
2008 
2009 typedef struct Clp_BuildString {
2010  char* data;
2011  char* pos;
2012  char* end_data;
2013  char buf[256];
2014 } Clp_BuildString;
2015 
2017  const Clp_Parser* clp);
2018 
2019 static void build_string_init(Clp_BuildString* bs, Clp_Parser* clp) {
2020  bs->data = bs->pos = bs->buf;
2021  bs->end_data = &bs->buf[sizeof(bs->buf)];
2022  if (clp)
2024 }
2025 
2026 static void build_string_cleanup(Clp_BuildString* bs) {
2027  if (bs->data != bs->buf)
2028  free(bs->data);
2029 }
2030 
2031 static int build_string_grow(Clp_BuildString* bs, size_t want) {
2032  size_t ipos = bs->pos - bs->data, ncap;
2033  if (!bs->pos)
2034  return 0;
2035  for (ncap = (bs->end_data - bs->data) << 1; ncap < want; ncap *= 2)
2036  /* nada */;
2037  if (bs->data == bs->buf) {
2038  if ((bs->data = (char*) malloc(ncap)))
2039  memcpy(bs->data, bs->buf, bs->pos - bs->buf);
2040  } else
2041  bs->data = (char*) realloc(bs->data, ncap);
2042  if (!bs->data) {
2043  bs->pos = bs->end_data = bs->data;
2044  return 0;
2045  } else {
2046  bs->pos = bs->data + ipos;
2047  bs->end_data = bs->data + ncap;
2048  return 1;
2049  }
2050 }
2051 
2052 #define ENSURE_BUILD_STRING(bs, space) \
2053  ((((bs)->end_data - (bs)->pos) >= (space)) \
2054  || build_string_grow((bs), (bs)->pos - (bs)->data + (space)))
2055 
2056 static void
2057 append_build_string(Clp_BuildString *bs, const char *s, int l)
2059  if (l < 0)
2060  l = strlen(s);
2061  if (ENSURE_BUILD_STRING(bs, l)) {
2062  memcpy(bs->pos, s, l);
2063  bs->pos += l;
2064  }
2065 }
2066 
2067 static void
2070  const Clp_Internal* cli = clp->internal;
2071  if (cli->program_name && cli->program_name[0]) {
2072  append_build_string(bs, cli->program_name, -1);
2073  append_build_string(bs, ": ", 2);
2074  }
2075 }
2076 
2077 
2078 static void
2080  const char *fmt, va_list val)
2081 {
2082  Clp_Internal *cli = clp->internal;
2083  const char *percent;
2084  int c;
2085 
2086  for (percent = strchr(fmt, '%'); percent; percent = strchr(fmt, '%')) {
2087  append_build_string(bs, fmt, percent - fmt);
2088  switch (*++percent) {
2089 
2090  case 's': {
2091  const char *s = va_arg(val, const char *);
2092  append_build_string(bs, s ? s : "(null)", -1);
2093  break;
2094  }
2095 
2096  case 'C': {
2097  const char *s = va_arg(val, const char *);
2098  if (cli->utf8)
2099  c = decode_utf8(s, 0);
2100  else
2101  c = (unsigned char) *s;
2102  goto char_c;
2103  }
2104 
2105  case 'c':
2106  c = va_arg(val, int);
2107  goto char_c;
2108 
2109  char_c:
2110  if (ENSURE_BUILD_STRING(bs, 4)) {
2111  if (c >= 32 && c <= 126)
2112  *bs->pos++ = c;
2113  else if (c < 32) {
2114  *bs->pos++ = '^';
2115  *bs->pos++ = c + 64;
2116  } else if (cli->utf8 && c >= 127 && c < 0x110000) {
2117  bs->pos = encode_utf8(bs->pos, 4, c);
2118  } else if (c >= 127 && c <= 255) {
2119  sprintf(bs->pos, "\\%03o", c & 0xFF);
2120  bs->pos += 4;
2121  } else {
2122  *bs->pos++ = '\\';
2123  *bs->pos++ = '?';
2124  }
2125  }
2126  break;
2127 
2128  case 'd': {
2129  int d = va_arg(val, int);
2130  if (ENSURE_BUILD_STRING(bs, 32)) {
2131  sprintf(bs->pos, "%d", d);
2132  bs->pos = strchr(bs->pos, 0);
2133  }
2134  break;
2135  }
2136 
2137  case 'O':
2138  case 'V': {
2139  int optno = cli->current_option;
2140  const Clp_Option *opt = &cli->opt[optno];
2141  if (optno < 0)
2142  append_build_string(bs, "(no current option!)", -1);
2143  else if (cli->current_short) {
2144  append_build_string(bs, cli->option_chars, -1);
2145  if (ENSURE_BUILD_STRING(bs, 5)) {
2146  if (cli->utf8)
2147  bs->pos = encode_utf8(bs->pos, 5, opt->short_name);
2148  else
2149  *bs->pos++ = opt->short_name;
2150  }
2151  } else if (cli->negated_by_no) {
2152  append_build_string(bs, cli->option_chars, -1);
2153  append_build_string(bs, "no-", 3);
2154  append_build_string(bs, opt->long_name + cli->iopt[optno].ilongoff, -1);
2155  } else {
2156  append_build_string(bs, cli->option_chars, -1);
2157  append_build_string(bs, opt->long_name + cli->iopt[optno].ilongoff, -1);
2158  }
2159  if (optno >= 0 && clp->have_val && *percent == 'V') {
2160  if (cli->current_short && !cli->iopt[optno].ioptional)
2161  append_build_string(bs, " ", 1);
2162  else if (!cli->current_short)
2163  append_build_string(bs, "=", 1);
2164  append_build_string(bs, clp->vstr, -1);
2165  }
2166  break;
2167  }
2168 
2169  case '%':
2170  if (ENSURE_BUILD_STRING(bs, 1))
2171  *bs->pos++ = '%';
2172  break;
2173 
2174  case '<':
2175  append_build_string(bs, (cli->utf8 ? "\342\200\230" : "'"), -1);
2176  break;
2177 
2178  case ',':
2179  case '>':
2180  append_build_string(bs, (cli->utf8 ? "\342\200\231" : "'"), -1);
2181  break;
2182 
2183  case 0:
2184  append_build_string(bs, "%", 1);
2185  goto done;
2186 
2187  default:
2188  if (ENSURE_BUILD_STRING(bs, 2)) {
2189  *bs->pos++ = '%';
2190  *bs->pos++ = *percent;
2191  }
2192  break;
2193 
2194  }
2195  fmt = ++percent;
2196  }
2197 
2198  done:
2199  append_build_string(bs, fmt, -1);
2200 }
2201 
2202 static const char* build_string_text(Clp_BuildString* bs, int report_oom) {
2203  if (bs->pos) {
2204  *bs->pos = 0;
2205  return bs->data;
2206  } else if (report_oom)
2207  return "out of memory\n";
2208  else
2209  return NULL;
2210 }
2211 
2212 static void
2214 {
2215  const char *text = build_string_text(bs, 1);
2216  if (clp->internal->error_handler != 0)
2217  (*clp->internal->error_handler)(clp, text);
2218  else
2219  fputs(text, stderr);
2220 }
2221 
2270 int
2271 Clp_OptionError(Clp_Parser *clp, const char *format, ...)
2272 {
2273  Clp_BuildString bs;
2274  va_list val;
2275  va_start(val, format);
2276  build_string_init(&bs, clp);
2277  Clp_vbsprintf(clp, &bs, format, val);
2278  append_build_string(&bs, "\n", 1);
2279  va_end(val);
2280  do_error(clp, &bs);
2281  build_string_cleanup(&bs);
2282  return bs.pos - bs.data;
2283 }
2284 
2294 int
2295 Clp_fprintf(Clp_Parser* clp, FILE* f, const char* format, ...)
2296 {
2297  Clp_BuildString bs;
2298  va_list val;
2299  va_start(val, format);
2300  build_string_init(&bs, NULL);
2301  Clp_vbsprintf(clp, &bs, format, val);
2302  va_end(val);
2303  if (bs.pos != bs.data)
2304  fwrite(bs.data, 1, bs.pos - bs.data, f);
2305  build_string_cleanup(&bs);
2306  return bs.pos - bs.data;
2307 }
2308 
2319 int
2320 Clp_vfprintf(Clp_Parser* clp, FILE* f, const char* format, va_list val)
2321 {
2322  Clp_BuildString bs;
2323  build_string_init(&bs, NULL);
2324  Clp_vbsprintf(clp, &bs, format, val);
2325  if (bs.pos != bs.data)
2326  fwrite(bs.data, 1, bs.pos - bs.data, f);
2327  build_string_cleanup(&bs);
2328  return bs.pos - bs.data;
2329 }
2330 
2345 int
2346 Clp_vsnprintf(Clp_Parser* clp, char* str, size_t size,
2347  const char* format, va_list val)
2348 {
2349  Clp_BuildString bs;
2350  build_string_init(&bs, NULL);
2351  Clp_vbsprintf(clp, &bs, format, val);
2352  if ((size_t) (bs.pos - bs.data) < size) {
2353  memcpy(str, bs.data, bs.pos - bs.data);
2354  str[bs.pos - bs.data] = 0;
2355  } else {
2356  memcpy(str, bs.data, size - 1);
2357  str[size - 1] = 0;
2358  }
2359  build_string_cleanup(&bs);
2360  return bs.pos - bs.data;
2361 }
2362 
2363 static int
2364 ambiguity_error(Clp_Parser *clp, int ambiguous, int *ambiguous_values,
2365  const Clp_Option *opt, const Clp_InternOption *iopt,
2366  const char *prefix, const char *fmt, ...)
2367 {
2368  Clp_Internal *cli = clp->internal;
2369  Clp_BuildString bs;
2370  int i;
2371  va_list val;
2372 
2373  va_start(val, fmt);
2374  build_string_init(&bs, clp);
2375  Clp_vbsprintf(clp, &bs, fmt, val);
2376  append_build_string(&bs, "\n", 1);
2377 
2379  append_build_string(&bs, "(Possibilities are", -1);
2380 
2381  for (i = 0; i < ambiguous && i < MAX_AMBIGUOUS_VALUES; i++) {
2382  int value = ambiguous_values[i];
2383  const char *no_dash = "";
2384  if (value < 0)
2385  value = -(value + 1), no_dash = "no-";
2386  if (i == 0)
2387  append_build_string(&bs, " ", 1);
2388  else if (i == ambiguous - 1)
2389  append_build_string(&bs, (i == 1 ? " and " : ", and "), -1);
2390  else
2391  append_build_string(&bs, ", ", 2);
2392  append_build_string(&bs, (cli->utf8 ? "\342\200\230" : "'"), -1);
2393  append_build_string(&bs, prefix, -1);
2394  append_build_string(&bs, no_dash, -1);
2395  append_build_string(&bs, opt[value].long_name + iopt[value].ilongoff, -1);
2396  append_build_string(&bs, (cli->utf8 ? "\342\200\231" : "'"), -1);
2397  }
2398 
2399  if (ambiguous > MAX_AMBIGUOUS_VALUES)
2400  append_build_string(&bs, ", and others", -1);
2401  append_build_string(&bs, ".)\n", -1);
2402  va_end(val);
2403 
2404  do_error(clp, &bs);
2405  build_string_cleanup(&bs);
2406  return 0;
2407 }
2408 
2409 static int
2410 copy_string(char *buf, int buflen, int bufpos, const char *what)
2411 {
2412  int l = strlen(what);
2413  if (l > buflen - bufpos - 1)
2414  l = buflen - bufpos - 1;
2415  memcpy(buf + bufpos, what, l);
2416  return l;
2417 }
2418 
2431 int
2432 Clp_CurOptionNameBuf(Clp_Parser *clp, char *buf, int len)
2433 {
2434  Clp_Internal *cli = clp->internal;
2435  int optno = cli->current_option;
2436  int pos = 0;
2437  if (optno < 0)
2438  pos += copy_string(buf, len, pos, "(no current option!)");
2439  else if (cli->current_short) {
2440  pos += copy_string(buf, len, pos, cli->option_chars);
2441  if (cli->utf8)
2442  pos = (encode_utf8(buf + pos, len - pos - 1, cli->opt[optno].short_name) - buf);
2443  else if (pos < len - 1)
2444  buf[pos++] = cli->opt[optno].short_name;
2445  } else if (cli->negated_by_no) {
2446  pos += copy_string(buf, len, pos, cli->option_chars);
2447  pos += copy_string(buf, len, pos, "no-");
2448  pos += copy_string(buf, len, pos, cli->opt[optno].long_name + cli->iopt[optno].ilongoff);
2449  } else {
2450  pos += copy_string(buf, len, pos, cli->option_chars);
2451  pos += copy_string(buf, len, pos, cli->opt[optno].long_name + cli->iopt[optno].ilongoff);
2452  }
2453  if (pos < len)
2454  buf[pos] = 0;
2455  return pos;
2456 }
2457 
2469 const char *
2471 {
2472  static char buf[256];
2473  Clp_CurOptionNameBuf(clp, buf, 256);
2474  return buf;
2475 }
2477 int
2478 Clp_IsLong(Clp_Parser *clp, const char *long_name)
2479 {
2480  Clp_Internal *cli = clp->internal;
2481  int optno = cli->current_option;
2482  return optno >= 0 && strcmp(cli->opt[optno].long_name, long_name) == 0;
2483 }
2484 
2485 int
2486 Clp_IsShort(Clp_Parser *clp, int short_name)
2487 {
2488  Clp_Internal *cli = clp->internal;
2489  int optno = cli->current_option;
2490  return optno >= 0 && cli->opt[optno].short_name == short_name;
2491 }
2492 
2493 #ifdef __cplusplus
2494 }
2495 #endif
Clp_Shift
const char * Clp_Shift(Clp_Parser *clp, int allow_options)
Return the next argument from clp without option parsing.
Definition: clp.c:1983
Clp_ParserState::negated_by_no
unsigned char negated_by_no
Definition: clp.c:236
Clp_ParserState::xtext
const char * xtext
Definition: clp.c:227
calculate_lmm
static void calculate_lmm(Clp_Parser *clp, const Clp_Option *opt, Clp_InternOption *iopt, int nopt)
Definition: clp.c:455
ENSURE_BUILD_STRING
#define ENSURE_BUILD_STRING(bs, space)
Definition: clp.c:2042
find_prefix_opt
static int find_prefix_opt(Clp_Parser *clp, const char *arg, int nopt, const Clp_Option *opt, const Clp_InternOption *iopt, int *ambiguous, int *ambiguous_values)
Definition: clp.c:947
build_string_program_prefix
static void build_string_program_prefix(Clp_BuildString *bs, const Clp_Parser *clp)
Definition: clp.c:2058
Clp_StringList
Definition: clp.c:240
Clp_ValParseFunc
int(* Clp_ValParseFunc)(Clp_Parser *clp, const char *vstr, int complain, void *user_data)
A value parsing function.
Definition: clp.h:219
Clp_ParserState::argc
int argc
Definition: clp.c:224
Clp_Internal::could_be_short
unsigned char could_be_short
Definition: clp.c:213
Clp_InternOption::ineg
unsigned ineg
Definition: clp.c:166
Clp_vsnprintf
int Clp_vsnprintf(Clp_Parser *clp, char *str, size_t size, const char *format, va_list val)
Format a message.
Definition: clp.c:2336
Clp_ParserState::current_option
int current_option
Definition: clp.c:232
Clp_ValType::val_type
int val_type
Definition: clp.c:154
encode_utf8
static char * encode_utf8(char *s, int n, int c)
Definition: clp.c:276
build_string_text
static const char * build_string_text(Clp_BuildString *bs, int report_oom)
Definition: clp.c:2192
do_error
static void do_error(Clp_Parser *clp, Clp_BuildString *bs)
Definition: clp.c:2203
next_argument
static int next_argument(Clp_Parser *clp, int want_argument)
Definition: clp.c:1560
Clp_InternOption::imandatory
unsigned imandatory
Definition: clp.c:163
long_as_short
static int long_as_short(const Clp_Internal *cli, const Clp_Option *o, Clp_InternOption *io, int failure)
Definition: clp.c:382
Clp_StringListLong
#define Clp_StringListLong
String list flag: values have long type.
Definition: clp.h:334
Clp_ParserState::argv
const char *const * argv
Definition: clp.c:223
Clp_Short
#define Clp_Short
Option character begins a set of short options.
Definition: clp.h:172
U_REPLACEMENT
#define U_REPLACEMENT
Definition: clp.c:273
Clp_Negate
#define Clp_Negate
Option flag: option may be negated.
Definition: clp.h:139
find_short
static int find_short(Clp_Parser *clp, const char *text)
Definition: clp.c:1769
Clp_Internal::utf8
int utf8
Definition: clp.c:200
Clp_InternOption::lmmpos
int lmmpos
Definition: clp.c:171
Clp_IsShort
int Clp_IsShort(Clp_Parser *clp, int short_name)
Test if the current option had short name name.
Definition: clp.c:2476
Clp_AddStringListType
int Clp_AddStringListType(Clp_Parser *clp, int val_type, int flags,...)
Define a new string list value type for clp.
Definition: clp.c:1285
Clp_ValStringNotOption
#define Clp_ValStringNotOption
Option value is a non-option string.
Definition: clp.h:62
max
#define max(a, b)
Definition: kcolor.h:31
Clp_Oclass::type
int type
Definition: clp.c:180
Clp_LongImplicit
#define Clp_LongImplicit
Option character can begin a long option, and is part of that long option.
Definition: clp.h:184
Clp_Option::option_id
int option_id
Definition: clp.h:46
parse_bool
static int parse_bool(Clp_Parser *, const char *, int, void *)
Definition: clp.c:1146
Clp_InternOption::lmmneg_short
unsigned lmmneg_short
Definition: clp.c:169
Clp_Mandatory
#define Clp_Mandatory
Option flag: value is mandatory.
Definition: clp.h:125
Clp_InternOption
Definition: clp.c:160
Clp_Oclass::c
int c
Definition: clp.c:179
Clp_Internal::long1neg
int long1neg
Definition: clp.c:199
Clp_ValUnsigned
#define Clp_ValUnsigned
Option value is an unsigned int.
Definition: clp.h:91
Clp_Internal::opt_generation
unsigned opt_generation
Definition: clp.c:188
Clp_Internal::argc
int argc
Definition: clp.c:194
Clp_SetOptionChar
int Clp_SetOptionChar(Clp_Parser *clp, int c, int type)
Set clp's treatment of character c.
Definition: clp.c:710
error
void error(const char *format,...)
Definition: gifdiff.c:439
Clp_BuildString::buf
char buf[256]
Definition: clp.c:2004
Clp_SetProgramName
const char * Clp_SetProgramName(Clp_Parser *clp, const char *name)
Set clp's program name.
Definition: clp.c:1419
Clp_OnlyNegated
#define Clp_OnlyNegated
Option flag: option must be negated.
Definition: clp.h:146
Clp_Done
#define Clp_Done
Clp_Next value: there are no more arguments.
Definition: clp.h:194
Clp_ValInt
#define Clp_ValInt
Option value is a signed int.
Definition: clp.h:78
Clp_fprintf
int Clp_fprintf(Clp_Parser *clp, FILE *f, const char *format,...)
Print a message.
Definition: clp.c:2285
Clp_CurOptionName
const char * Clp_CurOptionName(Clp_Parser *clp)
Extract the current option as a string.
Definition: clp.c:2460
argcmp
static int argcmp(const char *ref, const char *arg, int min_match, int fewer_dashes)
Definition: clp.c:909
Clp_Error
#define Clp_Error
Clp_Next value: internal CLP error.
Definition: clp.h:200
Clp_NotOption
#define Clp_NotOption
Clp_Next value: argument was not an option.
Definition: clp.h:191
compare
int compare(Gif_Stream *s1, Gif_Stream *s2)
Definition: gifdiff.c:238
copy_string
static int copy_string(char *buf, int buflen, int bufpos, const char *what)
Definition: clp.c:2400
Clp_Internal::xtext
const char * xtext
Definition: clp.c:203
Clp_BuildString::data
char * data
Definition: clp.c:2001
Clp_Internal::noclass
int noclass
Definition: clp.c:197
Clp_Parser
Command line parser.
Definition: clp.h:234
Clp_ValLong
#define Clp_ValLong
Option value is a signed long.
Definition: clp.h:104
Clp_Internal
struct Clp_Internal Clp_Internal
Clp_DeleteParser
void Clp_DeleteParser(Clp_Parser *clp)
Destroy a Clp_Parser object.
Definition: clp.c:579
Clp_BuildString::pos
char * pos
Definition: clp.c:2002
switch_to_short_argument
static void switch_to_short_argument(Clp_Parser *clp)
Definition: clp.c:1694
Clp_Option::long_name
const char * long_name
Definition: clp.h:42
Clp_Internal::option_chars
char option_chars[5]
Definition: clp.c:202
Clp_SetOptionProcessing
int Clp_SetOptionProcessing(Clp_Parser *clp, int on)
Set whether clp is searching for options.
Definition: clp.c:894
parse_string_list
static int parse_string_list(Clp_Parser *, const char *, int, void *)
Definition: clp.c:1181
Clp_DisallowOptions
#define Clp_DisallowOptions
Value type flag: value can't be an option string.
Definition: clp.h:314
Clp_ValDouble
#define Clp_ValDouble
Option value is a double. Accepts a real number as defined by strtod().
Definition: clp.h:110
uintptr_t
unsigned long uintptr_t
Definition: inttypes.h:25
Clp_Internal
Definition: clp.c:184
Clp_StringList::nitems_invalid_report
int nitems_invalid_report
Definition: clp.c:247
Clp_DeleteParserState
void Clp_DeleteParserState(Clp_ParserState *state)
Destroy a Clp_ParserState object.
Definition: clp.c:1470
clp_utf8_charlen
static int clp_utf8_charlen(const Clp_Internal *cli, const char *s)
Definition: clp.c:357
parse_double
static int parse_double(Clp_Parser *, const char *, int, void *)
Definition: clp.c:1128
Clp_InternOption::ipos
unsigned ipos
Definition: clp.c:165
parse_int
static int parse_int(Clp_Parser *, const char *, int, void *)
Definition: clp.c:1093
decode_utf8
static int decode_utf8(const char *s, const char **cp)
Definition: clp.c:300
Clp_Internal::nvaltype
int nvaltype
Definition: clp.c:191
Clp_Parser::option
const Clp_Option * option
Definition: clp.h:235
find_long
static int find_long(Clp_Parser *clp, const char *arg)
Definition: clp.c:1707
Clp_Optional
#define Clp_Optional
Option flag: value is optional.
Definition: clp.h:136
Clp_StringList
struct Clp_StringList Clp_StringList
Clp_Parser::s
const char * s
Definition: clp.h:249
Clp_NewParserState
Clp_ParserState * Clp_NewParserState(void)
Create a new Clp_ParserState.
Definition: clp.c:1446
Clp_ShortNegated
#define Clp_ShortNegated
Option character begins a set of negated short options.
Definition: clp.h:178
clp
static Clp_Parser * clp
Definition: gifdiff.c:58
Clp_ValUnsignedLong
#define Clp_ValUnsignedLong
Option value is an unsigned long.
Definition: clp.h:107
Clp_OptionChar
int Clp_OptionChar(Clp_Parser *clp, int c)
Return clp's treatment of character c.
Definition: clp.c:652
Clp_CurOptionNameBuf
int Clp_CurOptionNameBuf(Clp_Parser *clp, char *buf, int len)
Extract the current option as a string.
Definition: clp.c:2422
Clp_Parser::negated
int negated
Definition: clp.h:237
Clp_vfprintf
int Clp_vfprintf(Clp_Parser *clp, FILE *f, const char *format, va_list val)
Print a message.
Definition: clp.c:2310
Clp_Internal::current_short
unsigned char current_short
Definition: clp.c:214
Clp_ValBool
#define Clp_ValBool
Option value is a boolean.
Definition: clp.h:69
clp.h
Functions for parsing command line options.
Clp_StringList::val_long
unsigned char val_long
Definition: clp.c:246
Clp_OptionCharsSize
#define Clp_OptionCharsSize
Definition: clp.c:176
Clp_InternOption::ioptional
unsigned ioptional
Definition: clp.c:164
Clp_InternOption::ilong
unsigned ilong
Definition: clp.c:161
Clp_ValType
Definition: clp.c:153
get_oclass
static int get_oclass(Clp_Parser *clp, const char *text, int *ocharskip)
Definition: clp.c:1545
Clp_IsLong
int Clp_IsLong(Clp_Parser *clp, const char *long_name)
Test if the current option had long name name.
Definition: clp.c:2468
Clp_Oclass
Definition: clp.c:178
Clp_ValType::flags
int flags
Definition: clp.c:156
Clp_ParserState::option_processing
int option_processing
Definition: clp.c:229
Clp_Parser::l
long l
Definition: clp.h:246
Clp_InternOption::lmmneg
int lmmneg
Definition: clp.c:172
Clp_Internal::program_name
const char * program_name
Definition: clp.c:205
Clp_ValType::func
Clp_ValParseFunc func
Definition: clp.c:155
Clp_Parser::internal
struct Clp_Internal * internal
Definition: clp.h:265
Clp_StringList::nitems
int nitems
Definition: clp.c:243
Clp_SetErrorHandler
Clp_ErrorHandler Clp_SetErrorHandler(Clp_Parser *clp, void(*errh)(Clp_Parser *, const char *))
Definition: clp.c:614
min_different_chars
static int min_different_chars(const char *s, const char *t)
Definition: clp.c:367
Clp_Parser::u
unsigned u
Definition: clp.h:245
Clp_Internal::ambiguous_values
int ambiguous_values[4]
Definition: clp.c:218
utf8_charlen
static int utf8_charlen(const char *s)
Definition: clp.c:349
Clp_AddType
int Clp_AddType(Clp_Parser *clp, int val_type, int flags, Clp_ValParseFunc parser, void *user_data)
Define a new value type for clp.
Definition: clp.c:1041
Clp_BadOption
#define Clp_BadOption
Clp_Next value: argument was an erroneous option.
Definition: clp.h:197
Clp_Parser::user_data
void * user_data
Definition: clp.h:262
Clp_Internal::oclass
Clp_Oclass oclass[10]
Definition: clp.c:196
Clp_Internal::error_handler
void(* error_handler)(Clp_Parser *, const char *)
Definition: clp.c:206
Clp_InternOption::iprefmatch
unsigned iprefmatch
Definition: clp.c:167
Clp_AddStringListTypeVec
int Clp_AddStringListTypeVec(Clp_Parser *clp, int val_type, int flags, int nstrs, const char *const *strs, const int *vals)
Define a new string list value type for clp.
Definition: clp.c:1374
Clp_PreferredMatch
#define Clp_PreferredMatch
Option flag: prefer this option when matching.
Definition: clp.h:157
Clp_OclassSize
#define Clp_OclassSize
Definition: clp.c:182
Clp_InternOption::ishort
unsigned ishort
Definition: clp.c:162
Clp_SetArguments
void Clp_SetArguments(Clp_Parser *clp, int argc, const char *const *argv)
Set clp's arguments.
Definition: clp.c:871
Clp_Internal::whole_negated
unsigned char whole_negated
Definition: clp.c:212
Clp_Internal::negated_by_no
unsigned char negated_by_no
Definition: clp.c:215
parse_string
static int parse_string(Clp_Parser *, const char *, int, void *)
Definition: clp.c:1085
Clp_Option
Option description.
Definition: clp.h:41
Clp_Parser::ul
unsigned long ul
Definition: clp.h:247
Clp_RestoreParser
void Clp_RestoreParser(Clp_Parser *clp, const Clp_ParserState *state)
Restore parser state from state into clp.
Definition: clp.c:1513
Clp_ParserState
Definition: clp.c:222
val_type_binsearch
static int val_type_binsearch(Clp_Internal *cli, int val_type)
Definition: clp.c:994
Clp_Internal::argv
const char *const * argv
Definition: clp.c:193
ambiguity_error
static int ambiguity_error(Clp_Parser *, int, int *, const Clp_Option *, const Clp_InternOption *, const char *, const char *,...)
Definition: clp.c:2354
Clp_Internal::is_short
unsigned char is_short
Definition: clp.c:211
Clp_ParserState::option_chars
char option_chars[5]
Definition: clp.c:226
build_string_cleanup
static void build_string_cleanup(Clp_BuildString *bs)
Definition: clp.c:2016
Clp_ValType::user_data
void * user_data
Definition: clp.c:157
Clp_ParserState::whole_negated
unsigned char whole_negated
Definition: clp.c:234
Clp_OptionError
int Clp_OptionError(Clp_Parser *clp, const char *format,...)
Report a parser error.
Definition: clp.c:2261
Clp_Internal::option_processing
int option_processing
Definition: clp.c:208
append_build_string
static void append_build_string(Clp_BuildString *bs, const char *s, int l)
Definition: clp.c:2047
Clp_BuildString::end_data
char * end_data
Definition: clp.c:2003
Clp_Parser::have_val
int have_val
Definition: clp.h:239
Clp_Parser::vstr
const char * vstr
Definition: clp.h:240
clp_option_sentinel
static const Clp_Option clp_option_sentinel[]
Definition: clp.c:251
Clp_Internal::nopt
int nopt
Definition: clp.c:187
Clp_vbsprintf
static void Clp_vbsprintf(Clp_Parser *clp, Clp_BuildString *bs, const char *fmt, va_list val)
Definition: clp.c:2069
Clp_BuildString
struct Clp_BuildString Clp_BuildString
Clp_LongNegated
#define Clp_LongNegated
Option character begins a negated long option.
Definition: clp.h:181
Clp_SetOptions
int Clp_SetOptions(Clp_Parser *clp, int nopt, const Clp_Option *opt)
Set clp's option definitions.
Definition: clp.c:785
MAX_AMBIGUOUS_VALUES
#define MAX_AMBIGUOUS_VALUES
Definition: clp.c:151
Clp_BuildString
Definition: clp.c:1999
Clp_Next
int Clp_Next(Clp_Parser *clp)
Parse and return the next argument from clp.
Definition: clp.c:1835
finish_string_list
static int finish_string_list(Clp_Parser *clp, int val_type, int flags, Clp_Option *items, int nitems, int itemscap)
Definition: clp.c:1219
Clp_Internal::long1pos
int long1pos
Definition: clp.c:198
Clp_Option::val_type
int val_type
Definition: clp.h:48
Clp_ParserState::is_short
unsigned char is_short
Definition: clp.c:233
Clp_StringList::items
Clp_Option * items
Definition: clp.c:241
Clp_InternOption::ilongoff
unsigned char ilongoff
Definition: clp.c:170
Clp_SaveParser
void Clp_SaveParser(const Clp_Parser *clp, Clp_ParserState *state)
Save clp's current state in state.
Definition: clp.c:1480
set_option_text
static void set_option_text(Clp_Internal *cli, const char *text, int n_option_chars)
Definition: clp.c:1536
Clp_Option::flags
int flags
Definition: clp.h:50
Clp_Internal::ambiguous
int ambiguous
Definition: clp.c:217
Clp_ProgramName
const char * Clp_ProgramName(Clp_Parser *clp)
Return clp's program name.
Definition: clp.c:1407
Clp_Parser::val
union Clp_Parser::@0 val
Clp_DoubledLong
#define Clp_DoubledLong
Definition: clp.c:148
Clp_NewParser
Clp_Parser * Clp_NewParser(int argc, const char *const *argv, int nopt, const Clp_Option *opt)
Create a new Clp_Parser.
Definition: clp.c:503
Clp_ValString
#define Clp_ValString
Option value is an arbitrary string.
Definition: clp.h:59
Clp_Internal::opt
const Clp_Option * opt
Definition: clp.c:185
Clp_Internal::valtype
Clp_ValType * valtype
Definition: clp.c:190
Clp_ParserState::current_short
unsigned char current_short
Definition: clp.c:235
Clp_InitialValType
#define Clp_InitialValType
Definition: clp.c:150
Clp_ParserState::opt_generation
unsigned opt_generation
Definition: clp.c:231
Clp_Internal::iopt
Clp_InternOption * iopt
Definition: clp.c:186
Clp_ErrorHandler
void(* Clp_ErrorHandler)(Clp_Parser *clp, const char *message)
A function for reporting option errors.
Definition: clp.h:226
Clp_AllowNumbers
#define Clp_AllowNumbers
String list flag: allow explicit numbers.
Definition: clp.h:327
inttypes.h
Clp_Internal::current_option
int current_option
Definition: clp.c:209
Clp_Parser::i
int i
Definition: clp.h:244
Clp_Long
#define Clp_Long
Option character begins a long option.
Definition: clp.h:175
Clp_StringList::allow_int
unsigned char allow_int
Definition: clp.c:245
Clp_StringList::iopt
Clp_InternOption * iopt
Definition: clp.c:242
Clp_InternOption::lmmpos_short
unsigned lmmpos_short
Definition: clp.c:168
Clp_Parser::d
double d
Definition: clp.h:248
build_string_grow
static int build_string_grow(Clp_BuildString *bs, size_t want)
Definition: clp.c:2021
Clp_SetUTF8
int Clp_SetUTF8(Clp_Parser *clp, int utf8)
Set clp's UTF-8 mode.
Definition: clp.c:635
compare_options
static void compare_options(Clp_Parser *clp, const Clp_Option *o1, Clp_InternOption *io1, const Clp_Option *o2, Clp_InternOption *io2)
Definition: clp.c:398
Clp_Option::short_name
int short_name
Definition: clp.h:44
build_string_init
static void build_string_init(Clp_BuildString *bs, Clp_Parser *clp)
Definition: clp.c:2009