1 /*
2 * parseargs.cc
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, 2018 Albert Astals Cid <aacid@kde.org>
19 Copyright (C) 2011, 2012 Adrian Johnson <ajohnson@redneon.com>
20
21 To see a description of the changes please see the Changelog file that
22 came with your tarball or type make ChangeLog if you are building from git
23
24 ========================================================================*/
25
26 #include <cstdio>
27 #include <cstddef>
28 #include <cstring>
29 #include <cstdlib>
30 #include <cctype>
31 #include "parseargs.h"
32
33 #include "goo/gstrtod.h"
34 #include "goo/GooString.h"
35
36 static const ArgDesc *findArg(const ArgDesc *args, char *arg);
37 static bool grabArg(const ArgDesc *arg, int i, int *argc, char *argv[]);
38
parseArgs(const ArgDesc * args,int * argc,char * argv[])39 bool parseArgs(const ArgDesc *args, int *argc, char *argv[])
40 {
41 const ArgDesc *arg;
42 int i, j;
43 bool ok;
44
45 ok = true;
46 i = 1;
47 while (i < *argc) {
48 if (!strcmp(argv[i], "--")) {
49 --*argc;
50 for (j = i; j < *argc; ++j)
51 argv[j] = argv[j + 1];
52 break;
53 } else if ((arg = findArg(args, argv[i]))) {
54 if (!grabArg(arg, i, argc, argv))
55 ok = false;
56 } else {
57 ++i;
58 }
59 }
60 return ok;
61 }
62
printUsage(const char * program,const char * otherArgs,const ArgDesc * args)63 void printUsage(const char *program, const char *otherArgs, const ArgDesc *args)
64 {
65 const ArgDesc *arg;
66 const char *typ;
67 int w, w1;
68
69 w = 0;
70 for (arg = args; arg->arg; ++arg) {
71 if ((w1 = strlen(arg->arg)) > w)
72 w = w1;
73 }
74
75 fprintf(stderr, "Usage: %s [options]", program);
76 if (otherArgs)
77 fprintf(stderr, " %s", otherArgs);
78 fprintf(stderr, "\n");
79
80 for (arg = args; arg->arg; ++arg) {
81 fprintf(stderr, " %s", arg->arg);
82 w1 = 9 + w - strlen(arg->arg);
83 switch (arg->kind) {
84 case argInt:
85 case argIntDummy:
86 typ = " <int>";
87 break;
88 case argFP:
89 case argFPDummy:
90 typ = " <fp>";
91 break;
92 case argString:
93 case argStringDummy:
94 case argGooString:
95 typ = " <string>";
96 break;
97 case argFlag:
98 case argFlagDummy:
99 default:
100 typ = "";
101 break;
102 }
103 fprintf(stderr, "%-*s", w1, typ);
104 if (arg->usage)
105 fprintf(stderr, ": %s", arg->usage);
106 fprintf(stderr, "\n");
107 }
108 }
109
findArg(const ArgDesc * args,char * arg)110 static const ArgDesc *findArg(const ArgDesc *args, char *arg)
111 {
112 const ArgDesc *p;
113
114 for (p = args; p->arg; ++p) {
115 if (p->kind < argFlagDummy && !strcmp(p->arg, arg))
116 return p;
117 }
118 return nullptr;
119 }
120
grabArg(const ArgDesc * arg,int i,int * argc,char * argv[])121 static bool grabArg(const ArgDesc *arg, int i, int *argc, char *argv[])
122 {
123 int n;
124 int j;
125 bool ok;
126
127 ok = true;
128 n = 0;
129 switch (arg->kind) {
130 case argFlag:
131 *(bool *)arg->val = true;
132 n = 1;
133 break;
134 case argInt:
135 if (i + 1 < *argc && isInt(argv[i + 1])) {
136 *(int *)arg->val = atoi(argv[i + 1]);
137 n = 2;
138 } else {
139 ok = false;
140 n = 1;
141 }
142 break;
143 case argFP:
144 if (i + 1 < *argc && isFP(argv[i + 1])) {
145 *(double *)arg->val = gatof(argv[i + 1]);
146 n = 2;
147 } else {
148 ok = false;
149 n = 1;
150 }
151 break;
152 case argString:
153 if (i + 1 < *argc) {
154 strncpy((char *)arg->val, argv[i + 1], arg->size - 1);
155 ((char *)arg->val)[arg->size - 1] = '\0';
156 n = 2;
157 } else {
158 ok = false;
159 n = 1;
160 }
161 break;
162 case argGooString:
163 if (i + 1 < *argc) {
164 ((GooString *)arg->val)->Set(argv[i + 1]);
165 n = 2;
166 } else {
167 ok = false;
168 n = 1;
169 }
170 break;
171 default:
172 fprintf(stderr, "Internal error in arg table\n");
173 n = 1;
174 break;
175 }
176 if (n > 0) {
177 *argc -= n;
178 for (j = i; j < *argc; ++j)
179 argv[j] = argv[j + n];
180 }
181 return ok;
182 }
183
isInt(const char * s)184 bool isInt(const char *s)
185 {
186 if (*s == '-' || *s == '+')
187 ++s;
188 while (isdigit(*s))
189 ++s;
190 if (*s)
191 return false;
192 return true;
193 }
194
isFP(const char * s)195 bool isFP(const char *s)
196 {
197 int n;
198
199 if (*s == '-' || *s == '+')
200 ++s;
201 n = 0;
202 while (isdigit(*s)) {
203 ++s;
204 ++n;
205 }
206 if (*s == '.')
207 ++s;
208 while (isdigit(*s)) {
209 ++s;
210 ++n;
211 }
212 if (n > 0 && (*s == 'e' || *s == 'E')) {
213 ++s;
214 if (*s == '-' || *s == '+')
215 ++s;
216 n = 0;
217 if (!isdigit(*s))
218 return false;
219 do {
220 ++s;
221 } while (isdigit(*s));
222 }
223 if (*s)
224 return false;
225 return true;
226 }
227