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
36static const ArgDesc *findArg(const ArgDesc *args, char *arg);
37static bool grabArg(const ArgDesc *arg, int i, int *argc, char *argv[]);
38
39bool 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(s1: argv[i], s2: "--")) {
49 --*argc;
50 for (j = i; j < *argc; ++j) {
51 argv[j] = argv[j + 1];
52 }
53 break;
54 } else if ((arg = findArg(args, arg: argv[i]))) {
55 if (!grabArg(arg, i, argc, argv)) {
56 ok = false;
57 }
58 } else {
59 ++i;
60 }
61 }
62 return ok;
63}
64
65void printUsage(const char *program, const char *otherArgs, const ArgDesc *args)
66{
67 const ArgDesc *arg;
68 const char *typ;
69 int w, w1;
70
71 w = 0;
72 for (arg = args; arg->arg; ++arg) {
73 if ((w1 = strlen(s: arg->arg)) > w) {
74 w = w1;
75 }
76 }
77
78 fprintf(stderr, format: "Usage: %s [options]", program);
79 if (otherArgs) {
80 fprintf(stderr, format: " %s", otherArgs);
81 }
82 fprintf(stderr, format: "\n");
83
84 for (arg = args; arg->arg; ++arg) {
85 fprintf(stderr, format: " %s", arg->arg);
86 w1 = 9 + w - strlen(s: arg->arg);
87 switch (arg->kind) {
88 case argInt:
89 case argIntDummy:
90 typ = " <int>";
91 break;
92 case argFP:
93 case argFPDummy:
94 typ = " <fp>";
95 break;
96 case argString:
97 case argStringDummy:
98 case argGooString:
99 typ = " <string>";
100 break;
101 case argFlag:
102 case argFlagDummy:
103 default:
104 typ = "";
105 break;
106 }
107 fprintf(stderr, format: "%-*s", w1, typ);
108 if (arg->usage) {
109 fprintf(stderr, format: ": %s", arg->usage);
110 }
111 fprintf(stderr, format: "\n");
112 }
113}
114
115static const ArgDesc *findArg(const ArgDesc *args, char *arg)
116{
117 const ArgDesc *p;
118
119 for (p = args; p->arg; ++p) {
120 if (p->kind < argFlagDummy && !strcmp(s1: p->arg, s2: arg)) {
121 return p;
122 }
123 }
124 return nullptr;
125}
126
127static bool grabArg(const ArgDesc *arg, int i, int *argc, char *argv[])
128{
129 int n;
130 int j;
131 bool ok;
132
133 ok = true;
134 n = 0;
135 switch (arg->kind) {
136 case argFlag:
137 *(bool *)arg->val = true;
138 n = 1;
139 break;
140 case argInt:
141 if (i + 1 < *argc && isInt(s: argv[i + 1])) {
142 *(int *)arg->val = atoi(nptr: argv[i + 1]);
143 n = 2;
144 } else {
145 ok = false;
146 n = 1;
147 }
148 break;
149 case argFP:
150 if (i + 1 < *argc && isFP(s: argv[i + 1])) {
151 *(double *)arg->val = gatof(nptr: argv[i + 1]);
152 n = 2;
153 } else {
154 ok = false;
155 n = 1;
156 }
157 break;
158 case argString:
159 if (i + 1 < *argc) {
160 strncpy(dest: (char *)arg->val, src: argv[i + 1], n: arg->size - 1);
161 ((char *)arg->val)[arg->size - 1] = '\0';
162 n = 2;
163 } else {
164 ok = false;
165 n = 1;
166 }
167 break;
168 case argGooString:
169 if (i + 1 < *argc) {
170 ((GooString *)arg->val)->Set(argv[i + 1]);
171 n = 2;
172 } else {
173 ok = false;
174 n = 1;
175 }
176 break;
177 default:
178 fprintf(stderr, format: "Internal error in arg table\n");
179 n = 1;
180 break;
181 }
182 if (n > 0) {
183 *argc -= n;
184 for (j = i; j < *argc; ++j) {
185 argv[j] = argv[j + n];
186 }
187 }
188 return ok;
189}
190
191bool isInt(const char *s)
192{
193 if (*s == '-' || *s == '+') {
194 ++s;
195 }
196 while (isdigit(*s)) {
197 ++s;
198 }
199 if (*s) {
200 return false;
201 }
202 return true;
203}
204
205bool isFP(const char *s)
206{
207 int n;
208
209 if (*s == '-' || *s == '+') {
210 ++s;
211 }
212 n = 0;
213 while (isdigit(*s)) {
214 ++s;
215 ++n;
216 }
217 if (*s == '.') {
218 ++s;
219 }
220 while (isdigit(*s)) {
221 ++s;
222 ++n;
223 }
224 if (n > 0 && (*s == 'e' || *s == 'E')) {
225 ++s;
226 if (*s == '-' || *s == '+') {
227 ++s;
228 }
229 n = 0;
230 if (!isdigit(*s)) {
231 return false;
232 }
233 do {
234 ++s;
235 } while (isdigit(*s));
236 }
237 if (*s) {
238 return false;
239 }
240 return true;
241}
242

source code of poppler/utils/parseargs.cc