1 /*
2  * parseargs.h
3  *
4  * Command line argument parser.
5  *
6  * Copyright 1996-2003 Glyph & Cog, LLC
7  */
8 
9 /*========================================================================
10 
11  Modified under the Poppler project - http://poppler.freedesktop.org
12 
13  Poppler project changes to this file are under the GPLv2 or later license
14 
15  All changes made under the Poppler project to this file are licensed
16  under GPL version 2 or later
17 
18  Copyright (C) 2008, 2009 Albert Astals Cid <aacid@kde.org>
19 
20  To see a description of the changes please see the Changelog file that
21  came with your tarball or type make ChangeLog if you are building from git
22 
23 ========================================================================*/
24 
25 #include <stdio.h>
26 #include <stddef.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include "parseargs.h"
31 
32 #include "goo/gstrtod.h"
33 
34 static const ArgDesc *findArg(const ArgDesc *args, char *arg);
35 static GBool grabArg(const ArgDesc *arg, int i, int *argc, char *argv[]);
36 
parseArgs(const ArgDesc * args,int * argc,char * argv[])37 GBool parseArgs(const ArgDesc *args, int *argc, char *argv[]) {
38   const ArgDesc *arg;
39   int i, j;
40   GBool ok;
41 
42   ok = gTrue;
43   i = 1;
44   while (i < *argc) {
45     if (!strcmp(argv[i], "--")) {
46       --*argc;
47       for (j = i; j < *argc; ++j)
48 	argv[j] = argv[j+1];
49       break;
50     } else if ((arg = findArg(args, argv[i]))) {
51       if (!grabArg(arg, i, argc, argv))
52 	ok = gFalse;
53     } else {
54       ++i;
55     }
56   }
57   return ok;
58 }
59 
printUsage(char * program,char * otherArgs,const ArgDesc * args)60 void printUsage(char *program, char *otherArgs, const ArgDesc *args) {
61   const ArgDesc *arg;
62   char *typ;
63   int w, w1;
64 
65   w = 0;
66   for (arg = args; arg->arg; ++arg) {
67     if ((w1 = strlen(arg->arg)) > w)
68       w = w1;
69   }
70 
71   fprintf(stderr, "Usage: %s [options]", program);
72   if (otherArgs)
73     fprintf(stderr, " %s", otherArgs);
74   fprintf(stderr, "\n");
75 
76   for (arg = args; arg->arg; ++arg) {
77     fprintf(stderr, "  %s", arg->arg);
78     w1 = 9 + w - strlen(arg->arg);
79     switch (arg->kind) {
80     case argInt:
81     case argIntDummy:
82       typ = " <int>";
83       break;
84     case argFP:
85     case argFPDummy:
86       typ = " <fp>";
87       break;
88     case argString:
89     case argStringDummy:
90       typ = " <string>";
91       break;
92     case argFlag:
93     case argFlagDummy:
94     default:
95       typ = "";
96       break;
97     }
98     fprintf(stderr, "%-*s", w1, typ);
99     if (arg->usage)
100       fprintf(stderr, ": %s", arg->usage);
101     fprintf(stderr, "\n");
102   }
103 }
104 
findArg(const ArgDesc * args,char * arg)105 static const ArgDesc *findArg(const ArgDesc *args, char *arg) {
106   const ArgDesc *p;
107 
108   for (p = args; p->arg; ++p) {
109     if (p->kind < argFlagDummy && !strcmp(p->arg, arg))
110       return p;
111   }
112   return NULL;
113 }
114 
grabArg(const ArgDesc * arg,int i,int * argc,char * argv[])115 static GBool grabArg(const ArgDesc *arg, int i, int *argc, char *argv[]) {
116   int n;
117   int j;
118   GBool ok;
119 
120   ok = gTrue;
121   n = 0;
122   switch (arg->kind) {
123   case argFlag:
124     *(GBool *)arg->val = gTrue;
125     n = 1;
126     break;
127   case argInt:
128     if (i + 1 < *argc && isInt(argv[i+1])) {
129       *(int *)arg->val = atoi(argv[i+1]);
130       n = 2;
131     } else {
132       ok = gFalse;
133       n = 1;
134     }
135     break;
136   case argFP:
137     if (i + 1 < *argc && isFP(argv[i+1])) {
138       *(double *)arg->val = gatof(argv[i+1]);
139       n = 2;
140     } else {
141       ok = gFalse;
142       n = 1;
143     }
144     break;
145   case argString:
146     if (i + 1 < *argc) {
147       strncpy((char *)arg->val, argv[i+1], arg->size - 1);
148       ((char *)arg->val)[arg->size - 1] = '\0';
149       n = 2;
150     } else {
151       ok = gFalse;
152       n = 1;
153     }
154     break;
155   default:
156     fprintf(stderr, "Internal error in arg table\n");
157     n = 1;
158     break;
159   }
160   if (n > 0) {
161     *argc -= n;
162     for (j = i; j < *argc; ++j)
163       argv[j] = argv[j+n];
164   }
165   return ok;
166 }
167 
isInt(char * s)168 GBool isInt(char *s) {
169   if (*s == '-' || *s == '+')
170     ++s;
171   while (isdigit(*s))
172     ++s;
173   if (*s)
174     return gFalse;
175   return gTrue;
176 }
177 
isFP(char * s)178 GBool isFP(char *s) {
179   int n;
180 
181   if (*s == '-' || *s == '+')
182     ++s;
183   n = 0;
184   while (isdigit(*s)) {
185     ++s;
186     ++n;
187   }
188   if (*s == '.')
189     ++s;
190   while (isdigit(*s)) {
191     ++s;
192     ++n;
193   }
194   if (n > 0 && (*s == 'e' || *s == 'E')) {
195     ++s;
196     if (*s == '-' || *s == '+')
197       ++s;
198     n = 0;
199     if (!isdigit(*s))
200       return gFalse;
201     do {
202       ++s;
203     } while (isdigit(*s));
204   }
205   if (*s)
206     return gFalse;
207   return gTrue;
208 }
209