comparison mupdf-source/source/fitz/getopt.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
comparison
equal deleted inserted replaced
1:1d09e1dec1d9 2:b50eed0cc0ef
1 /*
2 * This is a version of the public domain getopt implementation by
3 * Henry Spencer originally posted to net.sources.
4 *
5 * This file is in the public domain.
6 */
7
8 #include <stdio.h>
9 #include <string.h>
10
11 #include "mupdf/fitz/getopt.h"
12 #include "mupdf/fitz/string-util.h"
13
14 char *fz_optarg; /* Global argument pointer. */
15 int fz_optind = 0; /* Global argv index. */
16 const fz_getopt_long_options *fz_optlong = NULL;
17 int fz_optitem = 0; /* Which item in a long opt list is selected? */
18
19 static int
20 match_long_option(int argc, char * const *argv, const fz_getopt_long_options *longopts, char *opt)
21 {
22 if (longopts == NULL)
23 {
24 fprintf(stderr, "%s: unknown option --%s\n", argv[0], opt);
25 return '?';
26 }
27
28 while (longopts->option)
29 {
30 const char *s = longopts->option;
31 const char *eq = strchr(s, '=');
32 size_t z = eq ? (size_t)(eq-s) : strlen(s);
33 int arg = 0; /* No arg */
34
35 if (s[z] == '=')
36 arg = 1; /* arg = 1 => Arg list given */
37 else if (z && s[z-1] == ':')
38 arg = 2, z--; /* arg = 2 -> argument expected */
39
40 /* If we don't match, try the next one. */
41 /* If we aren't expecting an argument, and the given string is longer than expected, try the next one. */
42 /* If we are expecting an argument, and the given string doesn't either terminate or end in '=', try the next one. */
43 if (strncmp(s, opt, z) || (arg == 0 && opt[z] != 0) || (arg != 0 && opt[z] != 0 && opt[z] != '='))
44 {
45 longopts++;
46 continue;
47 }
48
49 /* So we have a match. */
50 fz_optind++;
51 if (opt[z])
52 fz_optarg = &opt[z+1];
53 else if (fz_optind < argc)
54 fz_optarg = argv[fz_optind++];
55 else
56 {
57 fprintf(stderr, "%s: option requires argument --%s\n", argv[0], s);
58 return ':';
59 }
60
61 /* If there is an arg from a predefined list, try to match that here. */
62 if (arg == 1)
63 {
64 fz_optitem = fz_opt_from_list(&opt[z+1], &s[z+1]);
65 if (longopts->flag)
66 *longopts->flag = fz_optitem;
67 if (fz_optitem < 0)
68 return '?';
69 }
70 else if (arg == 2 && longopts->flag)
71 {
72 char *p = strchr(fz_optarg, ',');
73 if (*fz_optarg == 0)
74 {
75 fprintf(stderr, "%s: option requires argument --%s\n", argv[0], s);
76 return ':';
77 }
78 else if (!fz_strcasecmp(fz_optarg, "yes") || !fz_strcasecmp(fz_optarg, "on") || !fz_strcasecmp(fz_optarg, "true"))
79 *longopts->flag = 1;
80 else if (!fz_strcasecmp(fz_optarg, "no") || !fz_strcasecmp(fz_optarg, "off") || !fz_strcasecmp(fz_optarg, "false"))
81 *longopts->flag = 0;
82 else
83 *longopts->flag = fz_atoi(fz_optarg);
84 fz_optarg = p ? p+1 : NULL;
85 }
86 fz_optlong = longopts;
87 return 0;
88 }
89
90 fprintf(stderr, "%s: unknown option --%s\n", argv[0], opt);
91 return '?';
92 }
93
94 static char *scan = NULL; /* Private scan pointer. */
95
96 int
97 fz_getopt_long(int argc, char * const *argv, const char *optstring, const fz_getopt_long_options *longopts)
98 {
99 int c;
100 const char *place;
101
102 fz_optarg = NULL;
103 fz_optlong = NULL;
104 fz_optitem = -1;
105
106 while (!scan || *scan == '\0')
107 {
108 if (fz_optind == 0)
109 fz_optind++;
110
111 if (fz_optind >= argc || argv[fz_optind][0] != '-' || argv[fz_optind][1] == '\0')
112 return EOF;
113 if (argv[fz_optind][1] == '-' && argv[fz_optind][2] == '\0') {
114 fz_optind++;
115 return EOF;
116 }
117 if (argv[fz_optind][1] == '-')
118 {
119 scan = NULL;
120 return match_long_option(argc, argv, longopts, &argv[fz_optind][2]);
121 }
122
123 scan = argv[fz_optind]+1;
124 fz_optind++;
125 }
126
127 c = *scan++;
128 place = strchr(optstring, c);
129
130 if (!place || c == ':') {
131 fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
132 return '?';
133 }
134
135 place++;
136 if (*place == ':') {
137 if (*scan != '\0') {
138 fz_optarg = scan;
139 scan = NULL;
140 } else if( fz_optind < argc ) {
141 fz_optarg = argv[fz_optind];
142 fz_optind++;
143 } else {
144 fprintf(stderr, "%s: option requires argument -%c\n", argv[0], c);
145 return ':';
146 }
147 }
148
149 return c;
150 }
151
152 int
153 fz_getopt(int argc, char *const *argv, const char *optstring)
154 {
155 return fz_getopt_long(argc, argv, optstring, NULL);
156 }
157
158 int
159 fz_opt_from_list(char *opt, const char *optlist)
160 {
161 int n = 0;
162
163 while (*optlist)
164 {
165 const char *optend = optlist;
166
167 if (*optend == '*')
168 {
169 fz_optarg = opt;
170 return n;
171 }
172
173 while (*optend != 0 && *optend != '|' && *optend != ':')
174 optend++;
175
176 if (fz_strncasecmp(optlist, opt, optend-optlist))
177 {
178 /* We didn't match. Carry on. */
179 }
180 else if (opt[optend-optlist] == 0)
181 {
182 /* We matched, ending in NUL */
183 fz_optarg = NULL;
184 return n;
185 }
186 else if (*optend == ':' && opt[optend-optlist] == ':')
187 {
188 /* We matched, and we both have some arguments and expected some. */
189 fz_optarg = &opt[optend-optlist+1];
190 return n;
191 }
192
193 n++;
194 if (*optend == ':')
195 {
196 optend++;
197 if (*optend == '|')
198 optend++;
199 else if (*optend != 0)
200 {
201 fprintf(stderr, "Malformed options string");
202 return -1;
203 }
204 }
205 if (*optend == '|')
206 optend++;
207 optlist = optend;
208 }
209
210 fprintf(stderr, "Unrecognised option argument: %s\n", opt);
211 return -1;
212 }
213
214 char *
215 fz_optpath(char *opt)
216 {
217 if (!strcmp(opt, "-"))
218 return "/dev/stdout";
219 #ifdef _WIN32
220 if (!fz_strcasecmp(opt, "con"))
221 return "/dev/stdout";
222 if (!fz_strcasecmp(opt, "nul"))
223 return "/dev/null";
224 #endif
225 return opt;
226 }