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