Initial commit
netzel

netzel commited on 2024-02-21 23:00:28
Showing 7 changed files, with 7107 additions and 0 deletions.

... ...
@@ -0,0 +1,4955 @@
1
+/*******************************************************************************
2
+ * This file is part of the argtable3 library.
3
+ *
4
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
5
+ * <sheitmann@users.sourceforge.net>
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ *     * Redistributions of source code must retain the above copyright
11
+ *       notice, this list of conditions and the following disclaimer.
12
+ *     * Redistributions in binary form must reproduce the above copyright
13
+ *       notice, this list of conditions and the following disclaimer in the
14
+ *       documentation and/or other materials provided with the distribution.
15
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
16
+ *       may be used to endorse or promote products derived from this software
17
+ *       without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ ******************************************************************************/
30
+
31
+#include "argtable3.h"
32
+
33
+/*******************************************************************************
34
+ * This file is part of the argtable3 library.
35
+ *
36
+ * Copyright (C) 2013 Tom G. Huang
37
+ * <tomghuang@gmail.com>
38
+ * All rights reserved.
39
+ *
40
+ * Redistribution and use in source and binary forms, with or without
41
+ * modification, are permitted provided that the following conditions are met:
42
+ *     * Redistributions of source code must retain the above copyright
43
+ *       notice, this list of conditions and the following disclaimer.
44
+ *     * Redistributions in binary form must reproduce the above copyright
45
+ *       notice, this list of conditions and the following disclaimer in the
46
+ *       documentation and/or other materials provided with the distribution.
47
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
48
+ *       may be used to endorse or promote products derived from this software
49
+ *       without specific prior written permission.
50
+ *
51
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
52
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
55
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
56
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
58
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
59
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
60
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
61
+ ******************************************************************************/
62
+
63
+#ifndef ARG_UTILS_H
64
+#define ARG_UTILS_H
65
+
66
+#define ARG_ENABLE_TRACE 0
67
+#define ARG_ENABLE_LOG 1
68
+
69
+#ifdef __cplusplus
70
+extern "C" {
71
+#endif
72
+
73
+enum
74
+{
75
+    EMINCOUNT = 1,
76
+    EMAXCOUNT,
77
+    EBADINT,
78
+    EOVERFLOW,
79
+    EBADDOUBLE,
80
+    EBADDATE,
81
+    EREGNOMATCH
82
+};
83
+
84
+
85
+#if defined(_MSC_VER)
86
+#define ARG_TRACE(x) \
87
+    __pragma(warning(push)) \
88
+    __pragma(warning(disable:4127)) \
89
+    do { if (ARG_ENABLE_TRACE) dbg_printf x; } while (0) \
90
+    __pragma(warning(pop))
91
+
92
+#define ARG_LOG(x) \
93
+    __pragma(warning(push)) \
94
+    __pragma(warning(disable:4127)) \
95
+    do { if (ARG_ENABLE_LOG) dbg_printf x; } while (0) \
96
+    __pragma(warning(pop))
97
+#else
98
+#define ARG_TRACE(x) \
99
+    do { if (ARG_ENABLE_TRACE) dbg_printf x; } while (0)
100
+
101
+#define ARG_LOG(x) \
102
+    do { if (ARG_ENABLE_LOG) dbg_printf x; } while (0)
103
+#endif 
104
+
105
+extern void dbg_printf(const char *fmt, ...);
106
+
107
+#ifdef __cplusplus
108
+}
109
+#endif
110
+
111
+#endif
112
+
113
+/*******************************************************************************
114
+ * This file is part of the argtable3 library.
115
+ *
116
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
117
+ * <sheitmann@users.sourceforge.net>
118
+ * All rights reserved.
119
+ *
120
+ * Redistribution and use in source and binary forms, with or without
121
+ * modification, are permitted provided that the following conditions are met:
122
+ *     * Redistributions of source code must retain the above copyright
123
+ *       notice, this list of conditions and the following disclaimer.
124
+ *     * Redistributions in binary form must reproduce the above copyright
125
+ *       notice, this list of conditions and the following disclaimer in the
126
+ *       documentation and/or other materials provided with the distribution.
127
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
128
+ *       may be used to endorse or promote products derived from this software
129
+ *       without specific prior written permission.
130
+ *
131
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
132
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
133
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
134
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
135
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
136
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
137
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
138
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
139
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
140
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
141
+ ******************************************************************************/
142
+
143
+#include <stdarg.h>
144
+#include <stdio.h>
145
+
146
+
147
+void dbg_printf(const char *fmt, ...)
148
+{
149
+    va_list args;
150
+    va_start(args, fmt);
151
+    vfprintf(stderr, fmt, args);
152
+    va_end(args);
153
+}
154
+
155
+/*	$Id: getopt.h,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */
156
+/*	$OpenBSD: getopt.h,v 1.1 2002/12/03 20:24:29 millert Exp $	*/
157
+/*	$NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $	*/
158
+
159
+/*-
160
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
161
+ * All rights reserved.
162
+ *
163
+ * This code is derived from software contributed to The NetBSD Foundation
164
+ * by Dieter Baron and Thomas Klausner.
165
+ *
166
+ * Redistribution and use in source and binary forms, with or without
167
+ * modification, are permitted provided that the following conditions
168
+ * are met:
169
+ * 1. Redistributions of source code must retain the above copyright
170
+ *    notice, this list of conditions and the following disclaimer.
171
+ * 2. Redistributions in binary form must reproduce the above copyright
172
+ *    notice, this list of conditions and the following disclaimer in the
173
+ *    documentation and/or other materials provided with the distribution.
174
+ * 3. All advertising materials mentioning features or use of this software
175
+ *    must display the following acknowledgement:
176
+ *        This product includes software developed by the NetBSD
177
+ *        Foundation, Inc. and its contributors.
178
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
179
+ *    contributors may be used to endorse or promote products derived
180
+ *    from this software without specific prior written permission.
181
+ *
182
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
183
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
184
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
185
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
186
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
187
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
188
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
189
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
190
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
191
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
192
+ * POSSIBILITY OF SUCH DAMAGE.
193
+ */
194
+
195
+#ifndef _GETOPT_H_
196
+#define _GETOPT_H_
197
+
198
+#if 0
199
+#include <sys/cdefs.h>
200
+#endif
201
+
202
+/*
203
+ * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions
204
+ */
205
+#define no_argument        0
206
+#define required_argument  1
207
+#define optional_argument  2
208
+
209
+struct option {
210
+	/* name of long option */
211
+	const char *name;
212
+	/*
213
+	 * one of no_argument, required_argument, and optional_argument:
214
+	 * whether option takes an argument
215
+	 */
216
+	int has_arg;
217
+	/* if not NULL, set *flag to val when option found */
218
+	int *flag;
219
+	/* if flag not NULL, value to set *flag to; else return value */
220
+	int val;
221
+};
222
+
223
+#ifdef __cplusplus
224
+extern "C" {
225
+#endif
226
+
227
+int	 getopt_long(int, char * const *, const char *,
228
+	    const struct option *, int *);
229
+int	 getopt_long_only(int, char * const *, const char *,
230
+	    const struct option *, int *);
231
+#ifndef _GETOPT_DEFINED
232
+#define _GETOPT_DEFINED
233
+int	 getopt(int, char * const *, const char *);
234
+int	 getsubopt(char **, char * const *, char **);
235
+
236
+extern   char *optarg;                  /* getopt(3) external variables */
237
+extern   int opterr;
238
+extern   int optind;
239
+extern   int optopt;
240
+extern   int optreset;
241
+extern   char *suboptarg;               /* getsubopt(3) external variable */
242
+#endif /* _GETOPT_DEFINED */
243
+ 
244
+#ifdef __cplusplus
245
+}
246
+#endif
247
+#endif /* !_GETOPT_H_ */
248
+/*	$Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $	*/
249
+/*	$OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $	*/
250
+/*	$NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $	*/
251
+
252
+/*
253
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
254
+ *
255
+ * Permission to use, copy, modify, and distribute this software for any
256
+ * purpose with or without fee is hereby granted, provided that the above
257
+ * copyright notice and this permission notice appear in all copies.
258
+ *
259
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
260
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
261
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
262
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
263
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
264
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
265
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
266
+ *
267
+ * Sponsored in part by the Defense Advanced Research Projects
268
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
269
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
270
+ */
271
+
272
+#ifndef lint
273
+//static const char rcsid[]="$Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $";
274
+#endif /* lint */
275
+/*-
276
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
277
+ * All rights reserved.
278
+ *
279
+ * This code is derived from software contributed to The NetBSD Foundation
280
+ * by Dieter Baron and Thomas Klausner.
281
+ *
282
+ * Redistribution and use in source and binary forms, with or without
283
+ * modification, are permitted provided that the following conditions
284
+ * are met:
285
+ * 1. Redistributions of source code must retain the above copyright
286
+ *    notice, this list of conditions and the following disclaimer.
287
+ * 2. Redistributions in binary form must reproduce the above copyright
288
+ *    notice, this list of conditions and the following disclaimer in the
289
+ *    documentation and/or other materials provided with the distribution.
290
+ *
291
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
292
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
293
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
294
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
295
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
296
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
297
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
298
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
299
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
300
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
301
+ * POSSIBILITY OF SUCH DAMAGE.
302
+ */
303
+
304
+#if 0
305
+#include <err.h>
306
+#endif
307
+#include <errno.h>
308
+#include <stdlib.h>
309
+#include <string.h>
310
+
311
+
312
+#define	REPLACE_GETOPT		/* use this getopt as the system getopt(3) */
313
+
314
+#ifdef REPLACE_GETOPT
315
+int	opterr = 1;		/* if error message should be printed */
316
+int	optind = 1;		/* index into parent argv vector */
317
+int	optopt = '?';		/* character checked for validity */
318
+int	optreset;		/* reset getopt */
319
+char    *optarg;		/* argument associated with option */
320
+#endif
321
+
322
+#define PRINT_ERROR	((opterr) && (*options != ':'))
323
+
324
+#define FLAG_PERMUTE	0x01	/* permute non-options to the end of argv */
325
+#define FLAG_ALLARGS	0x02	/* treat non-options as args to option "-1" */
326
+#define FLAG_LONGONLY	0x04	/* operate as getopt_long_only */
327
+
328
+/* return values */
329
+#define	BADCH		(int)'?'
330
+#define	BADARG		((*options == ':') ? (int)':' : (int)'?')
331
+#define	INORDER 	(int)1
332
+
333
+#define	EMSG		""
334
+
335
+static int getopt_internal(int, char * const *, const char *,
336
+			   const struct option *, int *, int);
337
+static int parse_long_options(char * const *, const char *,
338
+			      const struct option *, int *, int);
339
+static int gcd(int, int);
340
+static void permute_args(int, int, int, char * const *);
341
+
342
+static char *place = EMSG; /* option letter processing */
343
+
344
+/* XXX: set optreset to 1 rather than these two */
345
+static int nonopt_start = -1; /* first non option argument (for permute) */
346
+static int nonopt_end = -1;   /* first option after non options (for permute) */
347
+
348
+/* Error messages */
349
+static const char recargchar[] = "option requires an argument -- %c";
350
+static const char recargstring[] = "option requires an argument -- %s";
351
+static const char ambig[] = "ambiguous option -- %.*s";
352
+static const char noarg[] = "option doesn't take an argument -- %.*s";
353
+static const char illoptchar[] = "unknown option -- %c";
354
+static const char illoptstring[] = "unknown option -- %s";
355
+
356
+
357
+
358
+#ifdef _WIN32
359
+
360
+/* Windows needs warnx().  We change the definition though:
361
+ *  1. (another) global is defined, opterrmsg, which holds the error message
362
+ *  2. errors are always printed out on stderr w/o the program name
363
+ * Note that opterrmsg always gets set no matter what opterr is set to.  The
364
+ * error message will not be printed if opterr is 0 as usual.
365
+ */
366
+
367
+#include <stdio.h>
368
+#include <stdarg.h>
369
+
370
+extern char opterrmsg[128];
371
+char opterrmsg[128]; /* buffer for the last error message */
372
+
373
+static void warnx(const char *fmt, ...)
374
+{
375
+	va_list ap;
376
+	va_start(ap, fmt);
377
+    /*
378
+    Make sure opterrmsg is always zero-terminated despite the _vsnprintf()
379
+    implementation specifics and manually suppress the warning.
380
+    */
381
+    memset(opterrmsg, 0, sizeof opterrmsg);
382
+	if (fmt != NULL)
383
+		_vsnprintf(opterrmsg, sizeof(opterrmsg) - 1, fmt, ap);
384
+	va_end(ap);
385
+
386
+#pragma warning(suppress: 6053)
387
+	fprintf(stderr, "%s\n", opterrmsg);
388
+}
389
+
390
+#else
391
+#include <err.h>
392
+#endif /*_WIN32*/
393
+
394
+
395
+/*
396
+ * Compute the greatest common divisor of a and b.
397
+ */
398
+static int
399
+gcd(int a, int b)
400
+{
401
+	int c;
402
+
403
+	c = a % b;
404
+	while (c != 0) {
405
+		a = b;
406
+		b = c;
407
+		c = a % b;
408
+	}
409
+
410
+	return (b);
411
+}
412
+
413
+/*
414
+ * Exchange the block from nonopt_start to nonopt_end with the block
415
+ * from nonopt_end to opt_end (keeping the same order of arguments
416
+ * in each block).
417
+ */
418
+static void
419
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
420
+	char * const *nargv)
421
+{
422
+	int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
423
+	char *swap;
424
+
425
+	/*
426
+	 * compute lengths of blocks and number and size of cycles
427
+	 */
428
+	nnonopts = panonopt_end - panonopt_start;
429
+	nopts = opt_end - panonopt_end;
430
+	ncycle = gcd(nnonopts, nopts);
431
+	cyclelen = (opt_end - panonopt_start) / ncycle;
432
+
433
+	for (i = 0; i < ncycle; i++) {
434
+		cstart = panonopt_end+i;
435
+		pos = cstart;
436
+		for (j = 0; j < cyclelen; j++) {
437
+			if (pos >= panonopt_end)
438
+				pos -= nnonopts;
439
+			else
440
+				pos += nopts;
441
+			swap = nargv[pos];
442
+			/* LINTED const cast */
443
+			((char **) nargv)[pos] = nargv[cstart];
444
+			/* LINTED const cast */
445
+			((char **)nargv)[cstart] = swap;
446
+		}
447
+	}
448
+}
449
+
450
+/*
451
+ * parse_long_options --
452
+ *	Parse long options in argc/argv argument vector.
453
+ * Returns -1 if short_too is set and the option does not match long_options.
454
+ */
455
+static int
456
+parse_long_options(char * const *nargv, const char *options,
457
+	const struct option *long_options, int *idx, int short_too)
458
+{
459
+	char *current_argv, *has_equal;
460
+	size_t current_argv_len;
461
+	int i, match;
462
+
463
+	current_argv = place;
464
+	match = -1;
465
+
466
+	optind++;
467
+
468
+	if ((has_equal = strchr(current_argv, '=')) != NULL) {
469
+		/* argument found (--option=arg) */
470
+		current_argv_len = has_equal - current_argv;
471
+		has_equal++;
472
+	} else
473
+		current_argv_len = strlen(current_argv);
474
+
475
+	for (i = 0; long_options[i].name; i++) {
476
+		/* find matching long option */
477
+		if (strncmp(current_argv, long_options[i].name,
478
+		    current_argv_len))
479
+			continue;
480
+
481
+		if (strlen(long_options[i].name) == current_argv_len) {
482
+			/* exact match */
483
+			match = i;
484
+			break;
485
+		}
486
+		/*
487
+		 * If this is a known short option, don't allow
488
+		 * a partial match of a single character.
489
+		 */
490
+		if (short_too && current_argv_len == 1)
491
+			continue;
492
+
493
+		if (match == -1)	/* partial match */
494
+			match = i;
495
+		else {
496
+			/* ambiguous abbreviation */
497
+			if (PRINT_ERROR)
498
+				warnx(ambig, (int)current_argv_len,
499
+				     current_argv);
500
+			optopt = 0;
501
+			return (BADCH);
502
+		}
503
+	}
504
+	if (match != -1) {		/* option found */
505
+		if (long_options[match].has_arg == no_argument
506
+		    && has_equal) {
507
+			if (PRINT_ERROR)
508
+				warnx(noarg, (int)current_argv_len,
509
+				     current_argv);
510
+			/*
511
+			 * XXX: GNU sets optopt to val regardless of flag
512
+			 */
513
+			if (long_options[match].flag == NULL)
514
+				optopt = long_options[match].val;
515
+			else
516
+				optopt = 0;
517
+			return (BADARG);
518
+		}
519
+		if (long_options[match].has_arg == required_argument ||
520
+		    long_options[match].has_arg == optional_argument) {
521
+			if (has_equal)
522
+				optarg = has_equal;
523
+			else if (long_options[match].has_arg ==
524
+			    required_argument) {
525
+				/*
526
+				 * optional argument doesn't use next nargv
527
+				 */
528
+				optarg = nargv[optind++];
529
+			}
530
+		}
531
+		if ((long_options[match].has_arg == required_argument)
532
+		    && (optarg == NULL)) {
533
+			/*
534
+			 * Missing argument; leading ':' indicates no error
535
+			 * should be generated.
536
+			 */
537
+			if (PRINT_ERROR)
538
+				warnx(recargstring,
539
+				    current_argv);
540
+			/*
541
+			 * XXX: GNU sets optopt to val regardless of flag
542
+			 */
543
+			if (long_options[match].flag == NULL)
544
+				optopt = long_options[match].val;
545
+			else
546
+				optopt = 0;
547
+			--optind;
548
+			return (BADARG);
549
+		}
550
+	} else {			/* unknown option */
551
+		if (short_too) {
552
+			--optind;
553
+			return (-1);
554
+		}
555
+		if (PRINT_ERROR)
556
+			warnx(illoptstring, current_argv);
557
+		optopt = 0;
558
+		return (BADCH);
559
+	}
560
+	if (idx)
561
+		*idx = match;
562
+	if (long_options[match].flag) {
563
+		*long_options[match].flag = long_options[match].val;
564
+		return (0);
565
+	} else
566
+		return (long_options[match].val);
567
+}
568
+
569
+/*
570
+ * getopt_internal --
571
+ *	Parse argc/argv argument vector.  Called by user level routines.
572
+ */
573
+static int
574
+getopt_internal(int nargc, char * const *nargv, const char *options,
575
+	const struct option *long_options, int *idx, int flags)
576
+{
577
+	char *oli;				/* option letter list index */
578
+	int optchar, short_too;
579
+	static int posixly_correct = -1;
580
+
581
+	if (options == NULL)
582
+		return (-1);
583
+
584
+	/*
585
+	 * Disable GNU extensions if POSIXLY_CORRECT is set or options
586
+	 * string begins with a '+'.
587
+	 */
588
+	if (posixly_correct == -1)
589
+		posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
590
+	if (posixly_correct || *options == '+')
591
+		flags &= ~FLAG_PERMUTE;
592
+	else if (*options == '-')
593
+		flags |= FLAG_ALLARGS;
594
+	if (*options == '+' || *options == '-')
595
+		options++;
596
+
597
+	/*
598
+	 * XXX Some GNU programs (like cvs) set optind to 0 instead of
599
+	 * XXX using optreset.  Work around this braindamage.
600
+	 */
601
+	if (optind == 0)
602
+		optind = optreset = 1;
603
+
604
+	optarg = NULL;
605
+	if (optreset)
606
+		nonopt_start = nonopt_end = -1;
607
+start:
608
+	if (optreset || !*place) {		/* update scanning pointer */
609
+		optreset = 0;
610
+		if (optind >= nargc) {          /* end of argument vector */
611
+			place = EMSG;
612
+			if (nonopt_end != -1) {
613
+				/* do permutation, if we have to */
614
+				permute_args(nonopt_start, nonopt_end,
615
+				    optind, nargv);
616
+				optind -= nonopt_end - nonopt_start;
617
+			}
618
+			else if (nonopt_start != -1) {
619
+				/*
620
+				 * If we skipped non-options, set optind
621
+				 * to the first of them.
622
+				 */
623
+				optind = nonopt_start;
624
+			}
625
+			nonopt_start = nonopt_end = -1;
626
+			return (-1);
627
+		}
628
+		if (*(place = nargv[optind]) != '-' ||
629
+		    (place[1] == '\0' && strchr(options, '-') == NULL)) {
630
+			place = EMSG;		/* found non-option */
631
+			if (flags & FLAG_ALLARGS) {
632
+				/*
633
+				 * GNU extension:
634
+				 * return non-option as argument to option 1
635
+				 */
636
+				optarg = nargv[optind++];
637
+				return (INORDER);
638
+			}
639
+			if (!(flags & FLAG_PERMUTE)) {
640
+				/*
641
+				 * If no permutation wanted, stop parsing
642
+				 * at first non-option.
643
+				 */
644
+				return (-1);
645
+			}
646
+			/* do permutation */
647
+			if (nonopt_start == -1)
648
+				nonopt_start = optind;
649
+			else if (nonopt_end != -1) {
650
+				permute_args(nonopt_start, nonopt_end,
651
+				    optind, nargv);
652
+				nonopt_start = optind -
653
+				    (nonopt_end - nonopt_start);
654
+				nonopt_end = -1;
655
+			}
656
+			optind++;
657
+			/* process next argument */
658
+			goto start;
659
+		}
660
+		if (nonopt_start != -1 && nonopt_end == -1)
661
+			nonopt_end = optind;
662
+
663
+		/*
664
+		 * If we have "-" do nothing, if "--" we are done.
665
+		 */
666
+		if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
667
+			optind++;
668
+			place = EMSG;
669
+			/*
670
+			 * We found an option (--), so if we skipped
671
+			 * non-options, we have to permute.
672
+			 */
673
+			if (nonopt_end != -1) {
674
+				permute_args(nonopt_start, nonopt_end,
675
+				    optind, nargv);
676
+				optind -= nonopt_end - nonopt_start;
677
+			}
678
+			nonopt_start = nonopt_end = -1;
679
+			return (-1);
680
+		}
681
+	}
682
+
683
+	/*
684
+	 * Check long options if:
685
+	 *  1) we were passed some
686
+	 *  2) the arg is not just "-"
687
+	 *  3) either the arg starts with -- we are getopt_long_only()
688
+	 */
689
+	if (long_options != NULL && place != nargv[optind] &&
690
+	    (*place == '-' || (flags & FLAG_LONGONLY))) {
691
+		short_too = 0;
692
+		if (*place == '-')
693
+			place++;		/* --foo long option */
694
+		else if (*place != ':' && strchr(options, *place) != NULL)
695
+			short_too = 1;		/* could be short option too */
696
+
697
+		optchar = parse_long_options(nargv, options, long_options,
698
+		    idx, short_too);
699
+		if (optchar != -1) {
700
+			place = EMSG;
701
+			return (optchar);
702
+		}
703
+	}
704
+
705
+	if ((optchar = (int)*place++) == (int)':' ||
706
+	    (optchar == (int)'-' && *place != '\0') ||
707
+	    (oli = strchr(options, optchar)) == NULL) {
708
+		/*
709
+		 * If the user specified "-" and  '-' isn't listed in
710
+		 * options, return -1 (non-option) as per POSIX.
711
+		 * Otherwise, it is an unknown option character (or ':').
712
+		 */
713
+		if (optchar == (int)'-' && *place == '\0')
714
+			return (-1);
715
+		if (!*place)
716
+			++optind;
717
+		if (PRINT_ERROR)
718
+			warnx(illoptchar, optchar);
719
+		optopt = optchar;
720
+		return (BADCH);
721
+	}
722
+	if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
723
+		/* -W long-option */
724
+		if (*place)			/* no space */
725
+			/* NOTHING */;
726
+		else if (++optind >= nargc) {	/* no arg */
727
+			place = EMSG;
728
+			if (PRINT_ERROR)
729
+				warnx(recargchar, optchar);
730
+			optopt = optchar;
731
+			return (BADARG);
732
+		} else				/* white space */
733
+			place = nargv[optind];
734
+		optchar = parse_long_options(nargv, options, long_options,
735
+		    idx, 0);
736
+		place = EMSG;
737
+		return (optchar);
738
+	}
739
+	if (*++oli != ':') {			/* doesn't take argument */
740
+		if (!*place)
741
+			++optind;
742
+	} else {				/* takes (optional) argument */
743
+		optarg = NULL;
744
+		if (*place)			/* no white space */
745
+			optarg = place;
746
+		else if (oli[1] != ':') {	/* arg not optional */
747
+			if (++optind >= nargc) {	/* no arg */
748
+				place = EMSG;
749
+				if (PRINT_ERROR)
750
+					warnx(recargchar, optchar);
751
+				optopt = optchar;
752
+				return (BADARG);
753
+			} else
754
+				optarg = nargv[optind];
755
+		}
756
+		place = EMSG;
757
+		++optind;
758
+	}
759
+	/* dump back option letter */
760
+	return (optchar);
761
+}
762
+
763
+#ifdef REPLACE_GETOPT
764
+/*
765
+ * getopt --
766
+ *	Parse argc/argv argument vector.
767
+ *
768
+ * [eventually this will replace the BSD getopt]
769
+ */
770
+int
771
+getopt(int nargc, char * const *nargv, const char *options)
772
+{
773
+
774
+	/*
775
+	 * We don't pass FLAG_PERMUTE to getopt_internal() since
776
+	 * the BSD getopt(3) (unlike GNU) has never done this.
777
+	 *
778
+	 * Furthermore, since many privileged programs call getopt()
779
+	 * before dropping privileges it makes sense to keep things
780
+	 * as simple (and bug-free) as possible.
781
+	 */
782
+	return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
783
+}
784
+#endif /* REPLACE_GETOPT */
785
+
786
+/*
787
+ * getopt_long --
788
+ *	Parse argc/argv argument vector.
789
+ */
790
+int
791
+getopt_long(int nargc, char * const *nargv, const char *options,
792
+    const struct option *long_options, int *idx)
793
+{
794
+
795
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
796
+	    FLAG_PERMUTE));
797
+}
798
+
799
+/*
800
+ * getopt_long_only --
801
+ *	Parse argc/argv argument vector.
802
+ */
803
+int
804
+getopt_long_only(int nargc, char * const *nargv, const char *options,
805
+    const struct option *long_options, int *idx)
806
+{
807
+
808
+	return (getopt_internal(nargc, nargv, options, long_options, idx,
809
+	    FLAG_PERMUTE|FLAG_LONGONLY));
810
+}
811
+/*******************************************************************************
812
+ * This file is part of the argtable3 library.
813
+ *
814
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
815
+ * <sheitmann@users.sourceforge.net>
816
+ * All rights reserved.
817
+ *
818
+ * Redistribution and use in source and binary forms, with or without
819
+ * modification, are permitted provided that the following conditions are met:
820
+ *     * Redistributions of source code must retain the above copyright
821
+ *       notice, this list of conditions and the following disclaimer.
822
+ *     * Redistributions in binary form must reproduce the above copyright
823
+ *       notice, this list of conditions and the following disclaimer in the
824
+ *       documentation and/or other materials provided with the distribution.
825
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
826
+ *       may be used to endorse or promote products derived from this software
827
+ *       without specific prior written permission.
828
+ *
829
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
830
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
831
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
832
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
833
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
834
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
835
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
836
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
837
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
838
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
839
+ ******************************************************************************/
840
+
841
+#include <stdlib.h>
842
+#include <string.h>
843
+
844
+#include "argtable3.h"
845
+
846
+
847
+char * arg_strptime(const char *buf, const char *fmt, struct tm *tm);
848
+
849
+
850
+static void arg_date_resetfn(struct arg_date *parent)
851
+{
852
+    ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
853
+    parent->count = 0;
854
+}
855
+
856
+
857
+static int arg_date_scanfn(struct arg_date *parent, const char *argval)
858
+{
859
+    int errorcode = 0;
860
+
861
+    if (parent->count == parent->hdr.maxcount)
862
+    {
863
+        errorcode = EMAXCOUNT;
864
+    }
865
+    else if (!argval)
866
+    {
867
+        /* no argument value was given, leave parent->tmval[] unaltered but still count it */
868
+        parent->count++;
869
+    }
870
+    else
871
+    {
872
+        const char *pend;
873
+        struct tm tm = parent->tmval[parent->count];
874
+
875
+        /* parse the given argument value, store result in parent->tmval[] */
876
+        pend = arg_strptime(argval, parent->format, &tm);
877
+        if (pend && pend[0] == '\0')
878
+            parent->tmval[parent->count++] = tm;
879
+        else
880
+            errorcode = EBADDATE;
881
+    }
882
+
883
+    ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
884
+    return errorcode;
885
+}
886
+
887
+
888
+static int arg_date_checkfn(struct arg_date *parent)
889
+{
890
+    int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
891
+
892
+    ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
893
+    return errorcode;
894
+}
895
+
896
+
897
+static void arg_date_errorfn(
898
+    struct arg_date *parent,
899
+    FILE *fp,
900
+    int errorcode,
901
+    const char *argval,
902
+    const char *progname)
903
+{
904
+    const char *shortopts = parent->hdr.shortopts;
905
+    const char *longopts  = parent->hdr.longopts;
906
+    const char *datatype  = parent->hdr.datatype;
907
+
908
+    /* make argval NULL safe */
909
+    argval = argval ? argval : "";
910
+
911
+    fprintf(fp, "%s: ", progname);
912
+    switch(errorcode)
913
+    {
914
+    case EMINCOUNT:
915
+        fputs("missing option ", fp);
916
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
917
+        break;
918
+
919
+    case EMAXCOUNT:
920
+        fputs("excess option ", fp);
921
+        arg_print_option(fp, shortopts, longopts, argval, "\n");
922
+        break;
923
+
924
+    case EBADDATE:
925
+    {
926
+        struct tm tm;
927
+        char buff[200];
928
+
929
+        fprintf(fp, "illegal timestamp format \"%s\"\n", argval);
930
+        memset(&tm, 0, sizeof(tm));
931
+        arg_strptime("1999-12-31 23:59:59", "%F %H:%M:%S", &tm);
932
+        strftime(buff, sizeof(buff), parent->format, &tm);
933
+        printf("correct format is \"%s\"\n", buff);
934
+        break;
935
+    }
936
+    }
937
+}
938
+
939
+
940
+struct arg_date * arg_date0(
941
+    const char * shortopts,
942
+    const char * longopts,
943
+    const char * format,
944
+    const char *datatype,
945
+    const char *glossary)
946
+{
947
+    return arg_daten(shortopts, longopts, format, datatype, 0, 1, glossary);
948
+}
949
+
950
+
951
+struct arg_date * arg_date1(
952
+    const char * shortopts,
953
+    const char * longopts,
954
+    const char * format,
955
+    const char *datatype,
956
+    const char *glossary)
957
+{
958
+    return arg_daten(shortopts, longopts, format, datatype, 1, 1, glossary);
959
+}
960
+
961
+
962
+struct arg_date * arg_daten(
963
+    const char * shortopts,
964
+    const char * longopts,
965
+    const char * format,
966
+    const char *datatype,
967
+    int mincount,
968
+    int maxcount,
969
+    const char *glossary)
970
+{
971
+    size_t nbytes;
972
+    struct arg_date *result;
973
+
974
+    /* foolproof things by ensuring maxcount is not less than mincount */
975
+    maxcount = (maxcount < mincount) ? mincount : maxcount;
976
+
977
+    /* default time format is the national date format for the locale */
978
+    if (!format)
979
+        format = "%x";
980
+
981
+    nbytes = sizeof(struct arg_date)         /* storage for struct arg_date */
982
+        + maxcount * sizeof(struct tm);    /* storage for tmval[maxcount] array */
983
+
984
+    /* allocate storage for the arg_date struct + tmval[] array.    */
985
+    /* we use calloc because we want the tmval[] array zero filled. */
986
+    result = (struct arg_date *)calloc(1, nbytes);
987
+    if (result)
988
+    {
989
+        /* init the arg_hdr struct */
990
+        result->hdr.flag      = ARG_HASVALUE;
991
+        result->hdr.shortopts = shortopts;
992
+        result->hdr.longopts  = longopts;
993
+        result->hdr.datatype  = datatype ? datatype : format;
994
+        result->hdr.glossary  = glossary;
995
+        result->hdr.mincount  = mincount;
996
+        result->hdr.maxcount  = maxcount;
997
+        result->hdr.parent    = result;
998
+        result->hdr.resetfn   = (arg_resetfn *)arg_date_resetfn;
999
+        result->hdr.scanfn    = (arg_scanfn *)arg_date_scanfn;
1000
+        result->hdr.checkfn   = (arg_checkfn *)arg_date_checkfn;
1001
+        result->hdr.errorfn   = (arg_errorfn *)arg_date_errorfn;
1002
+
1003
+        /* store the tmval[maxcount] array immediately after the arg_date struct */
1004
+        result->tmval  = (struct tm *)(result + 1);
1005
+
1006
+        /* init the remaining arg_date member variables */
1007
+        result->count = 0;
1008
+        result->format = format;
1009
+    }
1010
+
1011
+    ARG_TRACE(("arg_daten() returns %p\n", result));
1012
+    return result;
1013
+}
1014
+
1015
+
1016
+/*-
1017
+ * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc.
1018
+ * All rights reserved.
1019
+ *
1020
+ * This code was contributed to The NetBSD Foundation by Klaus Klein.
1021
+ * Heavily optimised by David Laight
1022
+ *
1023
+ * Redistribution and use in source and binary forms, with or without
1024
+ * modification, are permitted provided that the following conditions
1025
+ * are met:
1026
+ * 1. Redistributions of source code must retain the above copyright
1027
+ *    notice, this list of conditions and the following disclaimer.
1028
+ * 2. Redistributions in binary form must reproduce the above copyright
1029
+ *    notice, this list of conditions and the following disclaimer in the
1030
+ *    documentation and/or other materials provided with the distribution.
1031
+ *
1032
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
1033
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1034
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1035
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
1036
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1037
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1038
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1039
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1040
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1041
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
1042
+ * POSSIBILITY OF SUCH DAMAGE.
1043
+ */
1044
+
1045
+#include <ctype.h>
1046
+#include <string.h>
1047
+#include <time.h>
1048
+
1049
+/*
1050
+ * We do not implement alternate representations. However, we always
1051
+ * check whether a given modifier is allowed for a certain conversion.
1052
+ */
1053
+#define ALT_E                   0x01
1054
+#define ALT_O                   0x02
1055
+#define LEGAL_ALT(x)            { if (alt_format & ~(x)) return (0); }
1056
+#define TM_YEAR_BASE   (1900)
1057
+
1058
+static int conv_num(const char * *, int *, int, int);
1059
+
1060
+static const char *day[7] = {
1061
+    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
1062
+    "Friday", "Saturday"
1063
+};
1064
+
1065
+static const char *abday[7] = {
1066
+    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
1067
+};
1068
+
1069
+static const char *mon[12] = {
1070
+    "January", "February", "March", "April", "May", "June", "July",
1071
+    "August", "September", "October", "November", "December"
1072
+};
1073
+
1074
+static const char *abmon[12] = {
1075
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1076
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1077
+};
1078
+
1079
+static const char *am_pm[2] = {
1080
+    "AM", "PM"
1081
+};
1082
+
1083
+
1084
+static int arg_strcasecmp(const char *s1, const char *s2)
1085
+{
1086
+    const unsigned char *us1 = (const unsigned char *)s1;
1087
+    const unsigned char *us2 = (const unsigned char *)s2;
1088
+    while (tolower(*us1) == tolower(*us2++))
1089
+        if (*us1++ == '\0')
1090
+            return 0;
1091
+
1092
+    return tolower(*us1) - tolower(*--us2);
1093
+}
1094
+
1095
+
1096
+static int arg_strncasecmp(const char *s1, const char *s2, size_t n)
1097
+{
1098
+    if (n != 0)
1099
+    {
1100
+        const unsigned char *us1 = (const unsigned char *)s1;
1101
+        const unsigned char *us2 = (const unsigned char *)s2;
1102
+        do
1103
+        {
1104
+            if (tolower(*us1) != tolower(*us2++))
1105
+                return tolower(*us1) - tolower(*--us2);
1106
+
1107
+            if (*us1++ == '\0')
1108
+                break;
1109
+        } while (--n != 0);
1110
+    }
1111
+
1112
+    return 0;
1113
+}
1114
+
1115
+
1116
+char * arg_strptime(const char *buf, const char *fmt, struct tm *tm)
1117
+{
1118
+    char c;
1119
+    const char *bp;
1120
+    size_t len = 0;
1121
+    int alt_format, i, split_year = 0;
1122
+
1123
+    bp = buf;
1124
+
1125
+    while ((c = *fmt) != '\0') {
1126
+        /* Clear `alternate' modifier prior to new conversion. */
1127
+        alt_format = 0;
1128
+
1129
+        /* Eat up white-space. */
1130
+        if (isspace(c)) {
1131
+            while (isspace(*bp))
1132
+                bp++;
1133
+
1134
+            fmt++;
1135
+            continue;
1136
+        }
1137
+
1138
+        if ((c = *fmt++) != '%')
1139
+            goto literal;
1140
+
1141
+
1142
+again:
1143
+        switch (c = *fmt++)
1144
+        {
1145
+        case '%': /* "%%" is converted to "%". */
1146
+literal:
1147
+            if (c != *bp++)
1148
+                return (0);
1149
+            break;
1150
+
1151
+        /*
1152
+         * "Alternative" modifiers. Just set the appropriate flag
1153
+         * and start over again.
1154
+         */
1155
+        case 'E': /* "%E?" alternative conversion modifier. */
1156
+            LEGAL_ALT(0);
1157
+            alt_format |= ALT_E;
1158
+            goto again;
1159
+
1160
+        case 'O': /* "%O?" alternative conversion modifier. */
1161
+            LEGAL_ALT(0);
1162
+            alt_format |= ALT_O;
1163
+            goto again;
1164
+
1165
+        /*
1166
+         * "Complex" conversion rules, implemented through recursion.
1167
+         */
1168
+        case 'c': /* Date and time, using the locale's format. */
1169
+            LEGAL_ALT(ALT_E);
1170
+            bp = arg_strptime(bp, "%x %X", tm);
1171
+            if (!bp)
1172
+                return (0);
1173
+            break;
1174
+
1175
+        case 'D': /* The date as "%m/%d/%y". */
1176
+            LEGAL_ALT(0);
1177
+            bp = arg_strptime(bp, "%m/%d/%y", tm);
1178
+            if (!bp)
1179
+                return (0);
1180
+            break;
1181
+
1182
+        case 'R': /* The time as "%H:%M". */
1183
+            LEGAL_ALT(0);
1184
+            bp = arg_strptime(bp, "%H:%M", tm);
1185
+            if (!bp)
1186
+                return (0);
1187
+            break;
1188
+
1189
+        case 'r': /* The time in 12-hour clock representation. */
1190
+            LEGAL_ALT(0);
1191
+            bp = arg_strptime(bp, "%I:%M:%S %p", tm);
1192
+            if (!bp)
1193
+                return (0);
1194
+            break;
1195
+
1196
+        case 'T': /* The time as "%H:%M:%S". */
1197
+            LEGAL_ALT(0);
1198
+            bp = arg_strptime(bp, "%H:%M:%S", tm);
1199
+            if (!bp)
1200
+                return (0);
1201
+            break;
1202
+
1203
+        case 'X': /* The time, using the locale's format. */
1204
+            LEGAL_ALT(ALT_E);
1205
+            bp = arg_strptime(bp, "%H:%M:%S", tm);
1206
+            if (!bp)
1207
+                return (0);
1208
+            break;
1209
+
1210
+        case 'x': /* The date, using the locale's format. */
1211
+            LEGAL_ALT(ALT_E);
1212
+            bp = arg_strptime(bp, "%m/%d/%y", tm);
1213
+            if (!bp)
1214
+                return (0);
1215
+            break;
1216
+
1217
+        /*
1218
+         * "Elementary" conversion rules.
1219
+         */
1220
+        case 'A': /* The day of week, using the locale's form. */
1221
+        case 'a':
1222
+            LEGAL_ALT(0);
1223
+            for (i = 0; i < 7; i++) {
1224
+                /* Full name. */
1225
+                len = strlen(day[i]);
1226
+                if (arg_strncasecmp(day[i], bp, len) == 0)
1227
+                    break;
1228
+
1229
+                /* Abbreviated name. */
1230
+                len = strlen(abday[i]);
1231
+                if (arg_strncasecmp(abday[i], bp, len) == 0)
1232
+                    break;
1233
+            }
1234
+
1235
+            /* Nothing matched. */
1236
+            if (i == 7)
1237
+                return (0);
1238
+
1239
+            tm->tm_wday = i;
1240
+            bp += len;
1241
+            break;
1242
+
1243
+        case 'B': /* The month, using the locale's form. */
1244
+        case 'b':
1245
+        case 'h':
1246
+            LEGAL_ALT(0);
1247
+            for (i = 0; i < 12; i++) {
1248
+                /* Full name. */
1249
+                len = strlen(mon[i]);
1250
+                if (arg_strncasecmp(mon[i], bp, len) == 0)
1251
+                    break;
1252
+
1253
+                /* Abbreviated name. */
1254
+                len = strlen(abmon[i]);
1255
+                if (arg_strncasecmp(abmon[i], bp, len) == 0)
1256
+                    break;
1257
+            }
1258
+
1259
+            /* Nothing matched. */
1260
+            if (i == 12)
1261
+                return (0);
1262
+
1263
+            tm->tm_mon = i;
1264
+            bp += len;
1265
+            break;
1266
+
1267
+        case 'C': /* The century number. */
1268
+            LEGAL_ALT(ALT_E);
1269
+            if (!(conv_num(&bp, &i, 0, 99)))
1270
+                return (0);
1271
+
1272
+            if (split_year) {
1273
+                tm->tm_year = (tm->tm_year % 100) + (i * 100);
1274
+            } else {
1275
+                tm->tm_year = i * 100;
1276
+                split_year = 1;
1277
+            }
1278
+            break;
1279
+
1280
+        case 'd': /* The day of month. */
1281
+        case 'e':
1282
+            LEGAL_ALT(ALT_O);
1283
+            if (!(conv_num(&bp, &tm->tm_mday, 1, 31)))
1284
+                return (0);
1285
+            break;
1286
+
1287
+        case 'k': /* The hour (24-hour clock representation). */
1288
+            LEGAL_ALT(0);
1289
+        /* FALLTHROUGH */
1290
+        case 'H':
1291
+            LEGAL_ALT(ALT_O);
1292
+            if (!(conv_num(&bp, &tm->tm_hour, 0, 23)))
1293
+                return (0);
1294
+            break;
1295
+
1296
+        case 'l': /* The hour (12-hour clock representation). */
1297
+            LEGAL_ALT(0);
1298
+        /* FALLTHROUGH */
1299
+        case 'I':
1300
+            LEGAL_ALT(ALT_O);
1301
+            if (!(conv_num(&bp, &tm->tm_hour, 1, 12)))
1302
+                return (0);
1303
+            if (tm->tm_hour == 12)
1304
+                tm->tm_hour = 0;
1305
+            break;
1306
+
1307
+        case 'j': /* The day of year. */
1308
+            LEGAL_ALT(0);
1309
+            if (!(conv_num(&bp, &i, 1, 366)))
1310
+                return (0);
1311
+            tm->tm_yday = i - 1;
1312
+            break;
1313
+
1314
+        case 'M': /* The minute. */
1315
+            LEGAL_ALT(ALT_O);
1316
+            if (!(conv_num(&bp, &tm->tm_min, 0, 59)))
1317
+                return (0);
1318
+            break;
1319
+
1320
+        case 'm': /* The month. */
1321
+            LEGAL_ALT(ALT_O);
1322
+            if (!(conv_num(&bp, &i, 1, 12)))
1323
+                return (0);
1324
+            tm->tm_mon = i - 1;
1325
+            break;
1326
+
1327
+        case 'p': /* The locale's equivalent of AM/PM. */
1328
+            LEGAL_ALT(0);
1329
+            /* AM? */
1330
+            if (arg_strcasecmp(am_pm[0], bp) == 0) {
1331
+                if (tm->tm_hour > 11)
1332
+                    return (0);
1333
+
1334
+                bp += strlen(am_pm[0]);
1335
+                break;
1336
+            }
1337
+            /* PM? */
1338
+            else if (arg_strcasecmp(am_pm[1], bp) == 0) {
1339
+                if (tm->tm_hour > 11)
1340
+                    return (0);
1341
+
1342
+                tm->tm_hour += 12;
1343
+                bp += strlen(am_pm[1]);
1344
+                break;
1345
+            }
1346
+
1347
+            /* Nothing matched. */
1348
+            return (0);
1349
+
1350
+        case 'S': /* The seconds. */
1351
+            LEGAL_ALT(ALT_O);
1352
+            if (!(conv_num(&bp, &tm->tm_sec, 0, 61)))
1353
+                return (0);
1354
+            break;
1355
+
1356
+        case 'U': /* The week of year, beginning on sunday. */
1357
+        case 'W': /* The week of year, beginning on monday. */
1358
+            LEGAL_ALT(ALT_O);
1359
+            /*
1360
+             * XXX This is bogus, as we can not assume any valid
1361
+             * information present in the tm structure at this
1362
+             * point to calculate a real value, so just check the
1363
+             * range for now.
1364
+             */
1365
+            if (!(conv_num(&bp, &i, 0, 53)))
1366
+                return (0);
1367
+            break;
1368
+
1369
+        case 'w': /* The day of week, beginning on sunday. */
1370
+            LEGAL_ALT(ALT_O);
1371
+            if (!(conv_num(&bp, &tm->tm_wday, 0, 6)))
1372
+                return (0);
1373
+            break;
1374
+
1375
+        case 'Y': /* The year. */
1376
+            LEGAL_ALT(ALT_E);
1377
+            if (!(conv_num(&bp, &i, 0, 9999)))
1378
+                return (0);
1379
+
1380
+            tm->tm_year = i - TM_YEAR_BASE;
1381
+            break;
1382
+
1383
+        case 'y': /* The year within 100 years of the epoch. */
1384
+            LEGAL_ALT(ALT_E | ALT_O);
1385
+            if (!(conv_num(&bp, &i, 0, 99)))
1386
+                return (0);
1387
+
1388
+            if (split_year) {
1389
+                tm->tm_year = ((tm->tm_year / 100) * 100) + i;
1390
+                break;
1391
+            }
1392
+            split_year = 1;
1393
+            if (i <= 68)
1394
+                tm->tm_year = i + 2000 - TM_YEAR_BASE;
1395
+            else
1396
+                tm->tm_year = i + 1900 - TM_YEAR_BASE;
1397
+            break;
1398
+
1399
+        /*
1400
+         * Miscellaneous conversions.
1401
+         */
1402
+        case 'n': /* Any kind of white-space. */
1403
+        case 't':
1404
+            LEGAL_ALT(0);
1405
+            while (isspace(*bp))
1406
+                bp++;
1407
+            break;
1408
+
1409
+
1410
+        default: /* Unknown/unsupported conversion. */
1411
+            return (0);
1412
+        }
1413
+
1414
+
1415
+    }
1416
+
1417
+    /* LINTED functional specification */
1418
+    return ((char *)bp);
1419
+}
1420
+
1421
+
1422
+static int conv_num(const char * *buf, int *dest, int llim, int ulim)
1423
+{
1424
+    int result = 0;
1425
+
1426
+    /* The limit also determines the number of valid digits. */
1427
+    int rulim = ulim;
1428
+
1429
+    if (**buf < '0' || **buf > '9')
1430
+        return (0);
1431
+
1432
+    do {
1433
+        result *= 10;
1434
+        result += *(*buf)++ - '0';
1435
+        rulim /= 10;
1436
+    } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
1437
+
1438
+    if (result < llim || result > ulim)
1439
+        return (0);
1440
+
1441
+    *dest = result;
1442
+    return (1);
1443
+}
1444
+/*******************************************************************************
1445
+ * This file is part of the argtable3 library.
1446
+ *
1447
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
1448
+ * <sheitmann@users.sourceforge.net>
1449
+ * All rights reserved.
1450
+ *
1451
+ * Redistribution and use in source and binary forms, with or without
1452
+ * modification, are permitted provided that the following conditions are met:
1453
+ *     * Redistributions of source code must retain the above copyright
1454
+ *       notice, this list of conditions and the following disclaimer.
1455
+ *     * Redistributions in binary form must reproduce the above copyright
1456
+ *       notice, this list of conditions and the following disclaimer in the
1457
+ *       documentation and/or other materials provided with the distribution.
1458
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
1459
+ *       may be used to endorse or promote products derived from this software
1460
+ *       without specific prior written permission.
1461
+ *
1462
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1463
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1464
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1465
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
1466
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1467
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1468
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1469
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1470
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1471
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1472
+ ******************************************************************************/
1473
+
1474
+#include <stdlib.h>
1475
+
1476
+#include "argtable3.h"
1477
+
1478
+
1479
+static void arg_dbl_resetfn(struct arg_dbl *parent)
1480
+{
1481
+    ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
1482
+    parent->count = 0;
1483
+}
1484
+
1485
+
1486
+static int arg_dbl_scanfn(struct arg_dbl *parent, const char *argval)
1487
+{
1488
+    int errorcode = 0;
1489
+
1490
+    if (parent->count == parent->hdr.maxcount)
1491
+    {
1492
+        /* maximum number of arguments exceeded */
1493
+        errorcode = EMAXCOUNT;
1494
+    }
1495
+    else if (!argval)
1496
+    {
1497
+        /* a valid argument with no argument value was given. */
1498
+        /* This happens when an optional argument value was invoked. */
1499
+        /* leave parent argument value unaltered but still count the argument. */
1500
+        parent->count++;
1501
+    }
1502
+    else
1503
+    {
1504
+        double val;
1505
+        char *end;
1506
+
1507
+        /* extract double from argval into val */
1508
+        val = strtod(argval, &end);
1509
+
1510
+        /* if success then store result in parent->dval[] array otherwise return error*/
1511
+        if (*end == 0)
1512
+            parent->dval[parent->count++] = val;
1513
+        else
1514
+            errorcode = EBADDOUBLE;
1515
+    }
1516
+
1517
+    ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
1518
+    return errorcode;
1519
+}
1520
+
1521
+
1522
+static int arg_dbl_checkfn(struct arg_dbl *parent)
1523
+{
1524
+    int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
1525
+    
1526
+    ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
1527
+    return errorcode;
1528
+}
1529
+
1530
+
1531
+static void arg_dbl_errorfn(
1532
+    struct arg_dbl *parent,
1533
+    FILE *fp,
1534
+    int errorcode,
1535
+    const char *argval,
1536
+    const char *progname)
1537
+{
1538
+    const char *shortopts = parent->hdr.shortopts;
1539
+    const char *longopts  = parent->hdr.longopts;
1540
+    const char *datatype  = parent->hdr.datatype;
1541
+
1542
+    /* make argval NULL safe */
1543
+    argval = argval ? argval : "";
1544
+
1545
+    fprintf(fp, "%s: ", progname);
1546
+    switch(errorcode)
1547
+    {
1548
+    case EMINCOUNT:
1549
+        fputs("missing option ", fp);
1550
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
1551
+        break;
1552
+
1553
+    case EMAXCOUNT:
1554
+        fputs("excess option ", fp);
1555
+        arg_print_option(fp, shortopts, longopts, argval, "\n");
1556
+        break;
1557
+
1558
+    case EBADDOUBLE:
1559
+        fprintf(fp, "invalid argument \"%s\" to option ", argval);
1560
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
1561
+        break;
1562
+    }
1563
+}
1564
+
1565
+
1566
+struct arg_dbl * arg_dbl0(
1567
+    const char * shortopts,
1568
+    const char * longopts,
1569
+    const char *datatype,
1570
+    const char *glossary)
1571
+{
1572
+    return arg_dbln(shortopts, longopts, datatype, 0, 1, glossary);
1573
+}
1574
+
1575
+
1576
+struct arg_dbl * arg_dbl1(
1577
+    const char * shortopts,
1578
+    const char * longopts,
1579
+    const char *datatype,
1580
+    const char *glossary)
1581
+{
1582
+    return arg_dbln(shortopts, longopts, datatype, 1, 1, glossary);
1583
+}
1584
+
1585
+
1586
+struct arg_dbl * arg_dbln(
1587
+    const char * shortopts,
1588
+    const char * longopts,
1589
+    const char *datatype,
1590
+    int mincount,
1591
+    int maxcount,
1592
+    const char *glossary)
1593
+{
1594
+    size_t nbytes;
1595
+    struct arg_dbl *result;
1596
+
1597
+    /* foolproof things by ensuring maxcount is not less than mincount */
1598
+    maxcount = (maxcount < mincount) ? mincount : maxcount;
1599
+
1600
+    nbytes = sizeof(struct arg_dbl)     /* storage for struct arg_dbl */
1601
+             + (maxcount + 1) * sizeof(double); /* storage for dval[maxcount] array plus one extra for padding to memory boundary */
1602
+
1603
+    result = (struct arg_dbl *)malloc(nbytes);
1604
+    if (result)
1605
+    {
1606
+        size_t addr;
1607
+        size_t rem;
1608
+
1609
+        /* init the arg_hdr struct */
1610
+        result->hdr.flag      = ARG_HASVALUE;
1611
+        result->hdr.shortopts = shortopts;
1612
+        result->hdr.longopts  = longopts;
1613
+        result->hdr.datatype  = datatype ? datatype : "<double>";
1614
+        result->hdr.glossary  = glossary;
1615
+        result->hdr.mincount  = mincount;
1616
+        result->hdr.maxcount  = maxcount;
1617
+        result->hdr.parent    = result;
1618
+        result->hdr.resetfn   = (arg_resetfn *)arg_dbl_resetfn;
1619
+        result->hdr.scanfn    = (arg_scanfn *)arg_dbl_scanfn;
1620
+        result->hdr.checkfn   = (arg_checkfn *)arg_dbl_checkfn;
1621
+        result->hdr.errorfn   = (arg_errorfn *)arg_dbl_errorfn;
1622
+
1623
+        /* Store the dval[maxcount] array on the first double boundary that
1624
+         * immediately follows the arg_dbl struct. We do the memory alignment
1625
+         * purely for SPARC and Motorola systems. They require floats and
1626
+         * doubles to be aligned on natural boundaries.
1627
+         */
1628
+        addr = (size_t)(result + 1);
1629
+        rem  = addr % sizeof(double);
1630
+        result->dval  = (double *)(addr + sizeof(double) - rem);
1631
+        ARG_TRACE(("addr=%p, dval=%p, sizeof(double)=%d rem=%d\n", addr, result->dval, (int)sizeof(double), (int)rem));
1632
+
1633
+        result->count = 0;
1634
+    }
1635
+    
1636
+    ARG_TRACE(("arg_dbln() returns %p\n", result));
1637
+    return result;
1638
+}
1639
+/*******************************************************************************
1640
+ * This file is part of the argtable3 library.
1641
+ *
1642
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
1643
+ * <sheitmann@users.sourceforge.net>
1644
+ * All rights reserved.
1645
+ *
1646
+ * Redistribution and use in source and binary forms, with or without
1647
+ * modification, are permitted provided that the following conditions are met:
1648
+ *     * Redistributions of source code must retain the above copyright
1649
+ *       notice, this list of conditions and the following disclaimer.
1650
+ *     * Redistributions in binary form must reproduce the above copyright
1651
+ *       notice, this list of conditions and the following disclaimer in the
1652
+ *       documentation and/or other materials provided with the distribution.
1653
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
1654
+ *       may be used to endorse or promote products derived from this software
1655
+ *       without specific prior written permission.
1656
+ *
1657
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1658
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1659
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1660
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
1661
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1662
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1663
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1664
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1665
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1666
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1667
+ ******************************************************************************/
1668
+
1669
+#include <stdlib.h>
1670
+
1671
+#include "argtable3.h"
1672
+
1673
+
1674
+static void arg_end_resetfn(struct arg_end *parent)
1675
+{
1676
+    ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
1677
+    parent->count = 0;
1678
+}
1679
+
1680
+static void arg_end_errorfn(
1681
+    void *parent,
1682
+    FILE *fp,
1683
+    int error,
1684
+    const char *argval,
1685
+    const char *progname)
1686
+{
1687
+    /* suppress unreferenced formal parameter warning */
1688
+    (void)parent;
1689
+
1690
+    progname = progname ? progname : "";
1691
+    argval = argval ? argval : "";
1692
+
1693
+    fprintf(fp, "%s: ", progname);
1694
+    switch(error)
1695
+    {
1696
+    case ARG_ELIMIT:
1697
+        fputs("too many errors to display", fp);
1698
+        break;
1699
+    case ARG_EMALLOC:
1700
+        fputs("insufficent memory", fp);
1701
+        break;
1702
+    case ARG_ENOMATCH:
1703
+        fprintf(fp, "unexpected argument \"%s\"", argval);
1704
+        break;
1705
+    case ARG_EMISSARG:
1706
+        fprintf(fp, "option \"%s\" requires an argument", argval);
1707
+        break;
1708
+    case ARG_ELONGOPT:
1709
+        fprintf(fp, "invalid option \"%s\"", argval);
1710
+        break;
1711
+    default:
1712
+        fprintf(fp, "invalid option \"-%c\"", error);
1713
+        break;
1714
+    }
1715
+    
1716
+    fputc('\n', fp);
1717
+}
1718
+
1719
+
1720
+struct arg_end * arg_end(int maxcount)
1721
+{
1722
+    size_t nbytes;
1723
+    struct arg_end *result;
1724
+
1725
+    nbytes = sizeof(struct arg_end)
1726
+             + maxcount * sizeof(int)     /* storage for int error[maxcount] array*/
1727
+             + maxcount * sizeof(void *)  /* storage for void* parent[maxcount] array */
1728
+             + maxcount * sizeof(char *); /* storage for char* argval[maxcount] array */
1729
+
1730
+    result = (struct arg_end *)malloc(nbytes);
1731
+    if (result)
1732
+    {
1733
+        /* init the arg_hdr struct */
1734
+        result->hdr.flag      = ARG_TERMINATOR;
1735
+        result->hdr.shortopts = NULL;
1736
+        result->hdr.longopts  = NULL;
1737
+        result->hdr.datatype  = NULL;
1738
+        result->hdr.glossary  = NULL;
1739
+        result->hdr.mincount  = 1;
1740
+        result->hdr.maxcount  = maxcount;
1741
+        result->hdr.parent    = result;
1742
+        result->hdr.resetfn   = (arg_resetfn *)arg_end_resetfn;
1743
+        result->hdr.scanfn    = NULL;
1744
+        result->hdr.checkfn   = NULL;
1745
+        result->hdr.errorfn   = (arg_errorfn *)arg_end_errorfn;
1746
+
1747
+        /* store error[maxcount] array immediately after struct arg_end */
1748
+        result->error = (int *)(result + 1);
1749
+
1750
+        /* store parent[maxcount] array immediately after error[] array */
1751
+        result->parent = (void * *)(result->error + maxcount );
1752
+
1753
+        /* store argval[maxcount] array immediately after parent[] array */
1754
+        result->argval = (const char * *)(result->parent + maxcount );
1755
+    }
1756
+
1757
+    ARG_TRACE(("arg_end(%d) returns %p\n", maxcount, result));
1758
+    return result;
1759
+}
1760
+
1761
+
1762
+void arg_print_errors(FILE * fp, struct arg_end * end, const char * progname)
1763
+{
1764
+    int i;
1765
+    ARG_TRACE(("arg_errors()\n"));
1766
+    for (i = 0; i < end->count; i++)
1767
+    {
1768
+        struct arg_hdr *errorparent = (struct arg_hdr *)(end->parent[i]);
1769
+        if (errorparent->errorfn)
1770
+            errorparent->errorfn(end->parent[i],
1771
+                                 fp,
1772
+                                 end->error[i],
1773
+                                 end->argval[i],
1774
+                                 progname);
1775
+    }
1776
+}
1777
+/*******************************************************************************
1778
+ * This file is part of the argtable3 library.
1779
+ *
1780
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
1781
+ * <sheitmann@users.sourceforge.net>
1782
+ * All rights reserved.
1783
+ *
1784
+ * Redistribution and use in source and binary forms, with or without
1785
+ * modification, are permitted provided that the following conditions are met:
1786
+ *     * Redistributions of source code must retain the above copyright
1787
+ *       notice, this list of conditions and the following disclaimer.
1788
+ *     * Redistributions in binary form must reproduce the above copyright
1789
+ *       notice, this list of conditions and the following disclaimer in the
1790
+ *       documentation and/or other materials provided with the distribution.
1791
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
1792
+ *       may be used to endorse or promote products derived from this software
1793
+ *       without specific prior written permission.
1794
+ *
1795
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
1796
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1797
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1798
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
1799
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
1800
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
1801
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
1802
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1803
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
1804
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1805
+ ******************************************************************************/
1806
+
1807
+#include <string.h>
1808
+#include <stdlib.h>
1809
+
1810
+#include "argtable3.h"
1811
+
1812
+#ifdef WIN32
1813
+# define FILESEPARATOR1 '\\'
1814
+# define FILESEPARATOR2 '/'
1815
+#else
1816
+# define FILESEPARATOR1 '/'
1817
+# define FILESEPARATOR2 '/'
1818
+#endif
1819
+
1820
+
1821
+static void arg_file_resetfn(struct arg_file *parent)
1822
+{
1823
+    ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
1824
+    parent->count = 0;
1825
+}
1826
+
1827
+
1828
+/* Returns ptr to the base filename within *filename */
1829
+static const char * arg_basename(const char *filename)
1830
+{
1831
+    const char *result = NULL, *result1, *result2;
1832
+
1833
+    /* Find the last occurrence of eother file separator character. */
1834
+    /* Two alternative file separator chars are supported as legal  */
1835
+    /* file separators but not both together in the same filename.  */
1836
+    result1 = (filename ? strrchr(filename, FILESEPARATOR1) : NULL);
1837
+    result2 = (filename ? strrchr(filename, FILESEPARATOR2) : NULL);
1838
+
1839
+    if (result2)
1840
+        result = result2 + 1;  /* using FILESEPARATOR2 (the alternative file separator) */
1841
+
1842
+    if (result1)
1843
+        result = result1 + 1;  /* using FILESEPARATOR1 (the preferred file separator) */
1844
+
1845
+    if (!result)
1846
+        result = filename;  /* neither file separator was found so basename is the whole filename */
1847
+
1848
+    /* special cases of "." and ".." are not considered basenames */
1849
+    if (result && ( strcmp(".", result) == 0 || strcmp("..", result) == 0 ))
1850
+        result = filename + strlen(filename);
1851
+
1852
+    return result;
1853
+}
1854
+
1855
+
1856
+/* Returns ptr to the file extension within *basename */
1857
+static const char * arg_extension(const char *basename)
1858
+{
1859
+    /* find the last occurrence of '.' in basename */
1860
+    const char *result = (basename ? strrchr(basename, '.') : NULL);
1861
+
1862
+    /* if no '.' was found then return pointer to end of basename */
1863
+    if (basename && !result)
1864
+        result = basename + strlen(basename);
1865
+
1866
+    /* special case: basenames with a single leading dot (eg ".foo") are not considered as true extensions */
1867
+    if (basename && result == basename)
1868
+        result = basename + strlen(basename);
1869
+
1870
+    /* special case: empty extensions (eg "foo.","foo..") are not considered as true extensions */
1871
+    if (basename && result && result[1] == '\0')
1872
+        result = basename + strlen(basename);
1873
+
1874
+    return result;
1875
+}
1876
+
1877
+
1878
+static int arg_file_scanfn(struct arg_file *parent, const char *argval)
1879
+{
1880
+    int errorcode = 0;
1881
+
1882
+    if (parent->count == parent->hdr.maxcount)
1883
+    {
1884
+        /* maximum number of arguments exceeded */
1885
+        errorcode = EMAXCOUNT;
1886
+    }
1887
+    else if (!argval)
1888
+    {
1889
+        /* a valid argument with no argument value was given. */
1890
+        /* This happens when an optional argument value was invoked. */
1891
+        /* leave parent arguiment value unaltered but still count the argument. */
1892
+        parent->count++;
1893
+    }
1894
+    else
1895
+    {
1896
+        parent->filename[parent->count]  = argval;
1897
+        parent->basename[parent->count]  = arg_basename(argval);
1898
+        parent->extension[parent->count] =
1899
+            arg_extension(parent->basename[parent->count]);                                /* only seek extensions within the basename (not the file path)*/
1900
+        parent->count++;
1901
+    }
1902
+
1903
+    ARG_TRACE(("%s4:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
1904
+    return errorcode;
1905
+}
1906
+
1907
+
1908
+static int arg_file_checkfn(struct arg_file *parent)
1909
+{
1910
+    int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
1911
+    
1912
+    ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
1913
+    return errorcode;
1914
+}
1915
+
1916
+
1917
+static void arg_file_errorfn(
1918
+    struct arg_file *parent,
1919
+    FILE *fp,
1920
+    int errorcode,
1921
+    const char *argval,
1922
+    const char *progname)
1923
+{
1924
+    const char *shortopts = parent->hdr.shortopts;
1925
+    const char *longopts  = parent->hdr.longopts;
1926
+    const char *datatype  = parent->hdr.datatype;
1927
+
1928
+    /* make argval NULL safe */
1929
+    argval = argval ? argval : "";
1930
+
1931
+    fprintf(fp, "%s: ", progname);
1932
+    switch(errorcode)
1933
+    {
1934
+    case EMINCOUNT:
1935
+        fputs("missing option ", fp);
1936
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
1937
+        break;
1938
+
1939
+    case EMAXCOUNT:
1940
+        fputs("excess option ", fp);
1941
+        arg_print_option(fp, shortopts, longopts, argval, "\n");
1942
+        break;
1943
+
1944
+    default:
1945
+        fprintf(fp, "unknown error at \"%s\"\n", argval);
1946
+    }
1947
+}
1948
+
1949
+
1950
+struct arg_file * arg_file0(
1951
+    const char * shortopts,
1952
+    const char * longopts,
1953
+    const char *datatype,
1954
+    const char *glossary)
1955
+{
1956
+    return arg_filen(shortopts, longopts, datatype, 0, 1, glossary);
1957
+}
1958
+
1959
+
1960
+struct arg_file * arg_file1(
1961
+    const char * shortopts,
1962
+    const char * longopts,
1963
+    const char *datatype,
1964
+    const char *glossary)
1965
+{
1966
+    return arg_filen(shortopts, longopts, datatype, 1, 1, glossary);
1967
+}
1968
+
1969
+
1970
+struct arg_file * arg_filen(
1971
+    const char * shortopts,
1972
+    const char * longopts,
1973
+    const char *datatype,
1974
+    int mincount,
1975
+    int maxcount,
1976
+    const char *glossary)
1977
+{
1978
+    size_t nbytes;
1979
+    struct arg_file *result;
1980
+
1981
+    /* foolproof things by ensuring maxcount is not less than mincount */
1982
+    maxcount = (maxcount < mincount) ? mincount : maxcount;
1983
+
1984
+    nbytes = sizeof(struct arg_file)      /* storage for struct arg_file */
1985
+             + sizeof(char *) * maxcount  /* storage for filename[maxcount] array */
1986
+             + sizeof(char *) * maxcount  /* storage for basename[maxcount] array */
1987
+             + sizeof(char *) * maxcount; /* storage for extension[maxcount] array */
1988
+
1989
+    result = (struct arg_file *)malloc(nbytes);
1990
+    if (result)
1991
+    {
1992
+        int i;
1993
+
1994
+        /* init the arg_hdr struct */
1995
+        result->hdr.flag      = ARG_HASVALUE;
1996
+        result->hdr.shortopts = shortopts;
1997
+        result->hdr.longopts  = longopts;
1998
+        result->hdr.glossary  = glossary;
1999
+        result->hdr.datatype  = datatype ? datatype : "<file>";
2000
+        result->hdr.mincount  = mincount;
2001
+        result->hdr.maxcount  = maxcount;
2002
+        result->hdr.parent    = result;
2003
+        result->hdr.resetfn   = (arg_resetfn *)arg_file_resetfn;
2004
+        result->hdr.scanfn    = (arg_scanfn *)arg_file_scanfn;
2005
+        result->hdr.checkfn   = (arg_checkfn *)arg_file_checkfn;
2006
+        result->hdr.errorfn   = (arg_errorfn *)arg_file_errorfn;
2007
+
2008
+        /* store the filename,basename,extension arrays immediately after the arg_file struct */
2009
+        result->filename  = (const char * *)(result + 1);
2010
+        result->basename  = result->filename + maxcount;
2011
+        result->extension = result->basename + maxcount;
2012
+        result->count = 0;
2013
+
2014
+        /* foolproof the string pointers by initialising them with empty strings */
2015
+        for (i = 0; i < maxcount; i++)
2016
+        {
2017
+            result->filename[i] = "";
2018
+            result->basename[i] = "";
2019
+            result->extension[i] = "";
2020
+        }
2021
+    }
2022
+    
2023
+    ARG_TRACE(("arg_filen() returns %p\n", result));
2024
+    return result;
2025
+}
2026
+/*******************************************************************************
2027
+ * This file is part of the argtable3 library.
2028
+ *
2029
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
2030
+ * <sheitmann@users.sourceforge.net>
2031
+ * All rights reserved.
2032
+ *
2033
+ * Redistribution and use in source and binary forms, with or without
2034
+ * modification, are permitted provided that the following conditions are met:
2035
+ *     * Redistributions of source code must retain the above copyright
2036
+ *       notice, this list of conditions and the following disclaimer.
2037
+ *     * Redistributions in binary form must reproduce the above copyright
2038
+ *       notice, this list of conditions and the following disclaimer in the
2039
+ *       documentation and/or other materials provided with the distribution.
2040
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
2041
+ *       may be used to endorse or promote products derived from this software
2042
+ *       without specific prior written permission.
2043
+ *
2044
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2045
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2046
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2047
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
2048
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2049
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2050
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2051
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2052
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2053
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2054
+ ******************************************************************************/
2055
+
2056
+#include <stdlib.h>
2057
+#include <limits.h>
2058
+#include <ctype.h>
2059
+
2060
+#include "argtable3.h"
2061
+
2062
+
2063
+static void arg_int_resetfn(struct arg_int *parent)
2064
+{
2065
+    ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
2066
+    parent->count = 0;
2067
+}
2068
+
2069
+
2070
+/* strtol0x() is like strtol() except that the numeric string is    */
2071
+/* expected to be prefixed by "0X" where X is a user supplied char. */
2072
+/* The string may optionally be prefixed by white space and + or -  */
2073
+/* as in +0X123 or -0X123.                                          */
2074
+/* Once the prefix has been scanned, the remainder of the numeric   */
2075
+/* string is converted using strtol() with the given base.          */
2076
+/* eg: to parse hex str="-0X12324", specify X='X' and base=16.      */
2077
+/* eg: to parse oct str="+0o12324", specify X='O' and base=8.       */
2078
+/* eg: to parse bin str="-0B01010", specify X='B' and base=2.       */
2079
+/* Failure of conversion is indicated by result where *endptr==str. */
2080
+static long int strtol0X(const char * str,
2081
+                         const char * *endptr,
2082
+                         char X,
2083
+                         int base)
2084
+{
2085
+    long int val;               /* stores result */
2086
+    int s = 1;                    /* sign is +1 or -1 */
2087
+    const char *ptr = str;        /* ptr to current position in str */
2088
+
2089
+    /* skip leading whitespace */
2090
+    while (isspace(*ptr))
2091
+        ptr++;
2092
+    /* printf("1) %s\n",ptr); */
2093
+
2094
+    /* scan optional sign character */
2095
+    switch (*ptr)
2096
+    {
2097
+    case '+':
2098
+        ptr++;
2099
+        s = 1;
2100
+        break;
2101
+    case '-':
2102
+        ptr++;
2103
+        s = -1;
2104
+        break;
2105
+    default:
2106
+        s = 1;
2107
+        break;
2108
+    }
2109
+    /* printf("2) %s\n",ptr); */
2110
+
2111
+    /* '0X' prefix */
2112
+    if ((*ptr++) != '0')
2113
+    {
2114
+        /* printf("failed to detect '0'\n"); */
2115
+        *endptr = str;
2116
+        return 0;
2117
+    }
2118
+    /* printf("3) %s\n",ptr); */
2119
+    if (toupper(*ptr++) != toupper(X))
2120
+    {
2121
+        /* printf("failed to detect '%c'\n",X); */
2122
+        *endptr = str;
2123
+        return 0;
2124
+    }
2125
+    /* printf("4) %s\n",ptr); */
2126
+
2127
+    /* attempt conversion on remainder of string using strtol() */
2128
+    val = strtol(ptr, (char * *)endptr, base);
2129
+    if (*endptr == ptr)
2130
+    {
2131
+        /* conversion failed */
2132
+        *endptr = str;
2133
+        return 0;
2134
+    }
2135
+
2136
+    /* success */
2137
+    return s * val;
2138
+}
2139
+
2140
+
2141
+/* Returns 1 if str matches suffix (case insensitive).    */
2142
+/* Str may contain trailing whitespace, but nothing else. */
2143
+static int detectsuffix(const char *str, const char *suffix)
2144
+{
2145
+    /* scan pairwise through strings until mismatch detected */
2146
+    while( toupper(*str) == toupper(*suffix) )
2147
+    {
2148
+        /* printf("'%c' '%c'\n", *str, *suffix); */
2149
+
2150
+        /* return 1 (success) if match persists until the string terminator */
2151
+        if (*str == '\0')
2152
+            return 1;
2153
+
2154
+        /* next chars */
2155
+        str++;
2156
+        suffix++;
2157
+    }
2158
+    /* printf("'%c' '%c' mismatch\n", *str, *suffix); */
2159
+
2160
+    /* return 0 (fail) if the matching did not consume the entire suffix */
2161
+    if (*suffix != 0)
2162
+        return 0;   /* failed to consume entire suffix */
2163
+
2164
+    /* skip any remaining whitespace in str */
2165
+    while (isspace(*str))
2166
+        str++;
2167
+
2168
+    /* return 1 (success) if we have reached end of str else return 0 (fail) */
2169
+    return (*str == '\0') ? 1 : 0;
2170
+}
2171
+
2172
+
2173
+static int arg_int_scanfn(struct arg_int *parent, const char *argval)
2174
+{
2175
+    int errorcode = 0;
2176
+
2177
+    if (parent->count == parent->hdr.maxcount)
2178
+    {
2179
+        /* maximum number of arguments exceeded */
2180
+        errorcode = EMAXCOUNT;
2181
+    }
2182
+    else if (!argval)
2183
+    {
2184
+        /* a valid argument with no argument value was given. */
2185
+        /* This happens when an optional argument value was invoked. */
2186
+        /* leave parent arguiment value unaltered but still count the argument. */
2187
+        parent->count++;
2188
+    }
2189
+    else
2190
+    {
2191
+        long int val;
2192
+        const char *end;
2193
+
2194
+        /* attempt to extract hex integer (eg: +0x123) from argval into val conversion */
2195
+        val = strtol0X(argval, &end, 'X', 16);
2196
+        if (end == argval)
2197
+        {
2198
+            /* hex failed, attempt octal conversion (eg +0o123) */
2199
+            val = strtol0X(argval, &end, 'O', 8);
2200
+            if (end == argval)
2201
+            {
2202
+                /* octal failed, attempt binary conversion (eg +0B101) */
2203
+                val = strtol0X(argval, &end, 'B', 2);
2204
+                if (end == argval)
2205
+                {
2206
+                    /* binary failed, attempt decimal conversion with no prefix (eg 1234) */
2207
+                    val = strtol(argval, (char * *)&end, 10);
2208
+                    if (end == argval)
2209
+                    {
2210
+                        /* all supported number formats failed */
2211
+                        return EBADINT;
2212
+                    }
2213
+                }
2214
+            }
2215
+        }
2216
+
2217
+        /* Safety check for integer overflow. WARNING: this check    */
2218
+        /* achieves nothing on machines where size(int)==size(long). */
2219
+        if ( val > INT_MAX || val < INT_MIN )
2220
+            errorcode = EOVERFLOW;
2221
+
2222
+        /* Detect any suffixes (KB,MB,GB) and multiply argument value appropriately. */
2223
+        /* We need to be mindful of integer overflows when using such big numbers.   */
2224
+        if (detectsuffix(end, "KB"))             /* kilobytes */
2225
+        {
2226
+            if ( val > (INT_MAX / 1024) || val < (INT_MIN / 1024) )
2227
+                errorcode = EOVERFLOW;          /* Overflow would occur if we proceed */
2228
+            else
2229
+                val *= 1024;                    /* 1KB = 1024 */
2230
+        }
2231
+        else if (detectsuffix(end, "MB"))        /* megabytes */
2232
+        {
2233
+            if ( val > (INT_MAX / 1048576) || val < (INT_MIN / 1048576) )
2234
+                errorcode = EOVERFLOW;          /* Overflow would occur if we proceed */
2235
+            else
2236
+                val *= 1048576;                 /* 1MB = 1024*1024 */
2237
+        }
2238
+        else if (detectsuffix(end, "GB"))        /* gigabytes */
2239
+        {
2240
+            if ( val > (INT_MAX / 1073741824) || val < (INT_MIN / 1073741824) )
2241
+                errorcode = EOVERFLOW;          /* Overflow would occur if we proceed */
2242
+            else
2243
+                val *= 1073741824;              /* 1GB = 1024*1024*1024 */
2244
+        }
2245
+        else if (!detectsuffix(end, ""))
2246
+            errorcode = EBADINT;                /* invalid suffix detected */
2247
+
2248
+        /* if success then store result in parent->ival[] array */
2249
+        if (errorcode == 0)
2250
+            parent->ival[parent->count++] = val;
2251
+    }
2252
+
2253
+    /* printf("%s:scanfn(%p,%p) returns %d\n",__FILE__,parent,argval,errorcode); */
2254
+    return errorcode;
2255
+}
2256
+
2257
+
2258
+static int arg_int_checkfn(struct arg_int *parent)
2259
+{
2260
+    int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
2261
+    /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/
2262
+    return errorcode;
2263
+}
2264
+
2265
+
2266
+static void arg_int_errorfn(
2267
+    struct arg_int *parent,
2268
+    FILE *fp,
2269
+    int errorcode,
2270
+    const char *argval,
2271
+    const char *progname)
2272
+{
2273
+    const char *shortopts = parent->hdr.shortopts;
2274
+    const char *longopts  = parent->hdr.longopts;
2275
+    const char *datatype  = parent->hdr.datatype;
2276
+
2277
+    /* make argval NULL safe */
2278
+    argval = argval ? argval : "";
2279
+
2280
+    fprintf(fp, "%s: ", progname);
2281
+    switch(errorcode)
2282
+    {
2283
+    case EMINCOUNT:
2284
+        fputs("missing option ", fp);
2285
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
2286
+        break;
2287
+
2288
+    case EMAXCOUNT:
2289
+        fputs("excess option ", fp);
2290
+        arg_print_option(fp, shortopts, longopts, argval, "\n");
2291
+        break;
2292
+
2293
+    case EBADINT:
2294
+        fprintf(fp, "invalid argument \"%s\" to option ", argval);
2295
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
2296
+        break;
2297
+
2298
+    case EOVERFLOW:
2299
+        fputs("integer overflow at option ", fp);
2300
+        arg_print_option(fp, shortopts, longopts, datatype, " ");
2301
+        fprintf(fp, "(%s is too large)\n", argval);
2302
+        break;
2303
+    }
2304
+}
2305
+
2306
+
2307
+struct arg_int * arg_int0(
2308
+    const char *shortopts,
2309
+    const char *longopts,
2310
+    const char *datatype,
2311
+    const char *glossary)
2312
+{
2313
+    return arg_intn(shortopts, longopts, datatype, 0, 1, glossary);
2314
+}
2315
+
2316
+
2317
+struct arg_int * arg_int1(
2318
+    const char *shortopts,
2319
+    const char *longopts,
2320
+    const char *datatype,
2321
+    const char *glossary)
2322
+{
2323
+    return arg_intn(shortopts, longopts, datatype, 1, 1, glossary);
2324
+}
2325
+
2326
+
2327
+struct arg_int * arg_intn(
2328
+    const char *shortopts,
2329
+    const char *longopts,
2330
+    const char *datatype,
2331
+    int mincount,
2332
+    int maxcount,
2333
+    const char *glossary)
2334
+{
2335
+    size_t nbytes;
2336
+    struct arg_int *result;
2337
+
2338
+    /* foolproof things by ensuring maxcount is not less than mincount */
2339
+    maxcount = (maxcount < mincount) ? mincount : maxcount;
2340
+
2341
+    nbytes = sizeof(struct arg_int)    /* storage for struct arg_int */
2342
+             + maxcount * sizeof(int); /* storage for ival[maxcount] array */
2343
+
2344
+    result = (struct arg_int *)malloc(nbytes);
2345
+    if (result)
2346
+    {
2347
+        /* init the arg_hdr struct */
2348
+        result->hdr.flag      = ARG_HASVALUE;
2349
+        result->hdr.shortopts = shortopts;
2350
+        result->hdr.longopts  = longopts;
2351
+        result->hdr.datatype  = datatype ? datatype : "<int>";
2352
+        result->hdr.glossary  = glossary;
2353
+        result->hdr.mincount  = mincount;
2354
+        result->hdr.maxcount  = maxcount;
2355
+        result->hdr.parent    = result;
2356
+        result->hdr.resetfn   = (arg_resetfn *)arg_int_resetfn;
2357
+        result->hdr.scanfn    = (arg_scanfn *)arg_int_scanfn;
2358
+        result->hdr.checkfn   = (arg_checkfn *)arg_int_checkfn;
2359
+        result->hdr.errorfn   = (arg_errorfn *)arg_int_errorfn;
2360
+
2361
+        /* store the ival[maxcount] array immediately after the arg_int struct */
2362
+        result->ival  = (int *)(result + 1);
2363
+        result->count = 0;
2364
+    }
2365
+    
2366
+    ARG_TRACE(("arg_intn() returns %p\n", result));
2367
+    return result;
2368
+}
2369
+/*******************************************************************************
2370
+ * This file is part of the argtable3 library.
2371
+ *
2372
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
2373
+ * <sheitmann@users.sourceforge.net>
2374
+ * All rights reserved.
2375
+ *
2376
+ * Redistribution and use in source and binary forms, with or without
2377
+ * modification, are permitted provided that the following conditions are met:
2378
+ *     * Redistributions of source code must retain the above copyright
2379
+ *       notice, this list of conditions and the following disclaimer.
2380
+ *     * Redistributions in binary form must reproduce the above copyright
2381
+ *       notice, this list of conditions and the following disclaimer in the
2382
+ *       documentation and/or other materials provided with the distribution.
2383
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
2384
+ *       may be used to endorse or promote products derived from this software
2385
+ *       without specific prior written permission.
2386
+ *
2387
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2388
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2389
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2390
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
2391
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2392
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2393
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2394
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2395
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2396
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2397
+ ******************************************************************************/
2398
+
2399
+#include <stdlib.h>
2400
+
2401
+#include "argtable3.h"
2402
+
2403
+
2404
+static void arg_lit_resetfn(struct arg_lit *parent)
2405
+{
2406
+    ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
2407
+    parent->count = 0;
2408
+}
2409
+
2410
+
2411
+static int arg_lit_scanfn(struct arg_lit *parent, const char *argval)
2412
+{
2413
+    int errorcode = 0;
2414
+    if (parent->count < parent->hdr.maxcount )
2415
+        parent->count++;
2416
+    else
2417
+        errorcode = EMAXCOUNT;
2418
+
2419
+    ARG_TRACE(("%s:scanfn(%p,%s) returns %d\n", __FILE__, parent, argval,
2420
+               errorcode));
2421
+    return errorcode;
2422
+}
2423
+
2424
+
2425
+static int arg_lit_checkfn(struct arg_lit *parent)
2426
+{
2427
+    int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
2428
+    ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
2429
+    return errorcode;
2430
+}
2431
+
2432
+
2433
+static void arg_lit_errorfn(
2434
+    struct arg_lit *parent,
2435
+    FILE *fp,
2436
+    int errorcode,
2437
+    const char *argval,
2438
+    const char *progname)
2439
+{
2440
+    const char *shortopts = parent->hdr.shortopts;
2441
+    const char *longopts  = parent->hdr.longopts;
2442
+    const char *datatype  = parent->hdr.datatype;
2443
+
2444
+    switch(errorcode)
2445
+    {
2446
+    case EMINCOUNT:
2447
+        fprintf(fp, "%s: missing option ", progname);
2448
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
2449
+        fprintf(fp, "\n");
2450
+        break;
2451
+
2452
+    case EMAXCOUNT:
2453
+        fprintf(fp, "%s: extraneous option ", progname);
2454
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
2455
+        break;
2456
+    }
2457
+
2458
+    ARG_TRACE(("%s:errorfn(%p, %p, %d, %s, %s)\n", __FILE__, parent, fp,
2459
+               errorcode, argval, progname));
2460
+}
2461
+
2462
+
2463
+struct arg_lit * arg_lit0(
2464
+    const char * shortopts,
2465
+    const char * longopts,
2466
+    const char * glossary)
2467
+{
2468
+    return arg_litn(shortopts, longopts, 0, 1, glossary);
2469
+}
2470
+
2471
+
2472
+struct arg_lit * arg_lit1(
2473
+    const char *shortopts,
2474
+    const char *longopts,
2475
+    const char *glossary)
2476
+{
2477
+    return arg_litn(shortopts, longopts, 1, 1, glossary);
2478
+}
2479
+
2480
+
2481
+struct arg_lit * arg_litn(
2482
+    const char *shortopts,
2483
+    const char *longopts,
2484
+    int mincount,
2485
+    int maxcount,
2486
+    const char *glossary)
2487
+{
2488
+    struct arg_lit *result;
2489
+
2490
+    /* foolproof things by ensuring maxcount is not less than mincount */
2491
+    maxcount = (maxcount < mincount) ? mincount : maxcount;
2492
+
2493
+    result = (struct arg_lit *)malloc(sizeof(struct arg_lit));
2494
+    if (result)
2495
+    {
2496
+        /* init the arg_hdr struct */
2497
+        result->hdr.flag      = 0;
2498
+        result->hdr.shortopts = shortopts;
2499
+        result->hdr.longopts  = longopts;
2500
+        result->hdr.datatype  = NULL;
2501
+        result->hdr.glossary  = glossary;
2502
+        result->hdr.mincount  = mincount;
2503
+        result->hdr.maxcount  = maxcount;
2504
+        result->hdr.parent    = result;
2505
+        result->hdr.resetfn   = (arg_resetfn *)arg_lit_resetfn;
2506
+        result->hdr.scanfn    = (arg_scanfn *)arg_lit_scanfn;
2507
+        result->hdr.checkfn   = (arg_checkfn *)arg_lit_checkfn;
2508
+        result->hdr.errorfn   = (arg_errorfn *)arg_lit_errorfn;
2509
+
2510
+        /* init local variables */
2511
+        result->count = 0;
2512
+    }
2513
+    
2514
+    ARG_TRACE(("arg_litn() returns %p\n", result));
2515
+    return result;
2516
+}
2517
+/*******************************************************************************
2518
+ * This file is part of the argtable3 library.
2519
+ *
2520
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
2521
+ * <sheitmann@users.sourceforge.net>
2522
+ * All rights reserved.
2523
+ *
2524
+ * Redistribution and use in source and binary forms, with or without
2525
+ * modification, are permitted provided that the following conditions are met:
2526
+ *     * Redistributions of source code must retain the above copyright
2527
+ *       notice, this list of conditions and the following disclaimer.
2528
+ *     * Redistributions in binary form must reproduce the above copyright
2529
+ *       notice, this list of conditions and the following disclaimer in the
2530
+ *       documentation and/or other materials provided with the distribution.
2531
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
2532
+ *       may be used to endorse or promote products derived from this software
2533
+ *       without specific prior written permission.
2534
+ *
2535
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2536
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2537
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2538
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
2539
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2540
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2541
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2542
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2543
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2544
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2545
+ ******************************************************************************/
2546
+
2547
+#include <stdlib.h>
2548
+
2549
+#include "argtable3.h"
2550
+
2551
+struct arg_rem *arg_rem(const char *datatype, const char *glossary)
2552
+{
2553
+    struct arg_rem *result = (struct arg_rem *)malloc(sizeof(struct arg_rem));
2554
+    if (result)
2555
+    {
2556
+        result->hdr.flag = 0;
2557
+        result->hdr.shortopts = NULL;
2558
+        result->hdr.longopts = NULL;
2559
+        result->hdr.datatype = datatype;
2560
+        result->hdr.glossary = glossary;
2561
+        result->hdr.mincount = 1;
2562
+        result->hdr.maxcount = 1;
2563
+        result->hdr.parent = result;
2564
+        result->hdr.resetfn = NULL;
2565
+        result->hdr.scanfn = NULL;
2566
+        result->hdr.checkfn = NULL;
2567
+        result->hdr.errorfn = NULL;
2568
+    }
2569
+
2570
+    ARG_TRACE(("arg_rem() returns %p\n", result));
2571
+    return result;
2572
+}
2573
+
2574
+/*******************************************************************************
2575
+ * This file is part of the argtable3 library.
2576
+ *
2577
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
2578
+ * <sheitmann@users.sourceforge.net>
2579
+ * All rights reserved.
2580
+ *
2581
+ * Redistribution and use in source and binary forms, with or without
2582
+ * modification, are permitted provided that the following conditions are met:
2583
+ *     * Redistributions of source code must retain the above copyright
2584
+ *       notice, this list of conditions and the following disclaimer.
2585
+ *     * Redistributions in binary form must reproduce the above copyright
2586
+ *       notice, this list of conditions and the following disclaimer in the
2587
+ *       documentation and/or other materials provided with the distribution.
2588
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
2589
+ *       may be used to endorse or promote products derived from this software
2590
+ *       without specific prior written permission.
2591
+ *
2592
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2593
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2594
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2595
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
2596
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2597
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2598
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2599
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2600
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
2601
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2602
+ ******************************************************************************/
2603
+
2604
+#include <stdlib.h>
2605
+#include <string.h>
2606
+
2607
+#include "argtable3.h"
2608
+
2609
+
2610
+#ifndef _TREX_H_
2611
+#define _TREX_H_
2612
+/***************************************************************
2613
+	T-Rex a tiny regular expression library
2614
+
2615
+	Copyright (C) 2003-2006 Alberto Demichelis
2616
+
2617
+	This software is provided 'as-is', without any express
2618
+	or implied warranty. In no event will the authors be held
2619
+	liable for any damages arising from the use of this software.
2620
+
2621
+	Permission is granted to anyone to use this software for
2622
+	any purpose, including commercial applications, and to alter
2623
+	it and redistribute it freely, subject to the following restrictions:
2624
+
2625
+		1. The origin of this software must not be misrepresented;
2626
+		you must not claim that you wrote the original software.
2627
+		If you use this software in a product, an acknowledgment
2628
+		in the product documentation would be appreciated but
2629
+		is not required.
2630
+
2631
+		2. Altered source versions must be plainly marked as such,
2632
+		and must not be misrepresented as being the original software.
2633
+
2634
+		3. This notice may not be removed or altered from any
2635
+		source distribution.
2636
+
2637
+****************************************************************/
2638
+
2639
+#ifdef __cplusplus
2640
+extern "C" {
2641
+#endif
2642
+
2643
+#ifdef _UNICODE
2644
+#define TRexChar unsigned short
2645
+#define MAX_CHAR 0xFFFF
2646
+#define _TREXC(c) L##c
2647
+#define trex_strlen wcslen
2648
+#define trex_printf wprintf
2649
+#else
2650
+#define TRexChar char
2651
+#define MAX_CHAR 0xFF
2652
+#define _TREXC(c) (c)
2653
+#define trex_strlen strlen
2654
+#define trex_printf printf
2655
+#endif
2656
+
2657
+#ifndef TREX_API
2658
+#define TREX_API extern
2659
+#endif
2660
+
2661
+#define TRex_True 1
2662
+#define TRex_False 0
2663
+
2664
+#define TREX_ICASE ARG_REX_ICASE
2665
+
2666
+typedef unsigned int TRexBool;
2667
+typedef struct TRex TRex;
2668
+
2669
+typedef struct {
2670
+	const TRexChar *begin;
2671
+	int len;
2672
+} TRexMatch;
2673
+
2674
+TREX_API TRex *trex_compile(const TRexChar *pattern, const TRexChar **error, int flags);
2675
+TREX_API void trex_free(TRex *exp);
2676
+TREX_API TRexBool trex_match(TRex* exp, const TRexChar* text);
2677
+TREX_API TRexBool trex_search(TRex* exp, const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end);
2678
+TREX_API TRexBool trex_searchrange(TRex* exp, const TRexChar* text_begin, const TRexChar* text_end, const TRexChar** out_begin, const TRexChar** out_end);
2679
+TREX_API int trex_getsubexpcount(TRex* exp);
2680
+TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp);
2681
+
2682
+#ifdef __cplusplus
2683
+}
2684
+#endif
2685
+
2686
+#endif
2687
+
2688
+
2689
+
2690
+struct privhdr
2691
+{
2692
+    const char *pattern;
2693
+    int flags;
2694
+};
2695
+
2696
+
2697
+static void arg_rex_resetfn(struct arg_rex *parent)
2698
+{
2699
+    ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
2700
+    parent->count = 0;
2701
+}
2702
+
2703
+static int arg_rex_scanfn(struct arg_rex *parent, const char *argval)
2704
+{
2705
+    int errorcode = 0;
2706
+    const TRexChar *error = NULL;
2707
+    TRex *rex = NULL;
2708
+    TRexBool is_match = TRex_False;
2709
+
2710
+    if (parent->count == parent->hdr.maxcount )
2711
+    {
2712
+        /* maximum number of arguments exceeded */
2713
+        errorcode = EMAXCOUNT;
2714
+    }
2715
+    else if (!argval)
2716
+    {
2717
+        /* a valid argument with no argument value was given. */
2718
+        /* This happens when an optional argument value was invoked. */
2719
+        /* leave parent argument value unaltered but still count the argument. */
2720
+        parent->count++;
2721
+    }
2722
+    else
2723
+    {
2724
+        struct privhdr *priv = (struct privhdr *)parent->hdr.priv;
2725
+
2726
+        /* test the current argument value for a match with the regular expression */
2727
+        /* if a match is detected, record the argument value in the arg_rex struct */
2728
+
2729
+        rex = trex_compile(priv->pattern, &error, priv->flags);
2730
+        is_match = trex_match(rex, argval);
2731
+        if (!is_match)
2732
+            errorcode = EREGNOMATCH;
2733
+        else
2734
+            parent->sval[parent->count++] = argval;
2735
+
2736
+        trex_free(rex);
2737
+    }
2738
+
2739
+    ARG_TRACE(("%s:scanfn(%p) returns %d\n",__FILE__,parent,errorcode));
2740
+    return errorcode;
2741
+}
2742
+
2743
+static int arg_rex_checkfn(struct arg_rex *parent)
2744
+{
2745
+    int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
2746
+    /*struct privhdr *priv = (struct privhdr*)parent->hdr.priv;*/
2747
+
2748
+    /* free the regex "program" we constructed in resetfn */
2749
+    /*regfree(&(priv->regex));*/
2750
+
2751
+    /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/
2752
+    return errorcode;
2753
+}
2754
+
2755
+static void arg_rex_errorfn(struct arg_rex *parent,
2756
+                    FILE *fp,
2757
+                    int errorcode,
2758
+                    const char *argval,
2759
+                    const char *progname)
2760
+{
2761
+    const char *shortopts = parent->hdr.shortopts;
2762
+    const char *longopts  = parent->hdr.longopts;
2763
+    const char *datatype  = parent->hdr.datatype;
2764
+
2765
+    /* make argval NULL safe */
2766
+    argval = argval ? argval : "";
2767
+
2768
+    fprintf(fp, "%s: ", progname);
2769
+    switch(errorcode)
2770
+    {
2771
+    case EMINCOUNT:
2772
+        fputs("missing option ", fp);
2773
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
2774
+        break;
2775
+
2776
+    case EMAXCOUNT:
2777
+        fputs("excess option ", fp);
2778
+        arg_print_option(fp, shortopts, longopts, argval, "\n");
2779
+        break;
2780
+
2781
+    case EREGNOMATCH:
2782
+        fputs("illegal value  ", fp);
2783
+        arg_print_option(fp, shortopts, longopts, argval, "\n");
2784
+        break;
2785
+
2786
+    default:
2787
+    {
2788
+        /*char errbuff[256];
2789
+        regerror(errorcode, NULL, errbuff, sizeof(errbuff));
2790
+        printf("%s\n", errbuff);*/
2791
+    }
2792
+    break;
2793
+    }
2794
+}
2795
+
2796
+
2797
+struct arg_rex * arg_rex0(const char * shortopts,
2798
+                          const char * longopts,
2799
+                          const char * pattern,
2800
+                          const char *datatype,
2801
+                          int flags,
2802
+                          const char *glossary)
2803
+{
2804
+    return arg_rexn(shortopts,
2805
+                    longopts,
2806
+                    pattern,
2807
+                    datatype,
2808
+                    0,
2809
+                    1,
2810
+                    flags,
2811
+                    glossary);
2812
+}
2813
+
2814
+struct arg_rex * arg_rex1(const char * shortopts,
2815
+                          const char * longopts,
2816
+                          const char * pattern,
2817
+                          const char *datatype,
2818
+                          int flags,
2819
+                          const char *glossary)
2820
+{
2821
+    return arg_rexn(shortopts,
2822
+                    longopts,
2823
+                    pattern,
2824
+                    datatype,
2825
+                    1,
2826
+                    1,
2827
+                    flags,
2828
+                    glossary);
2829
+}
2830
+
2831
+
2832
+struct arg_rex * arg_rexn(const char * shortopts,
2833
+                          const char * longopts,
2834
+                          const char * pattern,
2835
+                          const char *datatype,
2836
+                          int mincount,
2837
+                          int maxcount,
2838
+                          int flags,
2839
+                          const char *glossary)
2840
+{
2841
+    size_t nbytes;
2842
+    struct arg_rex *result;
2843
+    struct privhdr *priv;
2844
+    int i;
2845
+    const TRexChar *error = NULL;
2846
+    TRex *rex = NULL;
2847
+
2848
+    if (!pattern)
2849
+    {
2850
+        printf(
2851
+            "argtable: ERROR - illegal regular expression pattern \"(NULL)\"\n");
2852
+        printf("argtable: Bad argument table.\n");
2853
+        return NULL;
2854
+    }
2855
+
2856
+    /* foolproof things by ensuring maxcount is not less than mincount */
2857
+    maxcount = (maxcount < mincount) ? mincount : maxcount;
2858
+
2859
+    nbytes = sizeof(struct arg_rex)       /* storage for struct arg_rex */
2860
+             + sizeof(struct privhdr)     /* storage for private arg_rex data */
2861
+             + maxcount * sizeof(char *);  /* storage for sval[maxcount] array */
2862
+
2863
+    result = (struct arg_rex *)malloc(nbytes);
2864
+    if (result == NULL)
2865
+        return result;
2866
+
2867
+    /* init the arg_hdr struct */
2868
+    result->hdr.flag      = ARG_HASVALUE;
2869
+    result->hdr.shortopts = shortopts;
2870
+    result->hdr.longopts  = longopts;
2871
+    result->hdr.datatype  = datatype ? datatype : pattern;
2872
+    result->hdr.glossary  = glossary;
2873
+    result->hdr.mincount  = mincount;
2874
+    result->hdr.maxcount  = maxcount;
2875
+    result->hdr.parent    = result;
2876
+    result->hdr.resetfn   = (arg_resetfn *)arg_rex_resetfn;
2877
+    result->hdr.scanfn    = (arg_scanfn *)arg_rex_scanfn;
2878
+    result->hdr.checkfn   = (arg_checkfn *)arg_rex_checkfn;
2879
+    result->hdr.errorfn   = (arg_errorfn *)arg_rex_errorfn;
2880
+
2881
+    /* store the arg_rex_priv struct immediately after the arg_rex struct */
2882
+    result->hdr.priv  = result + 1;
2883
+    priv = (struct privhdr *)(result->hdr.priv);
2884
+    priv->pattern = pattern;
2885
+    priv->flags = flags;
2886
+
2887
+    /* store the sval[maxcount] array immediately after the arg_rex_priv struct */
2888
+    result->sval  = (const char * *)(priv + 1);
2889
+    result->count = 0;
2890
+
2891
+    /* foolproof the string pointers by initializing them to reference empty strings */
2892
+    for (i = 0; i < maxcount; i++)
2893
+        result->sval[i] = "";
2894
+
2895
+    /* here we construct and destroy a regex representation of the regular
2896
+     * expression for no other reason than to force any regex errors to be
2897
+     * trapped now rather than later. If we don't, then errors may go undetected
2898
+     * until an argument is actually parsed.
2899
+     */
2900
+
2901
+    rex = trex_compile(priv->pattern, &error, priv->flags);
2902
+    if (rex == NULL)
2903
+    {
2904
+        ARG_LOG(("argtable: %s \"%s\"\n", error ? error : _TREXC("undefined"), priv->pattern));
2905
+        ARG_LOG(("argtable: Bad argument table.\n"));
2906
+    }
2907
+
2908
+    trex_free(rex);
2909
+
2910
+    ARG_TRACE(("arg_rexn() returns %p\n", result));
2911
+    return result;
2912
+}
2913
+
2914
+
2915
+
2916
+/* see copyright notice in trex.h */
2917
+#include <string.h>
2918
+#include <stdlib.h>
2919
+#include <ctype.h>
2920
+#include <setjmp.h>
2921
+
2922
+#ifdef _UINCODE
2923
+#define scisprint iswprint
2924
+#define scstrlen wcslen
2925
+#define scprintf wprintf
2926
+#define _SC(x) L(x)
2927
+#else
2928
+#define scisprint isprint
2929
+#define scstrlen strlen
2930
+#define scprintf printf
2931
+#define _SC(x) (x)
2932
+#endif
2933
+
2934
+#ifdef _DEBUG
2935
+#include <stdio.h>
2936
+
2937
+static const TRexChar *g_nnames[] =
2938
+{
2939
+	_SC("NONE"),_SC("OP_GREEDY"),	_SC("OP_OR"),
2940
+	_SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"),	_SC("OP_CLASS"),
2941
+	_SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
2942
+	_SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB")
2943
+};
2944
+
2945
+#endif
2946
+#define OP_GREEDY		(MAX_CHAR+1) /* * + ? {n}*/
2947
+#define OP_OR			(MAX_CHAR+2)
2948
+#define OP_EXPR			(MAX_CHAR+3) /*parentesis ()*/
2949
+#define OP_NOCAPEXPR	(MAX_CHAR+4) /*parentesis (?:)*/
2950
+#define OP_DOT			(MAX_CHAR+5)
2951
+#define OP_CLASS		(MAX_CHAR+6)
2952
+#define OP_CCLASS		(MAX_CHAR+7)
2953
+#define OP_NCLASS		(MAX_CHAR+8) /*negates class the [^*/
2954
+#define OP_RANGE		(MAX_CHAR+9)
2955
+#define OP_CHAR			(MAX_CHAR+10)
2956
+#define OP_EOL			(MAX_CHAR+11)
2957
+#define OP_BOL			(MAX_CHAR+12)
2958
+#define OP_WB			(MAX_CHAR+13)
2959
+
2960
+#define TREX_SYMBOL_ANY_CHAR ('.')
2961
+#define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
2962
+#define TREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
2963
+#define TREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
2964
+#define TREX_SYMBOL_BRANCH ('|')
2965
+#define TREX_SYMBOL_END_OF_STRING ('$')
2966
+#define TREX_SYMBOL_BEGINNING_OF_STRING ('^')
2967
+#define TREX_SYMBOL_ESCAPE_CHAR ('\\')
2968
+
2969
+
2970
+typedef int TRexNodeType;
2971
+
2972
+typedef struct tagTRexNode{
2973
+	TRexNodeType type;
2974
+	int left;
2975
+	int right;
2976
+	int next;
2977
+}TRexNode;
2978
+
2979
+struct TRex{
2980
+	const TRexChar *_eol;
2981
+	const TRexChar *_bol;
2982
+	const TRexChar *_p;
2983
+	int _first;
2984
+	int _op;
2985
+	TRexNode *_nodes;
2986
+	int _nallocated;
2987
+	int _nsize;
2988
+	int _nsubexpr;
2989
+	TRexMatch *_matches;
2990
+	int _currsubexp;
2991
+	void *_jmpbuf;
2992
+	const TRexChar **_error;
2993
+	int _flags;
2994
+};
2995
+
2996
+static int trex_list(TRex *exp);
2997
+
2998
+static int trex_newnode(TRex *exp, TRexNodeType type)
2999
+{
3000
+	TRexNode n;
3001
+	int newid;
3002
+	n.type = type;
3003
+	n.next = n.right = n.left = -1;
3004
+	if(type == OP_EXPR)
3005
+		n.right = exp->_nsubexpr++;
3006
+	if(exp->_nallocated < (exp->_nsize + 1)) {
3007
+		exp->_nallocated *= 2;
3008
+		exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode));
3009
+	}
3010
+	exp->_nodes[exp->_nsize++] = n;
3011
+	newid = exp->_nsize - 1;
3012
+	return (int)newid;
3013
+}
3014
+
3015
+static void trex_error(TRex *exp,const TRexChar *error)
3016
+{
3017
+	if(exp->_error) *exp->_error = error;
3018
+	longjmp(*((jmp_buf*)exp->_jmpbuf),-1);
3019
+}
3020
+
3021
+static void trex_expect(TRex *exp, int n){
3022
+	if((*exp->_p) != n)
3023
+		trex_error(exp, _SC("expected paren"));
3024
+	exp->_p++;
3025
+}
3026
+
3027
+static TRexChar trex_escapechar(TRex *exp)
3028
+{
3029
+	if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){
3030
+		exp->_p++;
3031
+		switch(*exp->_p) {
3032
+		case 'v': exp->_p++; return '\v';
3033
+		case 'n': exp->_p++; return '\n';
3034
+		case 't': exp->_p++; return '\t';
3035
+		case 'r': exp->_p++; return '\r';
3036
+		case 'f': exp->_p++; return '\f';
3037
+		default: return (*exp->_p++);
3038
+		}
3039
+	} else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected"));
3040
+	return (*exp->_p++);
3041
+}
3042
+
3043
+static int trex_charclass(TRex *exp,int classid)
3044
+{
3045
+	int n = trex_newnode(exp,OP_CCLASS);
3046
+	exp->_nodes[n].left = classid;
3047
+	return n;
3048
+}
3049
+
3050
+static int trex_charnode(TRex *exp,TRexBool isclass)
3051
+{
3052
+	TRexChar t;
3053
+	if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) {
3054
+		exp->_p++;
3055
+		switch(*exp->_p) {
3056
+			case 'n': exp->_p++; return trex_newnode(exp,'\n');
3057
+			case 't': exp->_p++; return trex_newnode(exp,'\t');
3058
+			case 'r': exp->_p++; return trex_newnode(exp,'\r');
3059
+			case 'f': exp->_p++; return trex_newnode(exp,'\f');
3060
+			case 'v': exp->_p++; return trex_newnode(exp,'\v');
3061
+			case 'a': case 'A': case 'w': case 'W': case 's': case 'S':
3062
+			case 'd': case 'D': case 'x': case 'X': case 'c': case 'C':
3063
+			case 'p': case 'P': case 'l': case 'u':
3064
+				{
3065
+				t = *exp->_p; exp->_p++;
3066
+				return trex_charclass(exp,t);
3067
+				}
3068
+			case 'b':
3069
+			case 'B':
3070
+				if(!isclass) {
3071
+					int node = trex_newnode(exp,OP_WB);
3072
+					exp->_nodes[node].left = *exp->_p;
3073
+					exp->_p++;
3074
+					return node;
3075
+				} /*else default*/
3076
+			default:
3077
+				t = *exp->_p; exp->_p++;
3078
+				return trex_newnode(exp,t);
3079
+		}
3080
+	}
3081
+	else if(!scisprint(*exp->_p)) {
3082
+
3083
+		trex_error(exp,_SC("letter expected"));
3084
+	}
3085
+	t = *exp->_p; exp->_p++;
3086
+	return trex_newnode(exp,t);
3087
+}
3088
+static int trex_class(TRex *exp)
3089
+{
3090
+	int ret = -1;
3091
+	int first = -1,chain;
3092
+	if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){
3093
+		ret = trex_newnode(exp,OP_NCLASS);
3094
+		exp->_p++;
3095
+	}else ret = trex_newnode(exp,OP_CLASS);
3096
+
3097
+	if(*exp->_p == ']') trex_error(exp,_SC("empty class"));
3098
+	chain = ret;
3099
+	while(*exp->_p != ']' && exp->_p != exp->_eol) {
3100
+		if(*exp->_p == '-' && first != -1){
3101
+			int r,t;
3102
+			if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range"));
3103
+			r = trex_newnode(exp,OP_RANGE);
3104
+			if(first>*exp->_p) trex_error(exp,_SC("invalid range"));
3105
+			if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges"));
3106
+			exp->_nodes[r].left = exp->_nodes[first].type;
3107
+			t = trex_escapechar(exp);
3108
+			exp->_nodes[r].right = t;
3109
+            exp->_nodes[chain].next = r;
3110
+			chain = r;
3111
+			first = -1;
3112
+		}
3113
+		else{
3114
+			if(first!=-1){
3115
+				int c = first;
3116
+				exp->_nodes[chain].next = c;
3117
+				chain = c;
3118
+				first = trex_charnode(exp,TRex_True);
3119
+			}
3120
+			else{
3121
+				first = trex_charnode(exp,TRex_True);
3122
+			}
3123
+		}
3124
+	}
3125
+	if(first!=-1){
3126
+		int c = first;
3127
+		exp->_nodes[chain].next = c;
3128
+		chain = c;
3129
+		first = -1;
3130
+	}
3131
+	/* hack? */
3132
+	exp->_nodes[ret].left = exp->_nodes[ret].next;
3133
+	exp->_nodes[ret].next = -1;
3134
+	return ret;
3135
+}
3136
+
3137
+static int trex_parsenumber(TRex *exp)
3138
+{
3139
+	int ret = *exp->_p-'0';
3140
+	int positions = 10;
3141
+	exp->_p++;
3142
+	while(isdigit(*exp->_p)) {
3143
+		ret = ret*10+(*exp->_p++-'0');
3144
+		if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant"));
3145
+		positions *= 10;
3146
+	};
3147
+	return ret;
3148
+}
3149
+
3150
+static int trex_element(TRex *exp)
3151
+{
3152
+	int ret = -1;
3153
+	switch(*exp->_p)
3154
+	{
3155
+	case '(': {
3156
+		int expr,newn;
3157
+		exp->_p++;
3158
+
3159
+
3160
+		if(*exp->_p =='?') {
3161
+			exp->_p++;
3162
+			trex_expect(exp,':');
3163
+			expr = trex_newnode(exp,OP_NOCAPEXPR);
3164
+		}
3165
+		else
3166
+			expr = trex_newnode(exp,OP_EXPR);
3167
+		newn = trex_list(exp);
3168
+		exp->_nodes[expr].left = newn;
3169
+		ret = expr;
3170
+		trex_expect(exp,')');
3171
+			  }
3172
+			  break;
3173
+	case '[':
3174
+		exp->_p++;
3175
+		ret = trex_class(exp);
3176
+		trex_expect(exp,']');
3177
+		break;
3178
+	case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break;
3179
+	case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break;
3180
+	default:
3181
+		ret = trex_charnode(exp,TRex_False);
3182
+		break;
3183
+	}
3184
+
3185
+	{
3186
+		TRexBool isgreedy = TRex_False;
3187
+		unsigned short p0 = 0, p1 = 0;
3188
+		switch(*exp->_p){
3189
+			case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break;
3190
+			case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break;
3191
+			case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break;
3192
+			case '{':
3193
+				exp->_p++;
3194
+				if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected"));
3195
+				p0 = (unsigned short)trex_parsenumber(exp);
3196
+				/*******************************/
3197
+				switch(*exp->_p) {
3198
+			case '}':
3199
+				p1 = p0; exp->_p++;
3200
+				break;
3201
+			case ',':
3202
+				exp->_p++;
3203
+				p1 = 0xFFFF;
3204
+				if(isdigit(*exp->_p)){
3205
+					p1 = (unsigned short)trex_parsenumber(exp);
3206
+				}
3207
+				trex_expect(exp,'}');
3208
+				break;
3209
+			default:
3210
+				trex_error(exp,_SC(", or } expected"));
3211
+		}
3212
+		/*******************************/
3213
+		isgreedy = TRex_True;
3214
+		break;
3215
+
3216
+		}
3217
+		if(isgreedy) {
3218
+			int nnode = trex_newnode(exp,OP_GREEDY);
3219
+			exp->_nodes[nnode].left = ret;
3220
+			exp->_nodes[nnode].right = ((p0)<<16)|p1;
3221
+			ret = nnode;
3222
+		}
3223
+	}
3224
+	if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
3225
+		int nnode = trex_element(exp);
3226
+		exp->_nodes[ret].next = nnode;
3227
+	}
3228
+
3229
+	return ret;
3230
+}
3231
+
3232
+static int trex_list(TRex *exp)
3233
+{
3234
+	int ret=-1,e;
3235
+	if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) {
3236
+		exp->_p++;
3237
+		ret = trex_newnode(exp,OP_BOL);
3238
+	}
3239
+	e = trex_element(exp);
3240
+	if(ret != -1) {
3241
+		exp->_nodes[ret].next = e;
3242
+	}
3243
+	else ret = e;
3244
+
3245
+	if(*exp->_p == TREX_SYMBOL_BRANCH) {
3246
+		int temp,tright;
3247
+		exp->_p++;
3248
+		temp = trex_newnode(exp,OP_OR);
3249
+		exp->_nodes[temp].left = ret;
3250
+		tright = trex_list(exp);
3251
+		exp->_nodes[temp].right = tright;
3252
+		ret = temp;
3253
+	}
3254
+	return ret;
3255
+}
3256
+
3257
+static TRexBool trex_matchcclass(int cclass,TRexChar c)
3258
+{
3259
+	switch(cclass) {
3260
+	case 'a': return isalpha(c)?TRex_True:TRex_False;
3261
+	case 'A': return !isalpha(c)?TRex_True:TRex_False;
3262
+	case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False;
3263
+	case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False;
3264
+	case 's': return isspace(c)?TRex_True:TRex_False;
3265
+	case 'S': return !isspace(c)?TRex_True:TRex_False;
3266
+	case 'd': return isdigit(c)?TRex_True:TRex_False;
3267
+	case 'D': return !isdigit(c)?TRex_True:TRex_False;
3268
+	case 'x': return isxdigit(c)?TRex_True:TRex_False;
3269
+	case 'X': return !isxdigit(c)?TRex_True:TRex_False;
3270
+	case 'c': return iscntrl(c)?TRex_True:TRex_False;
3271
+	case 'C': return !iscntrl(c)?TRex_True:TRex_False;
3272
+	case 'p': return ispunct(c)?TRex_True:TRex_False;
3273
+	case 'P': return !ispunct(c)?TRex_True:TRex_False;
3274
+	case 'l': return islower(c)?TRex_True:TRex_False;
3275
+	case 'u': return isupper(c)?TRex_True:TRex_False;
3276
+	}
3277
+	return TRex_False; /*cannot happen*/
3278
+}
3279
+
3280
+static TRexBool trex_matchclass(TRex* exp,TRexNode *node,TRexChar c)
3281
+{
3282
+	do {
3283
+		switch(node->type) {
3284
+			case OP_RANGE:
3285
+				if (exp->_flags & TREX_ICASE)
3286
+				{
3287
+					if(c >= toupper(node->left) && c <= toupper(node->right)) return TRex_True;
3288
+					if(c >= tolower(node->left) && c <= tolower(node->right)) return TRex_True;
3289
+				}
3290
+				else
3291
+				{
3292
+					if(c >= node->left && c <= node->right) return TRex_True;
3293
+				}
3294
+				break;
3295
+			case OP_CCLASS:
3296
+				if(trex_matchcclass(node->left,c)) return TRex_True;
3297
+				break;
3298
+			default:
3299
+				if (exp->_flags & TREX_ICASE)
3300
+				{
3301
+					if (c == tolower(node->type) || c == toupper(node->type)) return TRex_True;
3302
+				}
3303
+				else
3304
+				{
3305
+					if(c == node->type)return TRex_True;
3306
+				}
3307
+
3308
+		}
3309
+	} while((node->next != -1) && (node = &exp->_nodes[node->next]));
3310
+	return TRex_False;
3311
+}
3312
+
3313
+static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *str,TRexNode *next)
3314
+{
3315
+
3316
+	TRexNodeType type = node->type;
3317
+	switch(type) {
3318
+	case OP_GREEDY: {
3319
+		/*TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;*/
3320
+		TRexNode *greedystop = NULL;
3321
+		int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
3322
+		const TRexChar *s=str, *good = str;
3323
+
3324
+		if(node->next != -1) {
3325
+			greedystop = &exp->_nodes[node->next];
3326
+		}
3327
+		else {
3328
+			greedystop = next;
3329
+		}
3330
+
3331
+		while((nmaches == 0xFFFF || nmaches < p1)) {
3332
+
3333
+			const TRexChar *stop;
3334
+			if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
3335
+				break;
3336
+			nmaches++;
3337
+			good=s;
3338
+			if(greedystop) {
3339
+				/*checks that 0 matches satisfy the expression(if so skips)
3340
+				if not would always stop(for instance if is a '?')*/
3341
+				if(greedystop->type != OP_GREEDY ||
3342
+				(greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
3343
+				{
3344
+					TRexNode *gnext = NULL;
3345
+					if(greedystop->next != -1) {
3346
+						gnext = &exp->_nodes[greedystop->next];
3347
+					}else if(next && next->next != -1){
3348
+						gnext = &exp->_nodes[next->next];
3349
+					}
3350
+					stop = trex_matchnode(exp,greedystop,s,gnext);
3351
+					if(stop) {
3352
+						/*if satisfied stop it*/
3353
+						if(p0 == p1 && p0 == nmaches) break;
3354
+						else if(nmaches >= p0 && p1 == 0xFFFF) break;
3355
+						else if(nmaches >= p0 && nmaches <= p1) break;
3356
+					}
3357
+				}
3358
+			}
3359
+
3360
+			if(s >= exp->_eol)
3361
+				break;
3362
+		}
3363
+		if(p0 == p1 && p0 == nmaches) return good;
3364
+		else if(nmaches >= p0 && p1 == 0xFFFF) return good;
3365
+		else if(nmaches >= p0 && nmaches <= p1) return good;
3366
+		return NULL;
3367
+	}
3368
+	case OP_OR: {
3369
+			const TRexChar *asd = str;
3370
+			TRexNode *temp=&exp->_nodes[node->left];
3371
+			while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) {
3372
+				if(temp->next != -1)
3373
+					temp = &exp->_nodes[temp->next];
3374
+				else
3375
+					return asd;
3376
+			}
3377
+			asd = str;
3378
+			temp = &exp->_nodes[node->right];
3379
+			while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) {
3380
+				if(temp->next != -1)
3381
+					temp = &exp->_nodes[temp->next];
3382
+				else
3383
+					return asd;
3384
+			}
3385
+			return NULL;
3386
+			break;
3387
+	}
3388
+	case OP_EXPR:
3389
+	case OP_NOCAPEXPR:{
3390
+			TRexNode *n = &exp->_nodes[node->left];
3391
+			const TRexChar *cur = str;
3392
+			int capture = -1;
3393
+			if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
3394
+				capture = exp->_currsubexp;
3395
+				exp->_matches[capture].begin = cur;
3396
+				exp->_currsubexp++;
3397
+			}
3398
+
3399
+			do {
3400
+				TRexNode *subnext = NULL;
3401
+				if(n->next != -1) {
3402
+					subnext = &exp->_nodes[n->next];
3403
+				}else {
3404
+					subnext = next;
3405
+				}
3406
+				if(!(cur = trex_matchnode(exp,n,cur,subnext))) {
3407
+					if(capture != -1){
3408
+						exp->_matches[capture].begin = 0;
3409
+						exp->_matches[capture].len = 0;
3410
+					}
3411
+					return NULL;
3412
+				}
3413
+			} while((n->next != -1) && (n = &exp->_nodes[n->next]));
3414
+
3415
+			if(capture != -1)
3416
+				exp->_matches[capture].len = (int)(cur - exp->_matches[capture].begin);
3417
+			return cur;
3418
+	}
3419
+	case OP_WB:
3420
+		if((str == exp->_bol && !isspace(*str))
3421
+		 || ((str == exp->_eol && !isspace(*(str-1))))
3422
+		 || ((!isspace(*str) && isspace(*(str+1))))
3423
+		 || ((isspace(*str) && !isspace(*(str+1)))) ) {
3424
+			return (node->left == 'b')?str:NULL;
3425
+		}
3426
+		return (node->left == 'b')?NULL:str;
3427
+	case OP_BOL:
3428
+		if(str == exp->_bol) return str;
3429
+		return NULL;
3430
+	case OP_EOL:
3431
+		if(str == exp->_eol) return str;
3432
+		return NULL;
3433
+	case OP_DOT:
3434
+		str++;
3435
+		return str;
3436
+	case OP_NCLASS:
3437
+	case OP_CLASS:
3438
+		if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) {
3439
+                        str++;
3440
+			return str;
3441
+		}
3442
+		return NULL;
3443
+	case OP_CCLASS:
3444
+		if(trex_matchcclass(node->left,*str)) {
3445
+                        str++;
3446
+			return str;
3447
+		}
3448
+		return NULL;
3449
+	default: /* char */
3450
+		if (exp->_flags & TREX_ICASE)
3451
+		{
3452
+			if(*str != tolower(node->type) && *str != toupper(node->type)) return NULL;
3453
+		}
3454
+		else
3455
+		{
3456
+			if (*str != node->type) return NULL;
3457
+		}
3458
+		str++;
3459
+		return str;
3460
+	}
3461
+	return NULL;
3462
+}
3463
+
3464
+/* public api */
3465
+TRex *trex_compile(const TRexChar *pattern,const TRexChar **error,int flags)
3466
+{
3467
+	TRex *exp = (TRex *)malloc(sizeof(TRex));
3468
+	exp->_eol = exp->_bol = NULL;
3469
+	exp->_p = pattern;
3470
+	exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar);
3471
+	exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode));
3472
+	exp->_nsize = 0;
3473
+	exp->_matches = 0;
3474
+	exp->_nsubexpr = 0;
3475
+	exp->_first = trex_newnode(exp,OP_EXPR);
3476
+	exp->_error = error;
3477
+	exp->_jmpbuf = malloc(sizeof(jmp_buf));
3478
+	exp->_flags = flags;
3479
+	if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
3480
+		int res = trex_list(exp);
3481
+		exp->_nodes[exp->_first].left = res;
3482
+		if(*exp->_p!='\0')
3483
+			trex_error(exp,_SC("unexpected character"));
3484
+#ifdef _DEBUG
3485
+		{
3486
+			int nsize,i;
3487
+			TRexNode *t;
3488
+			nsize = exp->_nsize;
3489
+			t = &exp->_nodes[0];
3490
+			scprintf(_SC("\n"));
3491
+			for(i = 0;i < nsize; i++) {
3492
+				if(exp->_nodes[i].type>MAX_CHAR)
3493
+					scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
3494
+				else
3495
+					scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);
3496
+				scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);
3497
+			}
3498
+			scprintf(_SC("\n"));
3499
+		}
3500
+#endif
3501
+		exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch));
3502
+		memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch));
3503
+	}
3504
+	else{
3505
+		trex_free(exp);
3506
+		return NULL;
3507
+	}
3508
+	return exp;
3509
+}
3510
+
3511
+void trex_free(TRex *exp)
3512
+{
3513
+	if(exp)	{
3514
+		if(exp->_nodes) free(exp->_nodes);
3515
+		if(exp->_jmpbuf) free(exp->_jmpbuf);
3516
+		if(exp->_matches) free(exp->_matches);
3517
+		free(exp);
3518
+	}
3519
+}
3520
+
3521
+TRexBool trex_match(TRex* exp,const TRexChar* text)
3522
+{
3523
+	const TRexChar* res = NULL;
3524
+	exp->_bol = text;
3525
+	exp->_eol = text + scstrlen(text);
3526
+	exp->_currsubexp = 0;
3527
+	res = trex_matchnode(exp,exp->_nodes,text,NULL);
3528
+	if(res == NULL || res != exp->_eol)
3529
+		return TRex_False;
3530
+	return TRex_True;
3531
+}
3532
+
3533
+TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end)
3534
+{
3535
+	const TRexChar *cur = NULL;
3536
+	int node = exp->_first;
3537
+	if(text_begin >= text_end) return TRex_False;
3538
+	exp->_bol = text_begin;
3539
+	exp->_eol = text_end;
3540
+	do {
3541
+		cur = text_begin;
3542
+		while(node != -1) {
3543
+			exp->_currsubexp = 0;
3544
+			cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL);
3545
+			if(!cur)
3546
+				break;
3547
+			node = exp->_nodes[node].next;
3548
+		}
3549
+		text_begin++;
3550
+	} while(cur == NULL && text_begin != text_end);
3551
+
3552
+	if(cur == NULL)
3553
+		return TRex_False;
3554
+
3555
+	--text_begin;
3556
+
3557
+	if(out_begin) *out_begin = text_begin;
3558
+	if(out_end) *out_end = cur;
3559
+	return TRex_True;
3560
+}
3561
+
3562
+TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end)
3563
+{
3564
+	return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);
3565
+}
3566
+
3567
+int trex_getsubexpcount(TRex* exp)
3568
+{
3569
+	return exp->_nsubexpr;
3570
+}
3571
+
3572
+TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp)
3573
+{
3574
+	if( n<0 || n >= exp->_nsubexpr) return TRex_False;
3575
+	*subexp = exp->_matches[n];
3576
+	return TRex_True;
3577
+}
3578
+/*******************************************************************************
3579
+ * This file is part of the argtable3 library.
3580
+ *
3581
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
3582
+ * <sheitmann@users.sourceforge.net>
3583
+ * All rights reserved.
3584
+ *
3585
+ * Redistribution and use in source and binary forms, with or without
3586
+ * modification, are permitted provided that the following conditions are met:
3587
+ *     * Redistributions of source code must retain the above copyright
3588
+ *       notice, this list of conditions and the following disclaimer.
3589
+ *     * Redistributions in binary form must reproduce the above copyright
3590
+ *       notice, this list of conditions and the following disclaimer in the
3591
+ *       documentation and/or other materials provided with the distribution.
3592
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
3593
+ *       may be used to endorse or promote products derived from this software
3594
+ *       without specific prior written permission.
3595
+ *
3596
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3597
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3598
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3599
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
3600
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3601
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3602
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3603
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3604
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3605
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3606
+ ******************************************************************************/
3607
+
3608
+#include <stdlib.h>
3609
+
3610
+#include "argtable3.h"
3611
+
3612
+
3613
+static void arg_str_resetfn(struct arg_str *parent)
3614
+{
3615
+    ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent));
3616
+    parent->count = 0;
3617
+}
3618
+
3619
+
3620
+static int arg_str_scanfn(struct arg_str *parent, const char *argval)
3621
+{
3622
+    int errorcode = 0;
3623
+
3624
+    if (parent->count == parent->hdr.maxcount)
3625
+    {
3626
+        /* maximum number of arguments exceeded */
3627
+        errorcode = EMAXCOUNT;
3628
+    }
3629
+    else if (!argval)
3630
+    {
3631
+        /* a valid argument with no argument value was given. */
3632
+        /* This happens when an optional argument value was invoked. */
3633
+        /* leave parent arguiment value unaltered but still count the argument. */
3634
+        parent->count++;
3635
+    }
3636
+    else
3637
+    {
3638
+        parent->sval[parent->count++] = argval;
3639
+    }
3640
+
3641
+    ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode));
3642
+    return errorcode;
3643
+}
3644
+
3645
+
3646
+static int arg_str_checkfn(struct arg_str *parent)
3647
+{
3648
+    int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0;
3649
+    
3650
+    ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode));
3651
+    return errorcode;
3652
+}
3653
+
3654
+
3655
+static void arg_str_errorfn(
3656
+    struct arg_str *parent,
3657
+    FILE *fp,
3658
+    int errorcode,
3659
+    const char *argval,
3660
+    const char *progname)
3661
+{
3662
+    const char *shortopts = parent->hdr.shortopts;
3663
+    const char *longopts  = parent->hdr.longopts;
3664
+    const char *datatype  = parent->hdr.datatype;
3665
+
3666
+    /* make argval NULL safe */
3667
+    argval = argval ? argval : "";
3668
+
3669
+    fprintf(fp, "%s: ", progname);
3670
+    switch(errorcode)
3671
+    {
3672
+    case EMINCOUNT:
3673
+        fputs("missing option ", fp);
3674
+        arg_print_option(fp, shortopts, longopts, datatype, "\n");
3675
+        break;
3676
+
3677
+    case EMAXCOUNT:
3678
+        fputs("excess option ", fp);
3679
+        arg_print_option(fp, shortopts, longopts, argval, "\n");
3680
+        break;
3681
+    }
3682
+}
3683
+
3684
+
3685
+struct arg_str * arg_str0(
3686
+    const char *shortopts,
3687
+    const char *longopts,
3688
+    const char *datatype,
3689
+    const char *glossary)
3690
+{
3691
+    return arg_strn(shortopts, longopts, datatype, 0, 1, glossary);
3692
+}
3693
+
3694
+
3695
+struct arg_str * arg_str1(
3696
+    const char *shortopts,
3697
+    const char *longopts,
3698
+    const char *datatype,
3699
+    const char *glossary)
3700
+{
3701
+    return arg_strn(shortopts, longopts, datatype, 1, 1, glossary);
3702
+}
3703
+
3704
+
3705
+struct arg_str * arg_strn(
3706
+    const char *shortopts,
3707
+    const char *longopts,
3708
+    const char *datatype,
3709
+    int mincount,
3710
+    int maxcount,
3711
+    const char *glossary)
3712
+{
3713
+    size_t nbytes;
3714
+    struct arg_str *result;
3715
+
3716
+    /* should not allow this stupid error */
3717
+    /* we should return an error code warning this logic error */
3718
+    /* foolproof things by ensuring maxcount is not less than mincount */
3719
+    maxcount = (maxcount < mincount) ? mincount : maxcount;
3720
+
3721
+    nbytes = sizeof(struct arg_str)     /* storage for struct arg_str */
3722
+             + maxcount * sizeof(char *); /* storage for sval[maxcount] array */
3723
+
3724
+    result = (struct arg_str *)malloc(nbytes);
3725
+    if (result)
3726
+    {
3727
+        int i;
3728
+
3729
+        /* init the arg_hdr struct */
3730
+        result->hdr.flag      = ARG_HASVALUE;
3731
+        result->hdr.shortopts = shortopts;
3732
+        result->hdr.longopts  = longopts;
3733
+        result->hdr.datatype  = datatype ? datatype : "<string>";
3734
+        result->hdr.glossary  = glossary;
3735
+        result->hdr.mincount  = mincount;
3736
+        result->hdr.maxcount  = maxcount;
3737
+        result->hdr.parent    = result;
3738
+        result->hdr.resetfn   = (arg_resetfn *)arg_str_resetfn;
3739
+        result->hdr.scanfn    = (arg_scanfn *)arg_str_scanfn;
3740
+        result->hdr.checkfn   = (arg_checkfn *)arg_str_checkfn;
3741
+        result->hdr.errorfn   = (arg_errorfn *)arg_str_errorfn;
3742
+
3743
+        /* store the sval[maxcount] array immediately after the arg_str struct */
3744
+        result->sval  = (const char * *)(result + 1);
3745
+        result->count = 0;
3746
+
3747
+        /* foolproof the string pointers by initialising them to reference empty strings */
3748
+        for (i = 0; i < maxcount; i++)
3749
+            result->sval[i] = "";
3750
+    }
3751
+    
3752
+    ARG_TRACE(("arg_strn() returns %p\n", result));
3753
+    return result;
3754
+}
3755
+/*******************************************************************************
3756
+ * This file is part of the argtable3 library.
3757
+ *
3758
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
3759
+ * <sheitmann@users.sourceforge.net>
3760
+ * All rights reserved.
3761
+ *
3762
+ * Redistribution and use in source and binary forms, with or without
3763
+ * modification, are permitted provided that the following conditions are met:
3764
+ *     * Redistributions of source code must retain the above copyright
3765
+ *       notice, this list of conditions and the following disclaimer.
3766
+ *     * Redistributions in binary form must reproduce the above copyright
3767
+ *       notice, this list of conditions and the following disclaimer in the
3768
+ *       documentation and/or other materials provided with the distribution.
3769
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
3770
+ *       may be used to endorse or promote products derived from this software
3771
+ *       without specific prior written permission.
3772
+ *
3773
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
3774
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3775
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3776
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
3777
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
3778
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
3779
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
3780
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3781
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3782
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3783
+ ******************************************************************************/
3784
+
3785
+#include <stdlib.h>
3786
+#include <string.h>
3787
+#include <stdlib.h>
3788
+#include <ctype.h>
3789
+
3790
+#include "argtable3.h"
3791
+
3792
+static
3793
+void arg_register_error(struct arg_end *end,
3794
+                        void *parent,
3795
+                        int error,
3796
+                        const char *argval)
3797
+{
3798
+    /* printf("arg_register_error(%p,%p,%d,%s)\n",end,parent,error,argval); */
3799
+    if (end->count < end->hdr.maxcount)
3800
+    {
3801
+        end->error[end->count] = error;
3802
+        end->parent[end->count] = parent;
3803
+        end->argval[end->count] = argval;
3804
+        end->count++;
3805
+    }
3806
+    else
3807
+    {
3808
+        end->error[end->hdr.maxcount - 1]  = ARG_ELIMIT;
3809
+        end->parent[end->hdr.maxcount - 1] = end;
3810
+        end->argval[end->hdr.maxcount - 1] = NULL;
3811
+    }
3812
+}
3813
+
3814
+
3815
+/*
3816
+ * Return index of first table entry with a matching short option
3817
+ * or -1 if no match was found.
3818
+ */
3819
+static
3820
+int find_shortoption(struct arg_hdr * *table, char shortopt)
3821
+{
3822
+    int tabindex;
3823
+    for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++)
3824
+    {
3825
+        if (table[tabindex]->shortopts &&
3826
+            strchr(table[tabindex]->shortopts, shortopt))
3827
+            return tabindex;
3828
+    }
3829
+    return -1;
3830
+}
3831
+
3832
+
3833
+struct longoptions
3834
+{
3835
+    int getoptval;
3836
+    int noptions;
3837
+    struct option *options;
3838
+};
3839
+
3840
+#if 0
3841
+static
3842
+void dump_longoptions(struct longoptions * longoptions)
3843
+{
3844
+    int i;
3845
+    printf("getoptval = %d\n", longoptions->getoptval);
3846
+    printf("noptions  = %d\n", longoptions->noptions);
3847
+    for (i = 0; i < longoptions->noptions; i++)
3848
+    {
3849
+        printf("options[%d].name    = \"%s\"\n",
3850
+               i,
3851
+               longoptions->options[i].name);
3852
+        printf("options[%d].has_arg = %d\n", i, longoptions->options[i].has_arg);
3853
+        printf("options[%d].flag    = %p\n", i, longoptions->options[i].flag);
3854
+        printf("options[%d].val     = %d\n", i, longoptions->options[i].val);
3855
+    }
3856
+}
3857
+#endif
3858
+
3859
+static
3860
+struct longoptions * alloc_longoptions(struct arg_hdr * *table)
3861
+{
3862
+    struct longoptions *result;
3863
+    size_t nbytes;
3864
+    int noptions = 1;
3865
+    size_t longoptlen = 0;
3866
+    int tabindex;
3867
+
3868
+    /*
3869
+     * Determine the total number of option structs required
3870
+     * by counting the number of comma separated long options
3871
+     * in all table entries and return the count in noptions.
3872
+     * note: noptions starts at 1 not 0 because we getoptlong
3873
+     * requires a NULL option entry to terminate the option array.
3874
+     * While we are at it, count the number of chars required
3875
+     * to store private copies of all the longoption strings
3876
+     * and return that count in logoptlen.
3877
+     */
3878
+    tabindex = 0;
3879
+    do
3880
+    {
3881
+        const char *longopts = table[tabindex]->longopts;
3882
+        longoptlen += (longopts ? strlen(longopts) : 0) + 1;
3883
+        while (longopts)
3884
+        {
3885
+            noptions++;
3886
+            longopts = strchr(longopts + 1, ',');
3887
+        }
3888
+    } while(!(table[tabindex++]->flag & ARG_TERMINATOR));
3889
+    /*printf("%d long options consuming %d chars in total\n",noptions,longoptlen);*/
3890
+
3891
+
3892
+    /* allocate storage for return data structure as: */
3893
+    /* (struct longoptions) + (struct options)[noptions] + char[longoptlen] */
3894
+    nbytes = sizeof(struct longoptions)
3895
+             + sizeof(struct option) * noptions
3896
+             + longoptlen;
3897
+    result = (struct longoptions *)malloc(nbytes);
3898
+    if (result)
3899
+    {
3900
+        int option_index = 0;
3901
+        char *store;
3902
+
3903
+        result->getoptval = 0;
3904
+        result->noptions = noptions;
3905
+        result->options = (struct option *)(result + 1);
3906
+        store = (char *)(result->options + noptions);
3907
+
3908
+        for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++)
3909
+        {
3910
+            const char *longopts = table[tabindex]->longopts;
3911
+
3912
+            while(longopts && *longopts)
3913
+            {
3914
+                char *storestart = store;
3915
+
3916
+                /* copy progressive longopt strings into the store */
3917
+                while (*longopts != 0 && *longopts != ',')
3918
+                    *store++ = *longopts++;
3919
+                *store++ = 0;
3920
+                if (*longopts == ',')
3921
+                    longopts++;
3922
+                /*fprintf(stderr,"storestart=\"%s\"\n",storestart);*/
3923
+
3924
+                result->options[option_index].name    = storestart;
3925
+                result->options[option_index].flag    = &(result->getoptval);
3926
+                result->options[option_index].val     = tabindex;
3927
+                if (table[tabindex]->flag & ARG_HASOPTVALUE)
3928
+                    result->options[option_index].has_arg = 2;
3929
+                else if (table[tabindex]->flag & ARG_HASVALUE)
3930
+                    result->options[option_index].has_arg = 1;
3931
+                else
3932
+                    result->options[option_index].has_arg = 0;
3933
+
3934
+                option_index++;
3935
+            }
3936
+        }
3937
+        /* terminate the options array with a zero-filled entry */
3938
+        result->options[option_index].name    = 0;
3939
+        result->options[option_index].has_arg = 0;
3940
+        result->options[option_index].flag    = 0;
3941
+        result->options[option_index].val     = 0;
3942
+    }
3943
+
3944
+    /*dump_longoptions(result);*/
3945
+    return result;
3946
+}
3947
+
3948
+static
3949
+char * alloc_shortoptions(struct arg_hdr * *table)
3950
+{
3951
+    char *result;
3952
+    size_t len = 2;
3953
+    int tabindex;
3954
+
3955
+    /* determine the total number of option chars required */
3956
+    for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++)
3957
+    {
3958
+        struct arg_hdr *hdr = table[tabindex];
3959
+        len += 3 * (hdr->shortopts ? strlen(hdr->shortopts) : 0);
3960
+    }
3961
+
3962
+    result = malloc(len);
3963
+    if (result)
3964
+    {
3965
+        char *res = result;
3966
+
3967
+        /* add a leading ':' so getopt return codes distinguish    */
3968
+        /* unrecognised option and options missing argument values */
3969
+        *res++ = ':';
3970
+
3971
+        for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++)
3972
+        {
3973
+            struct arg_hdr *hdr = table[tabindex];
3974
+            const char *shortopts = hdr->shortopts;
3975
+            while(shortopts && *shortopts)
3976
+            {
3977
+                *res++ = *shortopts++;
3978
+                if (hdr->flag & ARG_HASVALUE)
3979
+                    *res++ = ':';
3980
+                if (hdr->flag & ARG_HASOPTVALUE)
3981
+                    *res++ = ':';
3982
+            }
3983
+        }
3984
+        /* null terminate the string */
3985
+        *res = 0;
3986
+    }
3987
+
3988
+    /*printf("alloc_shortoptions() returns \"%s\"\n",(result?result:"NULL"));*/
3989
+    return result;
3990
+}
3991
+
3992
+
3993
+/* return index of the table terminator entry */
3994
+static
3995
+int arg_endindex(struct arg_hdr * *table)
3996
+{
3997
+    int tabindex = 0;
3998
+    while (!(table[tabindex]->flag & ARG_TERMINATOR))
3999
+        tabindex++;
4000
+    return tabindex;
4001
+}
4002
+
4003
+
4004
+static
4005
+void arg_parse_tagged(int argc,
4006
+                      char * *argv,
4007
+                      struct arg_hdr * *table,
4008
+                      struct arg_end *endtable)
4009
+{
4010
+    struct longoptions *longoptions;
4011
+    char *shortoptions;
4012
+    int copt;
4013
+
4014
+    /*printf("arg_parse_tagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/
4015
+
4016
+    /* allocate short and long option arrays for the given opttable[].   */
4017
+    /* if the allocs fail then put an error msg in the last table entry. */
4018
+    longoptions  = alloc_longoptions(table);
4019
+    shortoptions = alloc_shortoptions(table);
4020
+    if (!longoptions || !shortoptions)
4021
+    {
4022
+        /* one or both memory allocs failed */
4023
+        arg_register_error(endtable, endtable, ARG_EMALLOC, NULL);
4024
+        /* free anything that was allocated (this is null safe) */
4025
+        free(shortoptions);
4026
+        free(longoptions);
4027
+        return;
4028
+    }
4029
+
4030
+    /*dump_longoptions(longoptions);*/
4031
+
4032
+    /* reset getopts internal option-index to zero, and disable error reporting */
4033
+    optind = 0;
4034
+    opterr = 0;
4035
+
4036
+    /* fetch and process args using getopt_long */
4037
+    while( (copt =
4038
+                getopt_long(argc, argv, shortoptions, longoptions->options,
4039
+                            NULL)) != -1)
4040
+    {
4041
+        /*
4042
+           printf("optarg='%s'\n",optarg);
4043
+           printf("optind=%d\n",optind);
4044
+           printf("copt=%c\n",(char)copt);
4045
+           printf("optopt=%c (%d)\n",optopt, (int)(optopt));
4046
+         */
4047
+        switch(copt)
4048
+        {
4049
+        case 0:
4050
+        {
4051
+            int tabindex = longoptions->getoptval;
4052
+            void *parent  = table[tabindex]->parent;
4053
+            /*printf("long option detected from argtable[%d]\n", tabindex);*/
4054
+            if (optarg && optarg[0] == 0 &&
4055
+                (table[tabindex]->flag & ARG_HASVALUE))
4056
+            {
4057
+                /* printf(": long option %s requires an argument\n",argv[optind-1]); */
4058
+                arg_register_error(endtable, endtable, ARG_EMISSARG,
4059
+                                   argv[optind - 1]);
4060
+                /* continue to scan the (empty) argument value to enforce argument count checking */
4061
+            }
4062
+            if (table[tabindex]->scanfn)
4063
+            {
4064
+                int errorcode = table[tabindex]->scanfn(parent, optarg);
4065
+                if (errorcode != 0)
4066
+                    arg_register_error(endtable, parent, errorcode, optarg);
4067
+            }
4068
+        }
4069
+        break;
4070
+
4071
+        case '?':
4072
+            /*
4073
+             * getopt_long() found an unrecognised short option.
4074
+             * if it was a short option its value is in optopt
4075
+             * if it was a long option then optopt=0
4076
+             */
4077
+            switch (optopt)
4078
+            {
4079
+            case 0:
4080
+                /*printf("?0 unrecognised long option %s\n",argv[optind-1]);*/
4081
+                arg_register_error(endtable, endtable, ARG_ELONGOPT,
4082
+                                   argv[optind - 1]);
4083
+                break;
4084
+            default:
4085
+                /*printf("?* unrecognised short option '%c'\n",optopt);*/
4086
+                arg_register_error(endtable, endtable, optopt, NULL);
4087
+                break;
4088
+            }
4089
+            break;
4090
+
4091
+        case ':':
4092
+            /*
4093
+             * getopt_long() found an option with its argument missing.
4094
+             */
4095
+            /*printf(": option %s requires an argument\n",argv[optind-1]); */
4096
+            arg_register_error(endtable, endtable, ARG_EMISSARG,
4097
+                               argv[optind - 1]);
4098
+            break;
4099
+
4100
+        default:
4101
+        {
4102
+            /* getopt_long() found a valid short option */
4103
+            int tabindex = find_shortoption(table, (char)copt);
4104
+            /*printf("short option detected from argtable[%d]\n", tabindex);*/
4105
+            if (tabindex == -1)
4106
+            {
4107
+                /* should never get here - but handle it just in case */
4108
+                /*printf("unrecognised short option %d\n",copt);*/
4109
+                arg_register_error(endtable, endtable, copt, NULL);
4110
+            }
4111
+            else
4112
+            {
4113
+                if (table[tabindex]->scanfn)
4114
+                {
4115
+                    void *parent  = table[tabindex]->parent;
4116
+                    int errorcode = table[tabindex]->scanfn(parent, optarg);
4117
+                    if (errorcode != 0)
4118
+                        arg_register_error(endtable, parent, errorcode, optarg);
4119
+                }
4120
+            }
4121
+            break;
4122
+        }
4123
+        }
4124
+    }
4125
+
4126
+    free(shortoptions);
4127
+    free(longoptions);
4128
+}
4129
+
4130
+
4131
+static
4132
+void arg_parse_untagged(int argc,
4133
+                        char * *argv,
4134
+                        struct arg_hdr * *table,
4135
+                        struct arg_end *endtable)
4136
+{
4137
+    int tabindex = 0;
4138
+    int errorlast = 0;
4139
+    const char *optarglast = NULL;
4140
+    void *parentlast = NULL;
4141
+
4142
+    /*printf("arg_parse_untagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/
4143
+    while (!(table[tabindex]->flag & ARG_TERMINATOR))
4144
+    {
4145
+        void *parent;
4146
+        int errorcode;
4147
+
4148
+        /* if we have exhausted our argv[optind] entries then we have finished */
4149
+        if (optind >= argc)
4150
+        {
4151
+            /*printf("arg_parse_untagged(): argv[] exhausted\n");*/
4152
+            return;
4153
+        }
4154
+
4155
+        /* skip table entries with non-null long or short options (they are not untagged entries) */
4156
+        if (table[tabindex]->longopts || table[tabindex]->shortopts)
4157
+        {
4158
+            /*printf("arg_parse_untagged(): skipping argtable[%d] (tagged argument)\n",tabindex);*/
4159
+            tabindex++;
4160
+            continue;
4161
+        }
4162
+
4163
+        /* skip table entries with NULL scanfn */
4164
+        if (!(table[tabindex]->scanfn))
4165
+        {
4166
+            /*printf("arg_parse_untagged(): skipping argtable[%d] (NULL scanfn)\n",tabindex);*/
4167
+            tabindex++;
4168
+            continue;
4169
+        }
4170
+
4171
+        /* attempt to scan the current argv[optind] with the current     */
4172
+        /* table[tabindex] entry. If it succeeds then keep it, otherwise */
4173
+        /* try again with the next table[] entry.                        */
4174
+        parent = table[tabindex]->parent;
4175
+        errorcode = table[tabindex]->scanfn(parent, argv[optind]);
4176
+        if (errorcode == 0)
4177
+        {
4178
+            /* success, move onto next argv[optind] but stay with same table[tabindex] */
4179
+            /*printf("arg_parse_untagged(): argtable[%d] successfully matched\n",tabindex);*/
4180
+            optind++;
4181
+
4182
+            /* clear the last tentative error */
4183
+            errorlast = 0;
4184
+        }
4185
+        else
4186
+        {
4187
+            /* failure, try same argv[optind] with next table[tabindex] entry */
4188
+            /*printf("arg_parse_untagged(): argtable[%d] failed match\n",tabindex);*/
4189
+            tabindex++;
4190
+
4191
+            /* remember this as a tentative error we may wish to reinstate later */
4192
+            errorlast = errorcode;
4193
+            optarglast = argv[optind];
4194
+            parentlast = parent;
4195
+        }
4196
+
4197
+    }
4198
+
4199
+    /* if a tenative error still remains at this point then register it as a proper error */
4200
+    if (errorlast)
4201
+    {
4202
+        arg_register_error(endtable, parentlast, errorlast, optarglast);
4203
+        optind++;
4204
+    }
4205
+
4206
+    /* only get here when not all argv[] entries were consumed */
4207
+    /* register an error for each unused argv[] entry */
4208
+    while (optind < argc)
4209
+    {
4210
+        /*printf("arg_parse_untagged(): argv[%d]=\"%s\" not consumed\n",optind,argv[optind]);*/
4211
+        arg_register_error(endtable, endtable, ARG_ENOMATCH, argv[optind++]);
4212
+    }
4213
+
4214
+    return;
4215
+}
4216
+
4217
+
4218
+static
4219
+void arg_parse_check(struct arg_hdr * *table, struct arg_end *endtable)
4220
+{
4221
+    int tabindex = 0;
4222
+    /* printf("arg_parse_check()\n"); */
4223
+    do
4224
+    {
4225
+        if (table[tabindex]->checkfn)
4226
+        {
4227
+            void *parent  = table[tabindex]->parent;
4228
+            int errorcode = table[tabindex]->checkfn(parent);
4229
+            if (errorcode != 0)
4230
+                arg_register_error(endtable, parent, errorcode, NULL);
4231
+        }
4232
+    } while(!(table[tabindex++]->flag & ARG_TERMINATOR));
4233
+}
4234
+
4235
+
4236
+static
4237
+void arg_reset(void * *argtable)
4238
+{
4239
+    struct arg_hdr * *table = (struct arg_hdr * *)argtable;
4240
+    int tabindex = 0;
4241
+    /*printf("arg_reset(%p)\n",argtable);*/
4242
+    do
4243
+    {
4244
+        if (table[tabindex]->resetfn)
4245
+            table[tabindex]->resetfn(table[tabindex]->parent);
4246
+    } while(!(table[tabindex++]->flag & ARG_TERMINATOR));
4247
+}
4248
+
4249
+
4250
+int arg_parse(int argc, char * *argv, void * *argtable)
4251
+{
4252
+    struct arg_hdr * *table = (struct arg_hdr * *)argtable;
4253
+    struct arg_end *endtable;
4254
+    int endindex;
4255
+    char * *argvcopy = NULL;
4256
+
4257
+    /*printf("arg_parse(%d,%p,%p)\n",argc,argv,argtable);*/
4258
+
4259
+    /* reset any argtable data from previous invocations */
4260
+    arg_reset(argtable);
4261
+
4262
+    /* locate the first end-of-table marker within the array */
4263
+    endindex = arg_endindex(table);
4264
+    endtable = (struct arg_end *)table[endindex];
4265
+
4266
+    /* Special case of argc==0.  This can occur on Texas Instruments DSP. */
4267
+    /* Failure to trap this case results in an unwanted NULL result from  */
4268
+    /* the malloc for argvcopy (next code block).                         */
4269
+    if (argc == 0)
4270
+    {
4271
+        /* We must still perform post-parse checks despite the absence of command line arguments */
4272
+        arg_parse_check(table, endtable);
4273
+
4274
+        /* Now we are finished */
4275
+        return endtable->count;
4276
+    }
4277
+
4278
+    argvcopy = (char **)malloc(sizeof(char *) * (argc + 1));
4279
+    if (argvcopy)
4280
+    {
4281
+        int i;
4282
+
4283
+        /*
4284
+           Fill in the local copy of argv[]. We need a local copy
4285
+           because getopt rearranges argv[] which adversely affects
4286
+           susbsequent parsing attempts.
4287
+         */
4288
+        for (i = 0; i < argc; i++)
4289
+            argvcopy[i] = argv[i];
4290
+
4291
+        argvcopy[argc] = NULL;
4292
+        
4293
+        /* parse the command line (local copy) for tagged options */
4294
+        arg_parse_tagged(argc, argvcopy, table, endtable);
4295
+
4296
+        /* parse the command line (local copy) for untagged options */
4297
+        arg_parse_untagged(argc, argvcopy, table, endtable);
4298
+
4299
+        /* if no errors so far then perform post-parse checks otherwise dont bother */
4300
+        if (endtable->count == 0)
4301
+            arg_parse_check(table, endtable);
4302
+
4303
+        /* release the local copt of argv[] */
4304
+        free(argvcopy);
4305
+    }
4306
+    else
4307
+    {
4308
+        /* memory alloc failed */
4309
+        arg_register_error(endtable, endtable, ARG_EMALLOC, NULL);
4310
+    }
4311
+
4312
+    return endtable->count;
4313
+}
4314
+
4315
+
4316
+/*
4317
+ * Concatenate contents of src[] string onto *pdest[] string.
4318
+ * The *pdest pointer is altered to point to the end of the
4319
+ * target string and *pndest is decremented by the same number
4320
+ * of chars.
4321
+ * Does not append more than *pndest chars into *pdest[]
4322
+ * so as to prevent buffer overruns.
4323
+ * Its something like strncat() but more efficient for repeated
4324
+ * calls on the same destination string.
4325
+ * Example of use:
4326
+ *   char dest[30] = "good"
4327
+ *   size_t ndest = sizeof(dest);
4328
+ *   char *pdest = dest;
4329
+ *   arg_char(&pdest,"bye ",&ndest);
4330
+ *   arg_char(&pdest,"cruel ",&ndest);
4331
+ *   arg_char(&pdest,"world!",&ndest);
4332
+ * Results in:
4333
+ *   dest[] == "goodbye cruel world!"
4334
+ *   ndest  == 10
4335
+ */
4336
+static
4337
+void arg_cat(char * *pdest, const char *src, size_t *pndest)
4338
+{
4339
+    char *dest = *pdest;
4340
+    char *end  = dest + *pndest;
4341
+
4342
+    /*locate null terminator of dest string */
4343
+    while(dest < end && *dest != 0)
4344
+        dest++;
4345
+
4346
+    /* concat src string to dest string */
4347
+    while(dest < end && *src != 0)
4348
+        *dest++ = *src++;
4349
+
4350
+    /* null terminate dest string */
4351
+    *dest = 0;
4352
+
4353
+    /* update *pdest and *pndest */
4354
+    *pndest = end - dest;
4355
+    *pdest  = dest;
4356
+}
4357
+
4358
+
4359
+static
4360
+void arg_cat_option(char *dest,
4361
+                    size_t ndest,
4362
+                    const char *shortopts,
4363
+                    const char *longopts,
4364
+                    const char *datatype,
4365
+                    int optvalue)
4366
+{
4367
+    if (shortopts)
4368
+    {
4369
+        char option[3];
4370
+
4371
+        /* note: option array[] is initialiazed dynamically here to satisfy   */
4372
+        /* a deficiency in the watcom compiler wrt static array initializers. */
4373
+        option[0] = '-';
4374
+        option[1] = shortopts[0];
4375
+        option[2] = 0;
4376
+
4377
+        arg_cat(&dest, option, &ndest);
4378
+        if (datatype)
4379
+        {
4380
+            arg_cat(&dest, " ", &ndest);
4381
+            if (optvalue)
4382
+            {
4383
+                arg_cat(&dest, "[", &ndest);
4384
+                arg_cat(&dest, datatype, &ndest);
4385
+                arg_cat(&dest, "]", &ndest);
4386
+            }
4387
+            else
4388
+                arg_cat(&dest, datatype, &ndest);
4389
+        }
4390
+    }
4391
+    else if (longopts)
4392
+    {
4393
+        size_t ncspn;
4394
+
4395
+        /* add "--" tag prefix */
4396
+        arg_cat(&dest, "--", &ndest);
4397
+
4398
+        /* add comma separated option tag */
4399
+        ncspn = strcspn(longopts, ",");
4400
+        strncat(dest, longopts, (ncspn < ndest) ? ncspn : ndest);
4401
+
4402
+        if (datatype)
4403
+        {
4404
+            arg_cat(&dest, "=", &ndest);
4405
+            if (optvalue)
4406
+            {
4407
+                arg_cat(&dest, "[", &ndest);
4408
+                arg_cat(&dest, datatype, &ndest);
4409
+                arg_cat(&dest, "]", &ndest);
4410
+            }
4411
+            else
4412
+                arg_cat(&dest, datatype, &ndest);
4413
+        }
4414
+    }
4415
+    else if (datatype)
4416
+    {
4417
+        if (optvalue)
4418
+        {
4419
+            arg_cat(&dest, "[", &ndest);
4420
+            arg_cat(&dest, datatype, &ndest);
4421
+            arg_cat(&dest, "]", &ndest);
4422
+        }
4423
+        else
4424
+            arg_cat(&dest, datatype, &ndest);
4425
+    }
4426
+}
4427
+
4428
+static
4429
+void arg_cat_optionv(char *dest,
4430
+                     size_t ndest,
4431
+                     const char *shortopts,
4432
+                     const char *longopts,
4433
+                     const char *datatype,
4434
+                     int optvalue,
4435
+                     const char *separator)
4436
+{
4437
+    separator = separator ? separator : "";
4438
+
4439
+    if (shortopts)
4440
+    {
4441
+        const char *c = shortopts;
4442
+        while(*c)
4443
+        {
4444
+            /* "-a|-b|-c" */
4445
+            char shortopt[3];
4446
+
4447
+            /* note: shortopt array[] is initialiazed dynamically here to satisfy */
4448
+            /* a deficiency in the watcom compiler wrt static array initializers. */
4449
+            shortopt[0] = '-';
4450
+            shortopt[1] = *c;
4451
+            shortopt[2] = 0;
4452
+
4453
+            arg_cat(&dest, shortopt, &ndest);
4454
+            if (*++c)
4455
+                arg_cat(&dest, separator, &ndest);
4456
+        }
4457
+    }
4458
+
4459
+    /* put separator between long opts and short opts */
4460
+    if (shortopts && longopts)
4461
+        arg_cat(&dest, separator, &ndest);
4462
+
4463
+    if (longopts)
4464
+    {
4465
+        const char *c = longopts;
4466
+        while(*c)
4467
+        {
4468
+            size_t ncspn;
4469
+
4470
+            /* add "--" tag prefix */
4471
+            arg_cat(&dest, "--", &ndest);
4472
+
4473
+            /* add comma separated option tag */
4474
+            ncspn = strcspn(c, ",");
4475
+            strncat(dest, c, (ncspn < ndest) ? ncspn : ndest);
4476
+            c += ncspn;
4477
+
4478
+            /* add given separator in place of comma */
4479
+            if (*c == ',')
4480
+            {
4481
+                arg_cat(&dest, separator, &ndest);
4482
+                c++;
4483
+            }
4484
+        }
4485
+    }
4486
+
4487
+    if (datatype)
4488
+    {
4489
+        if (longopts)
4490
+            arg_cat(&dest, "=", &ndest);
4491
+        else if (shortopts)
4492
+            arg_cat(&dest, " ", &ndest);
4493
+
4494
+        if (optvalue)
4495
+        {
4496
+            arg_cat(&dest, "[", &ndest);
4497
+            arg_cat(&dest, datatype, &ndest);
4498
+            arg_cat(&dest, "]", &ndest);
4499
+        }
4500
+        else
4501
+            arg_cat(&dest, datatype, &ndest);
4502
+    }
4503
+}
4504
+
4505
+
4506
+/* this function should be deprecated because it doesnt consider optional argument values (ARG_HASOPTVALUE) */
4507
+void arg_print_option(FILE *fp,
4508
+                      const char *shortopts,
4509
+                      const char *longopts,
4510
+                      const char *datatype,
4511
+                      const char *suffix)
4512
+{
4513
+    char syntax[200] = "";
4514
+    suffix = suffix ? suffix : "";
4515
+
4516
+    /* there is no way of passing the proper optvalue for optional argument values here, so we must ignore it */
4517
+    arg_cat_optionv(syntax,
4518
+                    sizeof(syntax),
4519
+                    shortopts,
4520
+                    longopts,
4521
+                    datatype,
4522
+                    0,
4523
+                    "|");
4524
+
4525
+    fputs(syntax, fp);
4526
+    fputs(suffix, fp);
4527
+}
4528
+
4529
+
4530
+/*
4531
+ * Print a GNU style [OPTION] string in which all short options that
4532
+ * do not take argument values are presented in abbreviated form, as
4533
+ * in: -xvfsd, or -xvf[sd], or [-xvsfd]
4534
+ */
4535
+static
4536
+void arg_print_gnuswitch(FILE *fp, struct arg_hdr * *table)
4537
+{
4538
+    int tabindex;
4539
+    char *format1 = " -%c";
4540
+    char *format2 = " [-%c";
4541
+    char *suffix = "";
4542
+
4543
+    /* print all mandatory switches that are without argument values */
4544
+    for(tabindex = 0;
4545
+        table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR);
4546
+        tabindex++)
4547
+    {
4548
+        /* skip optional options */
4549
+        if (table[tabindex]->mincount < 1)
4550
+            continue;
4551
+
4552
+        /* skip non-short options */
4553
+        if (table[tabindex]->shortopts == NULL)
4554
+            continue;
4555
+
4556
+        /* skip options that take argument values */
4557
+        if (table[tabindex]->flag & ARG_HASVALUE)
4558
+            continue;
4559
+
4560
+        /* print the short option (only the first short option char, ignore multiple choices)*/
4561
+        fprintf(fp, format1, table[tabindex]->shortopts[0]);
4562
+        format1 = "%c";
4563
+        format2 = "[%c";
4564
+    }
4565
+
4566
+    /* print all optional switches that are without argument values */
4567
+    for(tabindex = 0;
4568
+        table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR);
4569
+        tabindex++)
4570
+    {
4571
+        /* skip mandatory args */
4572
+        if (table[tabindex]->mincount > 0)
4573
+            continue;
4574
+
4575
+        /* skip args without short options */
4576
+        if (table[tabindex]->shortopts == NULL)
4577
+            continue;
4578
+
4579
+        /* skip args with values */
4580
+        if (table[tabindex]->flag & ARG_HASVALUE)
4581
+            continue;
4582
+
4583
+        /* print first short option */
4584
+        fprintf(fp, format2, table[tabindex]->shortopts[0]);
4585
+        format2 = "%c";
4586
+        suffix = "]";
4587
+    }
4588
+
4589
+    fprintf(fp, "%s", suffix);
4590
+}
4591
+
4592
+
4593
+void arg_print_syntax(FILE *fp, void * *argtable, const char *suffix)
4594
+{
4595
+    struct arg_hdr * *table = (struct arg_hdr * *)argtable;
4596
+    int i, tabindex;
4597
+
4598
+    /* print GNU style [OPTION] string */
4599
+    arg_print_gnuswitch(fp, table);
4600
+
4601
+    /* print remaining options in abbreviated style */
4602
+    for(tabindex = 0;
4603
+        table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR);
4604
+        tabindex++)
4605
+    {
4606
+        char syntax[200] = "";
4607
+        const char *shortopts, *longopts, *datatype;
4608
+
4609
+        /* skip short options without arg values (they were printed by arg_print_gnu_switch) */
4610
+        if (table[tabindex]->shortopts &&
4611
+            !(table[tabindex]->flag & ARG_HASVALUE))
4612
+            continue;
4613
+
4614
+        shortopts = table[tabindex]->shortopts;
4615
+        longopts  = table[tabindex]->longopts;
4616
+        datatype  = table[tabindex]->datatype;
4617
+        arg_cat_option(syntax,
4618
+                       sizeof(syntax),
4619
+                       shortopts,
4620
+                       longopts,
4621
+                       datatype,
4622
+                       table[tabindex]->flag & ARG_HASOPTVALUE);
4623
+
4624
+        if (strlen(syntax) > 0)
4625
+        {
4626
+            /* print mandatory instances of this option */
4627
+            for (i = 0; i < table[tabindex]->mincount; i++)
4628
+                fprintf(fp, " %s", syntax);
4629
+
4630
+            /* print optional instances enclosed in "[..]" */
4631
+            switch ( table[tabindex]->maxcount - table[tabindex]->mincount )
4632
+            {
4633
+            case 0:
4634
+                break;
4635
+            case 1:
4636
+                fprintf(fp, " [%s]", syntax);
4637
+                break;
4638
+            case 2:
4639
+                fprintf(fp, " [%s] [%s]", syntax, syntax);
4640
+                break;
4641
+            default:
4642
+                fprintf(fp, " [%s]...", syntax);
4643
+                break;
4644
+            }
4645
+        }
4646
+    }
4647
+
4648
+    if (suffix)
4649
+        fprintf(fp, "%s", suffix);
4650
+}
4651
+
4652
+
4653
+void arg_print_syntaxv(FILE *fp, void * *argtable, const char *suffix)
4654
+{
4655
+    struct arg_hdr * *table = (struct arg_hdr * *)argtable;
4656
+    int i, tabindex;
4657
+
4658
+    /* print remaining options in abbreviated style */
4659
+    for(tabindex = 0;
4660
+        table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR);
4661
+        tabindex++)
4662
+    {
4663
+        char syntax[200] = "";
4664
+        const char *shortopts, *longopts, *datatype;
4665
+
4666
+        shortopts = table[tabindex]->shortopts;
4667
+        longopts  = table[tabindex]->longopts;
4668
+        datatype  = table[tabindex]->datatype;
4669
+        arg_cat_optionv(syntax,
4670
+                        sizeof(syntax),
4671
+                        shortopts,
4672
+                        longopts,
4673
+                        datatype,
4674
+                        table[tabindex]->flag & ARG_HASOPTVALUE,
4675
+                        "|");
4676
+
4677
+        /* print mandatory options */
4678
+        for (i = 0; i < table[tabindex]->mincount; i++)
4679
+            fprintf(fp, " %s", syntax);
4680
+
4681
+        /* print optional args enclosed in "[..]" */
4682
+        switch ( table[tabindex]->maxcount - table[tabindex]->mincount )
4683
+        {
4684
+        case 0:
4685
+            break;
4686
+        case 1:
4687
+            fprintf(fp, " [%s]", syntax);
4688
+            break;
4689
+        case 2:
4690
+            fprintf(fp, " [%s] [%s]", syntax, syntax);
4691
+            break;
4692
+        default:
4693
+            fprintf(fp, " [%s]...", syntax);
4694
+            break;
4695
+        }
4696
+    }
4697
+
4698
+    if (suffix)
4699
+        fprintf(fp, "%s", suffix);
4700
+}
4701
+
4702
+
4703
+void arg_print_glossary(FILE *fp, void * *argtable, const char *format)
4704
+{
4705
+    struct arg_hdr * *table = (struct arg_hdr * *)argtable;
4706
+    int tabindex;
4707
+
4708
+    format = format ? format : "  %-20s %s\n";
4709
+    for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++)
4710
+    {
4711
+        if (table[tabindex]->glossary)
4712
+        {
4713
+            char syntax[200] = "";
4714
+            const char *shortopts = table[tabindex]->shortopts;
4715
+            const char *longopts  = table[tabindex]->longopts;
4716
+            const char *datatype  = table[tabindex]->datatype;
4717
+            const char *glossary  = table[tabindex]->glossary;
4718
+            arg_cat_optionv(syntax,
4719
+                            sizeof(syntax),
4720
+                            shortopts,
4721
+                            longopts,
4722
+                            datatype,
4723
+                            table[tabindex]->flag & ARG_HASOPTVALUE,
4724
+                            ", ");
4725
+            fprintf(fp, format, syntax, glossary);
4726
+        }
4727
+    }
4728
+}
4729
+
4730
+
4731
+/**
4732
+ * Print a piece of text formatted, which means in a column with a
4733
+ * left and a right margin. The lines are wrapped at whitspaces next
4734
+ * to right margin. The function does not indent the first line, but
4735
+ * only the following ones.
4736
+ *
4737
+ * Example:
4738
+ * arg_print_formatted( fp, 0, 5, "Some text that doesn't fit." )
4739
+ * will result in the following output:
4740
+ *
4741
+ * Some
4742
+ * text
4743
+ * that
4744
+ * doesn'
4745
+ * t fit.
4746
+ *
4747
+ * Too long lines will be wrapped in the middle of a word.
4748
+ *
4749
+ * arg_print_formatted( fp, 2, 7, "Some text that doesn't fit." )
4750
+ * will result in the following output:
4751
+ *
4752
+ * Some
4753
+ *   text
4754
+ *   that
4755
+ *   doesn'
4756
+ *   t fit.
4757
+ *
4758
+ * As you see, the first line is not indented. This enables output of
4759
+ * lines, which start in a line where output already happened.
4760
+ *
4761
+ * Author: Uli Fouquet
4762
+ */
4763
+static
4764
+void arg_print_formatted( FILE *fp,
4765
+                          const unsigned lmargin,
4766
+                          const unsigned rmargin,
4767
+                          const char *text )
4768
+{
4769
+    const unsigned textlen = (int)strlen( text );
4770
+    unsigned line_start = 0;
4771
+    unsigned line_end = textlen + 1;
4772
+    const unsigned colwidth = (rmargin - lmargin) + 1;
4773
+
4774
+    /* Someone doesn't like us... */
4775
+    if ( line_end < line_start )
4776
+    { fprintf( fp, "%s\n", text ); }
4777
+
4778
+    while (line_end - 1 > line_start )
4779
+    {
4780
+        /* Eat leading whitespaces. This is essential because while
4781
+           wrapping lines, there will often be a whitespace at beginning
4782
+           of line */
4783
+        while ( isspace(*(text + line_start)) )
4784
+        { line_start++; }
4785
+
4786
+        if ((line_end - line_start) > colwidth )
4787
+        { line_end = line_start + colwidth; }
4788
+
4789
+        /* Find last whitespace, that fits into line */
4790
+        while ( ( line_end > line_start )
4791
+                && ( line_end - line_start > colwidth )
4792
+                && !isspace(*(text + line_end)))
4793
+        { line_end--; }
4794
+
4795
+        /* Do not print trailing whitespace. If this text
4796
+           has got only one line, line_end now points to the
4797
+           last char due to initialization. */
4798
+        line_end--;
4799
+
4800
+        /* Output line of text */
4801
+        while ( line_start < line_end )
4802
+        {
4803
+            fputc(*(text + line_start), fp );
4804
+            line_start++;
4805
+        }
4806
+        fputc( '\n', fp );
4807
+
4808
+        /* Initialize another line */
4809
+        if ( line_end + 1 < textlen )
4810
+        {
4811
+            unsigned i;
4812
+
4813
+            for (i = 0; i < lmargin; i++ )
4814
+            { fputc( ' ', fp ); }
4815
+
4816
+            line_end = textlen;
4817
+        }
4818
+
4819
+        /* If we have to print another line, get also the last char. */
4820
+        line_end++;
4821
+
4822
+    } /* lines of text */
4823
+}
4824
+
4825
+/**
4826
+ * Prints the glossary in strict GNU format.
4827
+ * Differences to arg_print_glossary() are:
4828
+ *   - wraps lines after 80 chars
4829
+ *   - indents lines without shortops
4830
+ *   - does not accept formatstrings
4831
+ *
4832
+ * Contributed by Uli Fouquet
4833
+ */
4834
+void arg_print_glossary_gnu(FILE *fp, void * *argtable )
4835
+{
4836
+    struct arg_hdr * *table = (struct arg_hdr * *)argtable;
4837
+    int tabindex;
4838
+
4839
+    for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++)
4840
+    {
4841
+        if (table[tabindex]->glossary)
4842
+        {
4843
+            char syntax[200] = "";
4844
+            const char *shortopts = table[tabindex]->shortopts;
4845
+            const char *longopts  = table[tabindex]->longopts;
4846
+            const char *datatype  = table[tabindex]->datatype;
4847
+            const char *glossary  = table[tabindex]->glossary;
4848
+
4849
+            if ( !shortopts && longopts )
4850
+            {
4851
+                /* Indent trailing line by 4 spaces... */
4852
+                memset( syntax, ' ', 4 );
4853
+                *(syntax + 4) = '\0';
4854
+            }
4855
+
4856
+            arg_cat_optionv(syntax,
4857
+                            sizeof(syntax),
4858
+                            shortopts,
4859
+                            longopts,
4860
+                            datatype,
4861
+                            table[tabindex]->flag & ARG_HASOPTVALUE,
4862
+                            ", ");
4863
+
4864
+            /* If syntax fits not into column, print glossary in new line... */
4865
+            if ( strlen(syntax) > 25 )
4866
+            {
4867
+                fprintf( fp, "  %-25s %s\n", syntax, "" );
4868
+                *syntax = '\0';
4869
+            }
4870
+
4871
+            fprintf( fp, "  %-25s ", syntax );
4872
+            arg_print_formatted( fp, 28, 79, glossary );
4873
+        }
4874
+    } /* for each table entry */
4875
+
4876
+    fputc( '\n', fp );
4877
+}
4878
+
4879
+
4880
+/**
4881
+ * Checks the argtable[] array for NULL entries and returns 1
4882
+ * if any are found, zero otherwise.
4883
+ */
4884
+int arg_nullcheck(void * *argtable)
4885
+{
4886
+    struct arg_hdr * *table = (struct arg_hdr * *)argtable;
4887
+    int tabindex;
4888
+    /*printf("arg_nullcheck(%p)\n",argtable);*/
4889
+
4890
+    if (!table)
4891
+        return 1;
4892
+
4893
+    tabindex = 0;
4894
+    do
4895
+    {
4896
+        /*printf("argtable[%d]=%p\n",tabindex,argtable[tabindex]);*/
4897
+        if (!table[tabindex])
4898
+            return 1;
4899
+    } while(!(table[tabindex++]->flag & ARG_TERMINATOR));
4900
+
4901
+    return 0;
4902
+}
4903
+
4904
+
4905
+/*
4906
+ * arg_free() is deprecated in favour of arg_freetable() due to a flaw in its design.
4907
+ * The flaw results in memory leak in the (very rare) case that an intermediate
4908
+ * entry in the argtable array failed its memory allocation while others following
4909
+ * that entry were still allocated ok. Those subsequent allocations will not be
4910
+ * deallocated by arg_free().
4911
+ * Despite the unlikeliness of the problem occurring, and the even unlikelier event
4912
+ * that it has any deliterious effect, it is fixed regardless by replacing arg_free()
4913
+ * with the newer arg_freetable() function.
4914
+ * We still keep arg_free() for backwards compatibility.
4915
+ */
4916
+void arg_free(void * *argtable)
4917
+{
4918
+    struct arg_hdr * *table = (struct arg_hdr * *)argtable;
4919
+    int tabindex = 0;
4920
+    int flag;
4921
+    /*printf("arg_free(%p)\n",argtable);*/
4922
+    do
4923
+    {
4924
+        /*
4925
+           if we encounter a NULL entry then somewhat incorrectly we presume
4926
+           we have come to the end of the array. It isnt strictly true because
4927
+           an intermediate entry could be NULL with other non-NULL entries to follow.
4928
+           The subsequent argtable entries would then not be freed as they should.
4929
+         */
4930
+        if (table[tabindex] == NULL)
4931
+            break;
4932
+
4933
+        flag = table[tabindex]->flag;
4934
+        free(table[tabindex]);
4935
+        table[tabindex++] = NULL;
4936
+
4937
+    } while(!(flag & ARG_TERMINATOR));
4938
+}
4939
+
4940
+/* frees each non-NULL element of argtable[], where n is the size of the number of entries in the array */
4941
+void arg_freetable(void * *argtable, size_t n)
4942
+{
4943
+    struct arg_hdr * *table = (struct arg_hdr * *)argtable;
4944
+    size_t tabindex = 0;
4945
+    /*printf("arg_freetable(%p)\n",argtable);*/
4946
+    for (tabindex = 0; tabindex < n; tabindex++)
4947
+    {
4948
+        if (table[tabindex] == NULL)
4949
+            continue;
4950
+
4951
+        free(table[tabindex]);
4952
+        table[tabindex] = NULL;
4953
+    };
4954
+}
4955
+
... ...
@@ -0,0 +1,305 @@
1
+/*******************************************************************************
2
+ * This file is part of the argtable3 library.
3
+ *
4
+ * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann
5
+ * <sheitmann@users.sourceforge.net>
6
+ * All rights reserved.
7
+ *
8
+ * Redistribution and use in source and binary forms, with or without
9
+ * modification, are permitted provided that the following conditions are met:
10
+ *     * Redistributions of source code must retain the above copyright
11
+ *       notice, this list of conditions and the following disclaimer.
12
+ *     * Redistributions in binary form must reproduce the above copyright
13
+ *       notice, this list of conditions and the following disclaimer in the
14
+ *       documentation and/or other materials provided with the distribution.
15
+ *     * Neither the name of STEWART HEITMANN nor the  names of its contributors
16
+ *       may be used to endorse or promote products derived from this software
17
+ *       without specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT,
23
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ ******************************************************************************/
30
+
31
+#ifndef ARGTABLE3
32
+#define ARGTABLE3
33
+
34
+#include <stdio.h>      /* FILE */
35
+#include <time.h>       /* struct tm */
36
+
37
+#ifdef __cplusplus
38
+extern "C" {
39
+#endif
40
+
41
+#define ARG_REX_ICASE 1
42
+    
43
+/* bit masks for arg_hdr.flag */
44
+enum
45
+{
46
+    ARG_TERMINATOR=0x1,
47
+    ARG_HASVALUE=0x2,
48
+    ARG_HASOPTVALUE=0x4
49
+};
50
+
51
+typedef void (arg_resetfn)(void *parent);
52
+typedef int  (arg_scanfn)(void *parent, const char *argval);
53
+typedef int  (arg_checkfn)(void *parent);
54
+typedef void (arg_errorfn)(void *parent, FILE *fp, int error, const char *argval, const char *progname);
55
+
56
+
57
+/*
58
+* The arg_hdr struct defines properties that are common to all arg_xxx structs.
59
+* The argtable library requires each arg_xxx struct to have an arg_hdr
60
+* struct as its first data member.
61
+* The argtable library functions then use this data to identify the
62
+* properties of the command line option, such as its option tags,
63
+* datatype string, and glossary strings, and so on.
64
+* Moreover, the arg_hdr struct contains pointers to custom functions that
65
+* are provided by each arg_xxx struct which perform the tasks of parsing
66
+* that particular arg_xxx arguments, performing post-parse checks, and
67
+* reporting errors.
68
+* These functions are private to the individual arg_xxx source code
69
+* and are the pointer to them are initiliased by that arg_xxx struct's
70
+* constructor function. The user could alter them after construction
71
+* if desired, but the original intention is for them to be set by the
72
+* constructor and left unaltered.
73
+*/
74
+struct arg_hdr
75
+{
76
+    char         flag;        /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */
77
+    const char  *shortopts;   /* String defining the short options */
78
+    const char  *longopts;    /* String defiing the long options */
79
+    const char  *datatype;    /* Description of the argument data type */
80
+    const char  *glossary;    /* Description of the option as shown by arg_print_glossary function */
81
+    int          mincount;    /* Minimum number of occurences of this option accepted */
82
+    int          maxcount;    /* Maximum number of occurences if this option accepted */
83
+    void        *parent;      /* Pointer to parent arg_xxx struct */
84
+    arg_resetfn *resetfn;     /* Pointer to parent arg_xxx reset function */
85
+    arg_scanfn  *scanfn;      /* Pointer to parent arg_xxx scan function */
86
+    arg_checkfn *checkfn;     /* Pointer to parent arg_xxx check function */
87
+    arg_errorfn *errorfn;     /* Pointer to parent arg_xxx error function */
88
+    void        *priv;        /* Pointer to private header data for use by arg_xxx functions */
89
+};
90
+
91
+struct arg_rem
92
+{
93
+    struct arg_hdr hdr;      /* The mandatory argtable header struct */
94
+};
95
+
96
+struct arg_lit
97
+{
98
+    struct arg_hdr hdr;      /* The mandatory argtable header struct */
99
+    int count;               /* Number of matching command line args */
100
+};
101
+
102
+struct arg_int
103
+{
104
+    struct arg_hdr hdr;      /* The mandatory argtable header struct */
105
+    int count;               /* Number of matching command line args */
106
+    int *ival;               /* Array of parsed argument values */
107
+};
108
+
109
+struct arg_dbl
110
+{
111
+    struct arg_hdr hdr;      /* The mandatory argtable header struct */
112
+    int count;               /* Number of matching command line args */
113
+    double *dval;            /* Array of parsed argument values */
114
+};
115
+
116
+struct arg_str
117
+{
118
+    struct arg_hdr hdr;      /* The mandatory argtable header struct */
119
+    int count;               /* Number of matching command line args */
120
+    const char **sval;       /* Array of parsed argument values */
121
+};
122
+
123
+struct arg_rex
124
+{
125
+    struct arg_hdr hdr;      /* The mandatory argtable header struct */
126
+    int count;               /* Number of matching command line args */
127
+    const char **sval;       /* Array of parsed argument values */
128
+};
129
+
130
+struct arg_file
131
+{
132
+    struct arg_hdr hdr;      /* The mandatory argtable header struct */
133
+    int count;               /* Number of matching command line args*/
134
+    const char **filename;   /* Array of parsed filenames  (eg: /home/foo.bar) */
135
+    const char **basename;   /* Array of parsed basenames  (eg: foo.bar) */
136
+    const char **extension;  /* Array of parsed extensions (eg: .bar) */
137
+};
138
+
139
+struct arg_date
140
+{
141
+    struct arg_hdr hdr;      /* The mandatory argtable header struct */
142
+    const char *format;      /* strptime format string used to parse the date */
143
+    int count;               /* Number of matching command line args */
144
+    struct tm *tmval;        /* Array of parsed time values */
145
+};
146
+
147
+enum {ARG_ELIMIT=1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG};
148
+struct arg_end
149
+{
150
+    struct arg_hdr hdr;      /* The mandatory argtable header struct */
151
+    int count;               /* Number of errors encountered */
152
+    int *error;              /* Array of error codes */
153
+    void **parent;           /* Array of pointers to offending arg_xxx struct */
154
+    const char **argval;     /* Array of pointers to offending argv[] string */
155
+};
156
+
157
+
158
+/**** arg_xxx constructor functions *********************************/
159
+
160
+struct arg_rem* arg_rem(const char* datatype, const char* glossary);
161
+
162
+struct arg_lit* arg_lit0(const char* shortopts,
163
+    const char* longopts,
164
+    const char* glossary);
165
+struct arg_lit* arg_lit1(const char* shortopts,
166
+    const char* longopts,
167
+    const char *glossary);
168
+struct arg_lit* arg_litn(const char* shortopts,
169
+    const char* longopts,
170
+    int mincount,
171
+    int maxcount,
172
+    const char *glossary);
173
+
174
+struct arg_key* arg_key0(const char* keyword,
175
+    int flags,
176
+    const char* glossary);
177
+struct arg_key* arg_key1(const char* keyword,
178
+    int flags,
179
+    const char* glossary);
180
+struct arg_key* arg_keyn(const char* keyword,
181
+    int flags,
182
+    int mincount,
183
+    int maxcount,
184
+    const char* glossary);
185
+
186
+struct arg_int* arg_int0(const char* shortopts,
187
+    const char* longopts,
188
+    const char* datatype,
189
+    const char* glossary);
190
+struct arg_int* arg_int1(const char* shortopts,
191
+    const char* longopts,
192
+    const char* datatype,
193
+    const char *glossary);
194
+struct arg_int* arg_intn(const char* shortopts,
195
+    const char* longopts,
196
+    const char *datatype,
197
+    int mincount,
198
+    int maxcount,
199
+    const char *glossary);
200
+
201
+struct arg_dbl* arg_dbl0(const char* shortopts,
202
+    const char* longopts,
203
+    const char* datatype,
204
+    const char* glossary);
205
+struct arg_dbl* arg_dbl1(const char* shortopts,
206
+    const char* longopts,
207
+    const char* datatype,
208
+    const char *glossary);
209
+struct arg_dbl* arg_dbln(const char* shortopts,
210
+    const char* longopts,
211
+    const char *datatype,
212
+    int mincount,
213
+    int maxcount,
214
+    const char *glossary);
215
+
216
+struct arg_str* arg_str0(const char* shortopts,
217
+    const char* longopts,
218
+    const char* datatype,
219
+    const char* glossary);
220
+struct arg_str* arg_str1(const char* shortopts,
221
+    const char* longopts,                    
222
+    const char* datatype,
223
+    const char *glossary);
224
+struct arg_str* arg_strn(const char* shortopts,
225
+    const char* longopts,
226
+    const char* datatype,
227
+    int mincount,
228
+    int maxcount,
229
+    const char *glossary);
230
+
231
+struct arg_rex* arg_rex0(const char* shortopts,
232
+    const char* longopts,
233
+    const char* pattern,
234
+    const char* datatype,
235
+    int flags,
236
+    const char* glossary);
237
+struct arg_rex* arg_rex1(const char* shortopts,
238
+    const char* longopts,
239
+    const char* pattern,
240
+    const char* datatype,
241
+    int flags,
242
+    const char *glossary);
243
+struct arg_rex* arg_rexn(const char* shortopts,
244
+    const char* longopts,
245
+    const char* pattern,
246
+    const char* datatype,
247
+    int mincount,
248
+    int maxcount,
249
+    int flags,
250
+    const char *glossary);
251
+
252
+struct arg_file* arg_file0(const char* shortopts,
253
+    const char* longopts,
254
+    const char* datatype,
255
+    const char* glossary);
256
+struct arg_file* arg_file1(const char* shortopts,
257
+    const char* longopts,
258
+    const char* datatype,
259
+    const char *glossary);
260
+struct arg_file* arg_filen(const char* shortopts,
261
+    const char* longopts,
262
+    const char* datatype,
263
+    int mincount,
264
+    int maxcount,
265
+    const char *glossary);
266
+
267
+struct arg_date* arg_date0(const char* shortopts,
268
+    const char* longopts,
269
+    const char* format,
270
+    const char* datatype,
271
+    const char* glossary);
272
+struct arg_date* arg_date1(const char* shortopts,
273
+    const char* longopts,
274
+    const char* format,
275
+    const char* datatype,
276
+    const char *glossary);
277
+struct arg_date* arg_daten(const char* shortopts,
278
+    const char* longopts,
279
+    const char* format,
280
+    const char* datatype,
281
+    int mincount,
282
+    int maxcount,
283
+    const char *glossary);
284
+
285
+struct arg_end* arg_end(int maxerrors);
286
+
287
+
288
+/**** other functions *******************************************/
289
+int arg_nullcheck(void **argtable);
290
+int arg_parse(int argc, char **argv, void **argtable);
291
+void arg_print_option(FILE *fp, const char *shortopts, const char *longopts, const char *datatype, const char *suffix);
292
+void arg_print_syntax(FILE *fp, void **argtable, const char *suffix);
293
+void arg_print_syntaxv(FILE *fp, void **argtable, const char *suffix);
294
+void arg_print_glossary(FILE *fp, void **argtable, const char *format);
295
+void arg_print_glossary_gnu(FILE *fp, void **argtable);
296
+void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname);
297
+void arg_freetable(void **argtable, size_t n);
298
+
299
+/**** deprecated functions, for back-compatibility only ********/
300
+void arg_free(void **argtable);
301
+
302
+#ifdef __cplusplus
303
+}
304
+#endif
305
+#endif
... ...
@@ -0,0 +1 @@
1
+683
... ...
@@ -0,0 +1,4 @@
1
+NR=`cat build.number`
2
+NR=$((NR+1))
3
+echo $NR > build.number
4
+echo $NR
0 5
\ No newline at end of file
... ...
@@ -0,0 +1,674 @@
1
+                    GNU GENERAL PUBLIC LICENSE
2
+                       Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5
+ Everyone is permitted to copy and distribute verbatim copies
6
+ of this license document, but changing it is not allowed.
7
+
8
+                            Preamble
9
+
10
+  The GNU General Public License is a free, copyleft license for
11
+software and other kinds of works.
12
+
13
+  The licenses for most software and other practical works are designed
14
+to take away your freedom to share and change the works.  By contrast,
15
+the GNU General Public License is intended to guarantee your freedom to
16
+share and change all versions of a program--to make sure it remains free
17
+software for all its users.  We, the Free Software Foundation, use the
18
+GNU General Public License for most of our software; it applies also to
19
+any other work released this way by its authors.  You can apply it to
20
+your programs, too.
21
+
22
+  When we speak of free software, we are referring to freedom, not
23
+price.  Our General Public Licenses are designed to make sure that you
24
+have the freedom to distribute copies of free software (and charge for
25
+them if you wish), that you receive source code or can get it if you
26
+want it, that you can change the software or use pieces of it in new
27
+free programs, and that you know you can do these things.
28
+
29
+  To protect your rights, we need to prevent others from denying you
30
+these rights or asking you to surrender the rights.  Therefore, you have
31
+certain responsibilities if you distribute copies of the software, or if
32
+you modify it: responsibilities to respect the freedom of others.
33
+
34
+  For example, if you distribute copies of such a program, whether
35
+gratis or for a fee, you must pass on to the recipients the same
36
+freedoms that you received.  You must make sure that they, too, receive
37
+or can get the source code.  And you must show them these terms so they
38
+know their rights.
39
+
40
+  Developers that use the GNU GPL protect your rights with two steps:
41
+(1) assert copyright on the software, and (2) offer you this License
42
+giving you legal permission to copy, distribute and/or modify it.
43
+
44
+  For the developers' and authors' protection, the GPL clearly explains
45
+that there is no warranty for this free software.  For both users' and
46
+authors' sake, the GPL requires that modified versions be marked as
47
+changed, so that their problems will not be attributed erroneously to
48
+authors of previous versions.
49
+
50
+  Some devices are designed to deny users access to install or run
51
+modified versions of the software inside them, although the manufacturer
52
+can do so.  This is fundamentally incompatible with the aim of
53
+protecting users' freedom to change the software.  The systematic
54
+pattern of such abuse occurs in the area of products for individuals to
55
+use, which is precisely where it is most unacceptable.  Therefore, we
56
+have designed this version of the GPL to prohibit the practice for those
57
+products.  If such problems arise substantially in other domains, we
58
+stand ready to extend this provision to those domains in future versions
59
+of the GPL, as needed to protect the freedom of users.
60
+
61
+  Finally, every program is threatened constantly by software patents.
62
+States should not allow patents to restrict development and use of
63
+software on general-purpose computers, but in those that do, we wish to
64
+avoid the special danger that patents applied to a free program could
65
+make it effectively proprietary.  To prevent this, the GPL assures that
66
+patents cannot be used to render the program non-free.
67
+
68
+  The precise terms and conditions for copying, distribution and
69
+modification follow.
70
+
71
+                       TERMS AND CONDITIONS
72
+
73
+  0. Definitions.
74
+
75
+  "This License" refers to version 3 of the GNU General Public License.
76
+
77
+  "Copyright" also means copyright-like laws that apply to other kinds of
78
+works, such as semiconductor masks.
79
+
80
+  "The Program" refers to any copyrightable work licensed under this
81
+License.  Each licensee is addressed as "you".  "Licensees" and
82
+"recipients" may be individuals or organizations.
83
+
84
+  To "modify" a work means to copy from or adapt all or part of the work
85
+in a fashion requiring copyright permission, other than the making of an
86
+exact copy.  The resulting work is called a "modified version" of the
87
+earlier work or a work "based on" the earlier work.
88
+
89
+  A "covered work" means either the unmodified Program or a work based
90
+on the Program.
91
+
92
+  To "propagate" a work means to do anything with it that, without
93
+permission, would make you directly or secondarily liable for
94
+infringement under applicable copyright law, except executing it on a
95
+computer or modifying a private copy.  Propagation includes copying,
96
+distribution (with or without modification), making available to the
97
+public, and in some countries other activities as well.
98
+
99
+  To "convey" a work means any kind of propagation that enables other
100
+parties to make or receive copies.  Mere interaction with a user through
101
+a computer network, with no transfer of a copy, is not conveying.
102
+
103
+  An interactive user interface displays "Appropriate Legal Notices"
104
+to the extent that it includes a convenient and prominently visible
105
+feature that (1) displays an appropriate copyright notice, and (2)
106
+tells the user that there is no warranty for the work (except to the
107
+extent that warranties are provided), that licensees may convey the
108
+work under this License, and how to view a copy of this License.  If
109
+the interface presents a list of user commands or options, such as a
110
+menu, a prominent item in the list meets this criterion.
111
+
112
+  1. Source Code.
113
+
114
+  The "source code" for a work means the preferred form of the work
115
+for making modifications to it.  "Object code" means any non-source
116
+form of a work.
117
+
118
+  A "Standard Interface" means an interface that either is an official
119
+standard defined by a recognized standards body, or, in the case of
120
+interfaces specified for a particular programming language, one that
121
+is widely used among developers working in that language.
122
+
123
+  The "System Libraries" of an executable work include anything, other
124
+than the work as a whole, that (a) is included in the normal form of
125
+packaging a Major Component, but which is not part of that Major
126
+Component, and (b) serves only to enable use of the work with that
127
+Major Component, or to implement a Standard Interface for which an
128
+implementation is available to the public in source code form.  A
129
+"Major Component", in this context, means a major essential component
130
+(kernel, window system, and so on) of the specific operating system
131
+(if any) on which the executable work runs, or a compiler used to
132
+produce the work, or an object code interpreter used to run it.
133
+
134
+  The "Corresponding Source" for a work in object code form means all
135
+the source code needed to generate, install, and (for an executable
136
+work) run the object code and to modify the work, including scripts to
137
+control those activities.  However, it does not include the work's
138
+System Libraries, or general-purpose tools or generally available free
139
+programs which are used unmodified in performing those activities but
140
+which are not part of the work.  For example, Corresponding Source
141
+includes interface definition files associated with source files for
142
+the work, and the source code for shared libraries and dynamically
143
+linked subprograms that the work is specifically designed to require,
144
+such as by intimate data communication or control flow between those
145
+subprograms and other parts of the work.
146
+
147
+  The Corresponding Source need not include anything that users
148
+can regenerate automatically from other parts of the Corresponding
149
+Source.
150
+
151
+  The Corresponding Source for a work in source code form is that
152
+same work.
153
+
154
+  2. Basic Permissions.
155
+
156
+  All rights granted under this License are granted for the term of
157
+copyright on the Program, and are irrevocable provided the stated
158
+conditions are met.  This License explicitly affirms your unlimited
159
+permission to run the unmodified Program.  The output from running a
160
+covered work is covered by this License only if the output, given its
161
+content, constitutes a covered work.  This License acknowledges your
162
+rights of fair use or other equivalent, as provided by copyright law.
163
+
164
+  You may make, run and propagate covered works that you do not
165
+convey, without conditions so long as your license otherwise remains
166
+in force.  You may convey covered works to others for the sole purpose
167
+of having them make modifications exclusively for you, or provide you
168
+with facilities for running those works, provided that you comply with
169
+the terms of this License in conveying all material for which you do
170
+not control copyright.  Those thus making or running the covered works
171
+for you must do so exclusively on your behalf, under your direction
172
+and control, on terms that prohibit them from making any copies of
173
+your copyrighted material outside their relationship with you.
174
+
175
+  Conveying under any other circumstances is permitted solely under
176
+the conditions stated below.  Sublicensing is not allowed; section 10
177
+makes it unnecessary.
178
+
179
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180
+
181
+  No covered work shall be deemed part of an effective technological
182
+measure under any applicable law fulfilling obligations under article
183
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
184
+similar laws prohibiting or restricting circumvention of such
185
+measures.
186
+
187
+  When you convey a covered work, you waive any legal power to forbid
188
+circumvention of technological measures to the extent such circumvention
189
+is effected by exercising rights under this License with respect to
190
+the covered work, and you disclaim any intention to limit operation or
191
+modification of the work as a means of enforcing, against the work's
192
+users, your or third parties' legal rights to forbid circumvention of
193
+technological measures.
194
+
195
+  4. Conveying Verbatim Copies.
196
+
197
+  You may convey verbatim copies of the Program's source code as you
198
+receive it, in any medium, provided that you conspicuously and
199
+appropriately publish on each copy an appropriate copyright notice;
200
+keep intact all notices stating that this License and any
201
+non-permissive terms added in accord with section 7 apply to the code;
202
+keep intact all notices of the absence of any warranty; and give all
203
+recipients a copy of this License along with the Program.
204
+
205
+  You may charge any price or no price for each copy that you convey,
206
+and you may offer support or warranty protection for a fee.
207
+
208
+  5. Conveying Modified Source Versions.
209
+
210
+  You may convey a work based on the Program, or the modifications to
211
+produce it from the Program, in the form of source code under the
212
+terms of section 4, provided that you also meet all of these conditions:
213
+
214
+    a) The work must carry prominent notices stating that you modified
215
+    it, and giving a relevant date.
216
+
217
+    b) The work must carry prominent notices stating that it is
218
+    released under this License and any conditions added under section
219
+    7.  This requirement modifies the requirement in section 4 to
220
+    "keep intact all notices".
221
+
222
+    c) You must license the entire work, as a whole, under this
223
+    License to anyone who comes into possession of a copy.  This
224
+    License will therefore apply, along with any applicable section 7
225
+    additional terms, to the whole of the work, and all its parts,
226
+    regardless of how they are packaged.  This License gives no
227
+    permission to license the work in any other way, but it does not
228
+    invalidate such permission if you have separately received it.
229
+
230
+    d) If the work has interactive user interfaces, each must display
231
+    Appropriate Legal Notices; however, if the Program has interactive
232
+    interfaces that do not display Appropriate Legal Notices, your
233
+    work need not make them do so.
234
+
235
+  A compilation of a covered work with other separate and independent
236
+works, which are not by their nature extensions of the covered work,
237
+and which are not combined with it such as to form a larger program,
238
+in or on a volume of a storage or distribution medium, is called an
239
+"aggregate" if the compilation and its resulting copyright are not
240
+used to limit the access or legal rights of the compilation's users
241
+beyond what the individual works permit.  Inclusion of a covered work
242
+in an aggregate does not cause this License to apply to the other
243
+parts of the aggregate.
244
+
245
+  6. Conveying Non-Source Forms.
246
+
247
+  You may convey a covered work in object code form under the terms
248
+of sections 4 and 5, provided that you also convey the
249
+machine-readable Corresponding Source under the terms of this License,
250
+in one of these ways:
251
+
252
+    a) Convey the object code in, or embodied in, a physical product
253
+    (including a physical distribution medium), accompanied by the
254
+    Corresponding Source fixed on a durable physical medium
255
+    customarily used for software interchange.
256
+
257
+    b) Convey the object code in, or embodied in, a physical product
258
+    (including a physical distribution medium), accompanied by a
259
+    written offer, valid for at least three years and valid for as
260
+    long as you offer spare parts or customer support for that product
261
+    model, to give anyone who possesses the object code either (1) a
262
+    copy of the Corresponding Source for all the software in the
263
+    product that is covered by this License, on a durable physical
264
+    medium customarily used for software interchange, for a price no
265
+    more than your reasonable cost of physically performing this
266
+    conveying of source, or (2) access to copy the
267
+    Corresponding Source from a network server at no charge.
268
+
269
+    c) Convey individual copies of the object code with a copy of the
270
+    written offer to provide the Corresponding Source.  This
271
+    alternative is allowed only occasionally and noncommercially, and
272
+    only if you received the object code with such an offer, in accord
273
+    with subsection 6b.
274
+
275
+    d) Convey the object code by offering access from a designated
276
+    place (gratis or for a charge), and offer equivalent access to the
277
+    Corresponding Source in the same way through the same place at no
278
+    further charge.  You need not require recipients to copy the
279
+    Corresponding Source along with the object code.  If the place to
280
+    copy the object code is a network server, the Corresponding Source
281
+    may be on a different server (operated by you or a third party)
282
+    that supports equivalent copying facilities, provided you maintain
283
+    clear directions next to the object code saying where to find the
284
+    Corresponding Source.  Regardless of what server hosts the
285
+    Corresponding Source, you remain obligated to ensure that it is
286
+    available for as long as needed to satisfy these requirements.
287
+
288
+    e) Convey the object code using peer-to-peer transmission, provided
289
+    you inform other peers where the object code and Corresponding
290
+    Source of the work are being offered to the general public at no
291
+    charge under subsection 6d.
292
+
293
+  A separable portion of the object code, whose source code is excluded
294
+from the Corresponding Source as a System Library, need not be
295
+included in conveying the object code work.
296
+
297
+  A "User Product" is either (1) a "consumer product", which means any
298
+tangible personal property which is normally used for personal, family,
299
+or household purposes, or (2) anything designed or sold for incorporation
300
+into a dwelling.  In determining whether a product is a consumer product,
301
+doubtful cases shall be resolved in favor of coverage.  For a particular
302
+product received by a particular user, "normally used" refers to a
303
+typical or common use of that class of product, regardless of the status
304
+of the particular user or of the way in which the particular user
305
+actually uses, or expects or is expected to use, the product.  A product
306
+is a consumer product regardless of whether the product has substantial
307
+commercial, industrial or non-consumer uses, unless such uses represent
308
+the only significant mode of use of the product.
309
+
310
+  "Installation Information" for a User Product means any methods,
311
+procedures, authorization keys, or other information required to install
312
+and execute modified versions of a covered work in that User Product from
313
+a modified version of its Corresponding Source.  The information must
314
+suffice to ensure that the continued functioning of the modified object
315
+code is in no case prevented or interfered with solely because
316
+modification has been made.
317
+
318
+  If you convey an object code work under this section in, or with, or
319
+specifically for use in, a User Product, and the conveying occurs as
320
+part of a transaction in which the right of possession and use of the
321
+User Product is transferred to the recipient in perpetuity or for a
322
+fixed term (regardless of how the transaction is characterized), the
323
+Corresponding Source conveyed under this section must be accompanied
324
+by the Installation Information.  But this requirement does not apply
325
+if neither you nor any third party retains the ability to install
326
+modified object code on the User Product (for example, the work has
327
+been installed in ROM).
328
+
329
+  The requirement to provide Installation Information does not include a
330
+requirement to continue to provide support service, warranty, or updates
331
+for a work that has been modified or installed by the recipient, or for
332
+the User Product in which it has been modified or installed.  Access to a
333
+network may be denied when the modification itself materially and
334
+adversely affects the operation of the network or violates the rules and
335
+protocols for communication across the network.
336
+
337
+  Corresponding Source conveyed, and Installation Information provided,
338
+in accord with this section must be in a format that is publicly
339
+documented (and with an implementation available to the public in
340
+source code form), and must require no special password or key for
341
+unpacking, reading or copying.
342
+
343
+  7. Additional Terms.
344
+
345
+  "Additional permissions" are terms that supplement the terms of this
346
+License by making exceptions from one or more of its conditions.
347
+Additional permissions that are applicable to the entire Program shall
348
+be treated as though they were included in this License, to the extent
349
+that they are valid under applicable law.  If additional permissions
350
+apply only to part of the Program, that part may be used separately
351
+under those permissions, but the entire Program remains governed by
352
+this License without regard to the additional permissions.
353
+
354
+  When you convey a copy of a covered work, you may at your option
355
+remove any additional permissions from that copy, or from any part of
356
+it.  (Additional permissions may be written to require their own
357
+removal in certain cases when you modify the work.)  You may place
358
+additional permissions on material, added by you to a covered work,
359
+for which you have or can give appropriate copyright permission.
360
+
361
+  Notwithstanding any other provision of this License, for material you
362
+add to a covered work, you may (if authorized by the copyright holders of
363
+that material) supplement the terms of this License with terms:
364
+
365
+    a) Disclaiming warranty or limiting liability differently from the
366
+    terms of sections 15 and 16 of this License; or
367
+
368
+    b) Requiring preservation of specified reasonable legal notices or
369
+    author attributions in that material or in the Appropriate Legal
370
+    Notices displayed by works containing it; or
371
+
372
+    c) Prohibiting misrepresentation of the origin of that material, or
373
+    requiring that modified versions of such material be marked in
374
+    reasonable ways as different from the original version; or
375
+
376
+    d) Limiting the use for publicity purposes of names of licensors or
377
+    authors of the material; or
378
+
379
+    e) Declining to grant rights under trademark law for use of some
380
+    trade names, trademarks, or service marks; or
381
+
382
+    f) Requiring indemnification of licensors and authors of that
383
+    material by anyone who conveys the material (or modified versions of
384
+    it) with contractual assumptions of liability to the recipient, for
385
+    any liability that these contractual assumptions directly impose on
386
+    those licensors and authors.
387
+
388
+  All other non-permissive additional terms are considered "further
389
+restrictions" within the meaning of section 10.  If the Program as you
390
+received it, or any part of it, contains a notice stating that it is
391
+governed by this License along with a term that is a further
392
+restriction, you may remove that term.  If a license document contains
393
+a further restriction but permits relicensing or conveying under this
394
+License, you may add to a covered work material governed by the terms
395
+of that license document, provided that the further restriction does
396
+not survive such relicensing or conveying.
397
+
398
+  If you add terms to a covered work in accord with this section, you
399
+must place, in the relevant source files, a statement of the
400
+additional terms that apply to those files, or a notice indicating
401
+where to find the applicable terms.
402
+
403
+  Additional terms, permissive or non-permissive, may be stated in the
404
+form of a separately written license, or stated as exceptions;
405
+the above requirements apply either way.
406
+
407
+  8. Termination.
408
+
409
+  You may not propagate or modify a covered work except as expressly
410
+provided under this License.  Any attempt otherwise to propagate or
411
+modify it is void, and will automatically terminate your rights under
412
+this License (including any patent licenses granted under the third
413
+paragraph of section 11).
414
+
415
+  However, if you cease all violation of this License, then your
416
+license from a particular copyright holder is reinstated (a)
417
+provisionally, unless and until the copyright holder explicitly and
418
+finally terminates your license, and (b) permanently, if the copyright
419
+holder fails to notify you of the violation by some reasonable means
420
+prior to 60 days after the cessation.
421
+
422
+  Moreover, your license from a particular copyright holder is
423
+reinstated permanently if the copyright holder notifies you of the
424
+violation by some reasonable means, this is the first time you have
425
+received notice of violation of this License (for any work) from that
426
+copyright holder, and you cure the violation prior to 30 days after
427
+your receipt of the notice.
428
+
429
+  Termination of your rights under this section does not terminate the
430
+licenses of parties who have received copies or rights from you under
431
+this License.  If your rights have been terminated and not permanently
432
+reinstated, you do not qualify to receive new licenses for the same
433
+material under section 10.
434
+
435
+  9. Acceptance Not Required for Having Copies.
436
+
437
+  You are not required to accept this License in order to receive or
438
+run a copy of the Program.  Ancillary propagation of a covered work
439
+occurring solely as a consequence of using peer-to-peer transmission
440
+to receive a copy likewise does not require acceptance.  However,
441
+nothing other than this License grants you permission to propagate or
442
+modify any covered work.  These actions infringe copyright if you do
443
+not accept this License.  Therefore, by modifying or propagating a
444
+covered work, you indicate your acceptance of this License to do so.
445
+
446
+  10. Automatic Licensing of Downstream Recipients.
447
+
448
+  Each time you convey a covered work, the recipient automatically
449
+receives a license from the original licensors, to run, modify and
450
+propagate that work, subject to this License.  You are not responsible
451
+for enforcing compliance by third parties with this License.
452
+
453
+  An "entity transaction" is a transaction transferring control of an
454
+organization, or substantially all assets of one, or subdividing an
455
+organization, or merging organizations.  If propagation of a covered
456
+work results from an entity transaction, each party to that
457
+transaction who receives a copy of the work also receives whatever
458
+licenses to the work the party's predecessor in interest had or could
459
+give under the previous paragraph, plus a right to possession of the
460
+Corresponding Source of the work from the predecessor in interest, if
461
+the predecessor has it or can get it with reasonable efforts.
462
+
463
+  You may not impose any further restrictions on the exercise of the
464
+rights granted or affirmed under this License.  For example, you may
465
+not impose a license fee, royalty, or other charge for exercise of
466
+rights granted under this License, and you may not initiate litigation
467
+(including a cross-claim or counterclaim in a lawsuit) alleging that
468
+any patent claim is infringed by making, using, selling, offering for
469
+sale, or importing the Program or any portion of it.
470
+
471
+  11. Patents.
472
+
473
+  A "contributor" is a copyright holder who authorizes use under this
474
+License of the Program or a work on which the Program is based.  The
475
+work thus licensed is called the contributor's "contributor version".
476
+
477
+  A contributor's "essential patent claims" are all patent claims
478
+owned or controlled by the contributor, whether already acquired or
479
+hereafter acquired, that would be infringed by some manner, permitted
480
+by this License, of making, using, or selling its contributor version,
481
+but do not include claims that would be infringed only as a
482
+consequence of further modification of the contributor version.  For
483
+purposes of this definition, "control" includes the right to grant
484
+patent sublicenses in a manner consistent with the requirements of
485
+this License.
486
+
487
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
488
+patent license under the contributor's essential patent claims, to
489
+make, use, sell, offer for sale, import and otherwise run, modify and
490
+propagate the contents of its contributor version.
491
+
492
+  In the following three paragraphs, a "patent license" is any express
493
+agreement or commitment, however denominated, not to enforce a patent
494
+(such as an express permission to practice a patent or covenant not to
495
+sue for patent infringement).  To "grant" such a patent license to a
496
+party means to make such an agreement or commitment not to enforce a
497
+patent against the party.
498
+
499
+  If you convey a covered work, knowingly relying on a patent license,
500
+and the Corresponding Source of the work is not available for anyone
501
+to copy, free of charge and under the terms of this License, through a
502
+publicly available network server or other readily accessible means,
503
+then you must either (1) cause the Corresponding Source to be so
504
+available, or (2) arrange to deprive yourself of the benefit of the
505
+patent license for this particular work, or (3) arrange, in a manner
506
+consistent with the requirements of this License, to extend the patent
507
+license to downstream recipients.  "Knowingly relying" means you have
508
+actual knowledge that, but for the patent license, your conveying the
509
+covered work in a country, or your recipient's use of the covered work
510
+in a country, would infringe one or more identifiable patents in that
511
+country that you have reason to believe are valid.
512
+
513
+  If, pursuant to or in connection with a single transaction or
514
+arrangement, you convey, or propagate by procuring conveyance of, a
515
+covered work, and grant a patent license to some of the parties
516
+receiving the covered work authorizing them to use, propagate, modify
517
+or convey a specific copy of the covered work, then the patent license
518
+you grant is automatically extended to all recipients of the covered
519
+work and works based on it.
520
+
521
+  A patent license is "discriminatory" if it does not include within
522
+the scope of its coverage, prohibits the exercise of, or is
523
+conditioned on the non-exercise of one or more of the rights that are
524
+specifically granted under this License.  You may not convey a covered
525
+work if you are a party to an arrangement with a third party that is
526
+in the business of distributing software, under which you make payment
527
+to the third party based on the extent of your activity of conveying
528
+the work, and under which the third party grants, to any of the
529
+parties who would receive the covered work from you, a discriminatory
530
+patent license (a) in connection with copies of the covered work
531
+conveyed by you (or copies made from those copies), or (b) primarily
532
+for and in connection with specific products or compilations that
533
+contain the covered work, unless you entered into that arrangement,
534
+or that patent license was granted, prior to 28 March 2007.
535
+
536
+  Nothing in this License shall be construed as excluding or limiting
537
+any implied license or other defenses to infringement that may
538
+otherwise be available to you under applicable patent law.
539
+
540
+  12. No Surrender of Others' Freedom.
541
+
542
+  If conditions are imposed on you (whether by court order, agreement or
543
+otherwise) that contradict the conditions of this License, they do not
544
+excuse you from the conditions of this License.  If you cannot convey a
545
+covered work so as to satisfy simultaneously your obligations under this
546
+License and any other pertinent obligations, then as a consequence you may
547
+not convey it at all.  For example, if you agree to terms that obligate you
548
+to collect a royalty for further conveying from those to whom you convey
549
+the Program, the only way you could satisfy both those terms and this
550
+License would be to refrain entirely from conveying the Program.
551
+
552
+  13. Use with the GNU Affero General Public License.
553
+
554
+  Notwithstanding any other provision of this License, you have
555
+permission to link or combine any covered work with a work licensed
556
+under version 3 of the GNU Affero General Public License into a single
557
+combined work, and to convey the resulting work.  The terms of this
558
+License will continue to apply to the part which is the covered work,
559
+but the special requirements of the GNU Affero General Public License,
560
+section 13, concerning interaction through a network will apply to the
561
+combination as such.
562
+
563
+  14. Revised Versions of this License.
564
+
565
+  The Free Software Foundation may publish revised and/or new versions of
566
+the GNU General Public License from time to time.  Such new versions will
567
+be similar in spirit to the present version, but may differ in detail to
568
+address new problems or concerns.
569
+
570
+  Each version is given a distinguishing version number.  If the
571
+Program specifies that a certain numbered version of the GNU General
572
+Public License "or any later version" applies to it, you have the
573
+option of following the terms and conditions either of that numbered
574
+version or of any later version published by the Free Software
575
+Foundation.  If the Program does not specify a version number of the
576
+GNU General Public License, you may choose any version ever published
577
+by the Free Software Foundation.
578
+
579
+  If the Program specifies that a proxy can decide which future
580
+versions of the GNU General Public License can be used, that proxy's
581
+public statement of acceptance of a version permanently authorizes you
582
+to choose that version for the Program.
583
+
584
+  Later license versions may give you additional or different
585
+permissions.  However, no additional obligations are imposed on any
586
+author or copyright holder as a result of your choosing to follow a
587
+later version.
588
+
589
+  15. Disclaimer of Warranty.
590
+
591
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599
+
600
+  16. Limitation of Liability.
601
+
602
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610
+SUCH DAMAGES.
611
+
612
+  17. Interpretation of Sections 15 and 16.
613
+
614
+  If the disclaimer of warranty and limitation of liability provided
615
+above cannot be given local legal effect according to their terms,
616
+reviewing courts shall apply local law that most closely approximates
617
+an absolute waiver of all civil liability in connection with the
618
+Program, unless a warranty or assumption of liability accompanies a
619
+copy of the Program in return for a fee.
620
+
621
+                     END OF TERMS AND CONDITIONS
622
+
623
+            How to Apply These Terms to Your New Programs
624
+
625
+  If you develop a new program, and you want it to be of the greatest
626
+possible use to the public, the best way to achieve this is to make it
627
+free software which everyone can redistribute and change under these terms.
628
+
629
+  To do so, attach the following notices to the program.  It is safest
630
+to attach them to the start of each source file to most effectively
631
+state the exclusion of warranty; and each file should have at least
632
+the "copyright" line and a pointer to where the full notice is found.
633
+
634
+    <one line to give the program's name and a brief idea of what it does.>
635
+    Copyright (C) <year>  <name of author>
636
+
637
+    This program is free software: you can redistribute it and/or modify
638
+    it under the terms of the GNU General Public License as published by
639
+    the Free Software Foundation, either version 3 of the License, or
640
+    (at your option) any later version.
641
+
642
+    This program is distributed in the hope that it will be useful,
643
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
644
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
645
+    GNU General Public License for more details.
646
+
647
+    You should have received a copy of the GNU General Public License
648
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
649
+
650
+Also add information on how to contact you by electronic and paper mail.
651
+
652
+  If the program does terminal interaction, make it output a short
653
+notice like this when it starts in an interactive mode:
654
+
655
+    <program>  Copyright (C) <year>  <name of author>
656
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657
+    This is free software, and you are welcome to redistribute it
658
+    under certain conditions; type `show c' for details.
659
+
660
+The hypothetical commands `show w' and `show c' should show the appropriate
661
+parts of the General Public License.  Of course, your program's commands
662
+might be different; for a GUI interface, you would use an "about box".
663
+
664
+  You should also get your employer (if you work as a programmer) or school,
665
+if any, to sign a "copyright disclaimer" for the program, if necessary.
666
+For more information on this, and how to apply and follow the GNU GPL, see
667
+<http://www.gnu.org/licenses/>.
668
+
669
+  The GNU General Public License does not permit incorporating your program
670
+into proprietary programs.  If your program is a subroutine library, you
671
+may consider it more useful to permit linking proprietary applications with
672
+the library.  If this is what you want to do, use the GNU Lesser General
673
+Public License instead of this License.  But first, please read
674
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
... ...
@@ -0,0 +1,100 @@
1
+#ifndef LIBTCC_H
2
+#define LIBTCC_H
3
+
4
+#ifndef LIBTCCAPI
5
+# define LIBTCCAPI
6
+#endif
7
+
8
+#ifdef __cplusplus
9
+extern "C" {
10
+#endif
11
+
12
+struct TCCState;
13
+
14
+typedef struct TCCState TCCState;
15
+
16
+/* create a new TCC compilation context */
17
+LIBTCCAPI TCCState *tcc_new(void);
18
+
19
+/* free a TCC compilation context */
20
+LIBTCCAPI void tcc_delete(TCCState *s);
21
+
22
+/* set CONFIG_TCCDIR at runtime */
23
+LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
24
+
25
+/* set error/warning display callback */
26
+LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque,
27
+    void (*error_func)(void *opaque, const char *msg));
28
+
29
+/* set options as from command line (multiple supported) */
30
+LIBTCCAPI void tcc_set_options(TCCState *s, const char *str);
31
+
32
+/*****************************/
33
+/* preprocessor */
34
+
35
+/* add include path */
36
+LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
37
+
38
+/* add in system include path */
39
+LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
40
+
41
+/* define preprocessor symbol 'sym'. Can put optional value */
42
+LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
43
+
44
+/* undefine preprocess symbol 'sym' */
45
+LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
46
+
47
+/*****************************/
48
+/* compiling */
49
+
50
+/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
51
+LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
52
+
53
+/* compile a string containing a C source. Return -1 if error. */
54
+LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
55
+
56
+/*****************************/
57
+/* linking commands */
58
+
59
+/* set output type. MUST BE CALLED before any compilation */
60
+LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
61
+#define TCC_OUTPUT_MEMORY   1 /* output will be run in memory (default) */
62
+#define TCC_OUTPUT_EXE      2 /* executable file */
63
+#define TCC_OUTPUT_DLL      3 /* dynamic library */
64
+#define TCC_OUTPUT_OBJ      4 /* object file */
65
+#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess (used internally) */
66
+
67
+/* equivalent to -Lpath option */
68
+LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
69
+
70
+/* the library name is the same as the argument of the '-l' option */
71
+LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
72
+
73
+/* add a symbol to the compiled program */
74
+LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);
75
+
76
+/* output an executable, library or object file. DO NOT call
77
+   tcc_relocate() before. */
78
+LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
79
+
80
+/* link and run main() function and return its value. DO NOT call
81
+   tcc_relocate() before. */
82
+LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
83
+
84
+/* do all relocations (needed before using tcc_get_symbol()) */
85
+LIBTCCAPI int tcc_relocate(TCCState *s1, void *ptr);
86
+/* possible values for 'ptr':
87
+   - TCC_RELOCATE_AUTO : Allocate and manage memory internally
88
+   - NULL              : return required memory size for the step below
89
+   - memory address    : copy code to memory passed by the caller
90
+   returns -1 if error. */
91
+#define TCC_RELOCATE_AUTO (void*)1
92
+
93
+/* return symbol value or NULL if not found */
94
+LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
95
+
96
+#ifdef __cplusplus
97
+}
98
+#endif
99
+
100
+#endif
... ...
@@ -0,0 +1,1068 @@
1
+#include <stdio.h>
2
+#include <string.h>
3
+#include <stdlib.h>
4
+#include <float.h>
5
+#include <omp.h>
6
+#include <gdal.h>
7
+#include <ogr_srs_api.h>
8
+
9
+#include "argtable3.h"
10
+#include "libtcc.h"
11
+
12
+#define MAX_INPUTS 256
13
+#define MAX_OUTPUTS 64
14
+
15
+char libtcc_path[10000] = "";
16
+
17
+typedef int (*exec_type)(int,int,int,int,int,int,int,double*,double*, double*,double*);
18
+typedef int (*begin_end_exec_type)(int,int,int,double*,double*);
19
+
20
+/*
21
+int fff(int COLS, int ROWS, int COL, int ROW, int INPNUM, int OUTNUM, int MEMNUM, double *IN, double *OUT, double *MEM, double* GEOTRANS) {
22
+  int i;
23
+  double v=0.0;
24
+  for(i=0; i<10; i++) v+=sin(i);
25
+  return 0;
26
+}
27
+*/
28
+typedef struct {
29
+  GDALDatasetH dataset_h;
30
+  GDALRasterBandH band_h;
31
+  int is_no_data;
32
+  double no_data;
33
+  double *buffer;
34
+  double *iobuffer;
35
+} layer;
36
+
37
+const char *opts_compress_none[] = { "TILED=NO", "BIGTIFF=YES", NULL};
38
+const char *opts_compress_deflate[] = { "TILED=NO", "BIGTIFF=YES", "COMPRESS=DEFLATE", NULL};
39
+const char *opts_compress_deflate2[] = { "TILED=NO", "BIGTIFF=YES", "COMPRESS=DEFLATE", "PREDICTOR=2", NULL};
40
+const char *opts_compress_deflate3[] = { "TILED=NO", "BIGTIFF=YES", "COMPRESS=DEFLATE", "PREDICTOR=3", NULL};
41
+const char *opts_compress_lzw[] = { "TILED=NO", "BIGTIFF=YES", "COMPRESS=LZW", NULL};
42
+const char *opts_compress_lzw2[] = { "TILED=NO", "BIGTIFF=YES", "COMPRESS=LZW", "PREDICTOR=2", NULL };
43
+const char *opts_compress_lzw3[] = { "TILED=NO", "BIGTIFF=YES", "COMPRESS=LZW", "PREDICTOR=3", NULL };
44
+const char *default_type = "Float64";
45
+
46
+layer *input_layers;
47
+layer *output_layers;
48
+
49
+int fl_quiet = 0;
50
+int ninputs = 0;
51
+int noutputs = 0;
52
+int cols = 0;
53
+int rows = 0;
54
+
55
+int file_exists(const char *fname) {
56
+  FILE *f = fopen(fname,"r");
57
+  if(f) {
58
+    fclose(f);
59
+    return 1;
60
+  }
61
+  return 0;
62
+}
63
+
64
+void show_progress(int col, int cols) {
65
+  if(fl_quiet) return;
66
+  static int p = -1;
67
+  int n = (int)(100.0*col/cols);
68
+  if(p!=n) {
69
+    p=n;
70
+    fprintf(stderr,"\b\b\b\b%3d%%",p); fflush(stderr);
71
+    if(p==100) fprintf(stderr,"\n");
72
+  }
73
+}
74
+
75
+void show_message(FILE *f,char *message) {
76
+  if(fl_quiet) return;
77
+  fprintf(f,"%s\n",message);
78
+  fflush(f);
79
+}
80
+
81
+void show_help(char *prog_name, void **argtable) {
82
+  if(fl_quiet) return;
83
+
84
+  fprintf(stdout,"\nusage:\n\n%s",prog_name);
85
+  arg_print_syntax(stdout, argtable, "\n");
86
+  fprintf(stdout,"\n");
87
+  arg_print_glossary_gnu(stdout, argtable);
88
+  fprintf(stdout,"\n");
89
+  fprintf(stdout,"   A user has to define -e or -p option!\n\n");
90
+  fprintf(stdout,"\n");
91
+  fprintf(stdout,"   plMapcalc version: %s\n\n", VERSION);
92
+  fflush(stdout);
93
+}
94
+
95
+int set_num_threads(struct arg_int *th) {
96
+  int i = 1;
97
+  if(th->count>0)
98
+    i = th->ival[0];
99
+  omp_set_num_threads(i);
100
+  return i;
101
+}
102
+
103
+int is_bbox_ok(layer *inputs, int ninputs) {
104
+  double eps = 0.00000000001;
105
+  double geo_transform[2][6];
106
+  int i,j;
107
+  
108
+  if(ninputs<2) return 1;
109
+  GDALGetGeoTransform(inputs[0].dataset_h,geo_transform[0]);
110
+  for(i=1; i<ninputs; i++) {
111
+	GDALGetGeoTransform(inputs[i].dataset_h,geo_transform[1]);
112
+	for(j=0; j<6; j++)
113
+	  if(fabs(geo_transform[0][j]-geo_transform[1][j])>eps)
114
+	    return 0;
115
+  }
116
+  return 1;
117
+}
118
+
119
+int is_pojection_ok(layer *inputs, int ninputs) {
120
+  if(ninputs<2) return TRUE;
121
+
122
+  int i = 1;
123
+  int proj_ok = TRUE;
124
+  char *p = (char *)GDALGetProjectionRef(inputs[0].dataset_h);
125
+//  printf("\nProjection: %s\n\n",p);
126
+  char *p1;
127
+  OGRSpatialReferenceH ref = OSRNewSpatialReference(p);
128
+  int proj = OSRIsProjected(ref);
129
+  OGRSpatialReferenceH ref1;
130
+  
131
+  while(proj_ok && i<ninputs) {
132
+	p1 = (char *)GDALGetProjectionRef(inputs[i].dataset_h);
133
+	ref1 = OSRNewSpatialReference(p1);   
134
+    if(proj) {
135
+      if(!OSRIsSame(ref,ref1))
136
+        proj_ok = FALSE;
137
+    } else {
138
+      if(!OSRIsSameGeogCS(ref,ref1))
139
+        proj_ok = FALSE;
140
+    }
141
+    OSRDestroySpatialReference(ref1);
142
+    i++;
143
+  }
144
+  
145
+  OSRDestroySpatialReference(ref);
146
+  return proj_ok;
147
+}
148
+
149
+char ** str_tokens(char *s, char sep) {
150
+  int i, n=0;
151
+  char *p;
152
+
153
+  char **tab = (char **)calloc(11, sizeof(char *));
154
+
155
+  for(i=0; i<11; i++) tab[i] = NULL;
156
+
157
+  n = 0;
158
+  p = s;
159
+  p++; // skip two starting characters. In windows, skipping drive letter and colon.
160
+  p++;
161
+  do {
162
+    if(*p==sep) {
163
+      *p = '\0';
164
+      tab[n++] = p;
165
+      if(n>10) {
166
+        show_message(stderr, "Too many options per file!");
167
+        exit(1);
168
+      }
169
+    }
170
+    p++;
171
+  }  while(*p!='\0');
172
+  tab[n++] = p;
173
+
174
+
175
+  tab[0] = s;
176
+  for(i=1; i<n; i++) {
177
+    p=tab[i];
178
+    p--;
179
+    while(*p!='\0') 
180
+      tab[i]=p--;
181
+  }
182
+  return tab;
183
+}
184
+
185
+char *get_file_name(const char *data) {
186
+	int l = (int)strlen(data)+2;
187
+	char *s = (char *)malloc(l);
188
+	strcpy(s,data);
189
+	char **toks = str_tokens(s,':');
190
+    char *tok = toks[0];
191
+
192
+	char *result = NULL;
193
+	if(tok!=NULL && *tok!='\0') {
194
+	  l=(int)strlen(tok)+2;
195
+	  result = (char *)malloc(l);
196
+	  strcpy(result,tok);
197
+	}
198
+	free(s);
199
+    free(toks);
200
+	return result;
201
+}
202
+
203
+char *get_type_name(const char *data) {
204
+	char *def = (char *)default_type;
205
+	int l = (int)strlen(data)+2;
206
+	char *s = (char *)malloc(l);
207
+	char *result = NULL;
208
+
209
+	strcpy(s, data);
210
+	char **toks = str_tokens(s,':');
211
+    char *tok = toks[1];
212
+
213
+	if(tok!=NULL && strlen(tok)>0) {
214
+	  l=(int)strlen(tok)+2;
215
+	  result = (char *)malloc(l);
216
+	  strcpy(result,tok);
217
+	} else {
218
+	  l=(int)strlen(def)+2;
219
+	  result = (char *)malloc(l);
220
+	  strcpy(result,def);
221
+    }
222
+	free(s);
223
+    free(toks);
224
+	return result;
225
+}
226
+
227
+double get_nodata_value(const char *data) {
228
+	int l = (int)strlen(data)+2;
229
+	char *s = (char *)malloc(l);
230
+	strcpy(s,data);
231
+	char **toks = str_tokens(s,':');
232
+    char *tok = toks[2];
233
+
234
+	double result = 0.0;
235
+	if(tok!=NULL)
236
+	  result = atof(tok);
237
+	free(s);
238
+    free(toks);
239
+	return result;
240
+}
241
+
242
+int get_isnodata_value(const char *data) {
243
+	int l = (int)strlen(data)+2;
244
+	char *s = (char *)malloc(l);
245
+	strcpy(s,data);
246
+	char **toks = str_tokens(s,':');
247
+    char *tok = toks[2];
248
+	int result = (tok!=NULL && *tok!='\0');
249
+	free(s);
250
+    free(toks);
251
+	return result;
252
+}
253
+
254
+char *get_compression_name(const char *data) {
255
+	int l = (int)strlen(data)+2;
256
+	char *s = (char *)malloc(l);
257
+	strcpy(s,data);
258
+	char **toks = str_tokens(s,':');
259
+    char *tok = toks[3];
260
+	char *result = NULL;
261
+
262
+	if(tok!=NULL && strlen(tok)>0) {
263
+	  l=(int)strlen(tok)+2;
264
+	  result = (char *)malloc(l);
265
+	  strcpy(result,tok);
266
+	}
267
+	free(s);
268
+    free(toks);
269
+	return result;
270
+}
271
+
272
+char **get_compression_opts(const char *data) {
273
+	int l = (int)strlen(data)+2;
274
+	char *s = (char *)malloc(l);
275
+	strcpy(s,data);
276
+	char **toks = str_tokens(s,':');
277
+    char *tok = toks[3];
278
+	char **result = NULL;
279
+    if(tok!=NULL && *tok!='\0') {
280
+      if(strcmp(tok,"DEFLATE")==0)
281
+        result = (char **)opts_compress_deflate;
282
+      else if(strcmp(tok,"LZW")==0)
283
+        result = (char **)opts_compress_lzw;
284
+      else if(strcmp(tok,"DEFLATE2")==0)
285
+        result = (char **)opts_compress_deflate2;
286
+      else if(strcmp(tok,"LZW2")==0)
287
+        result = (char **)opts_compress_lzw2;
288
+      else if(strcmp(tok,"DEFLATE3")==0)
289
+        result = (char **)opts_compress_deflate3;
290
+      else if(strcmp(tok,"LZW3")==0)
291
+        result = (char **)opts_compress_lzw3;
292
+      else
293
+        result = (char **)opts_compress_none;
294
+    }
295
+	free(s);
296
+    free(toks);
297
+	return result;
298
+}
299
+
300
+int get_band_number(const char *data) {
301
+	int l = (int)strlen(data)+2;
302
+	char *s = (char *)malloc(l);
303
+	strcpy(s,data);
304
+	char **toks = str_tokens(s,':');
305
+    char *tok = toks[1];
306
+	int result = 1;
307
+    if(tok!=NULL && *tok!='\0') 
308
+      result = atoi(tok);
309
+	free(s);
310
+    free(toks);
311
+    if(result==0) result = 1;
312
+	return result;
313
+}
314
+
315
+
316
+layer *open_inputs(struct arg_str *input) {
317
+  int i;
318
+  int n = input->count;
319
+  char *fname; 
320
+  int band = 1;
321
+  layer *layers = NULL;
322
+  
323
+  if(n>=MAX_INPUTS) {
324
+	show_message(stderr,"Too many input files!!");
325
+	exit(1);
326
+  }
327
+
328
+  if(n!=0) {
329
+    for(i=0; i<n; i++) {
330
+      fname = get_file_name(input->sval[i]);
331
+
332
+      if(!file_exists(fname)) {
333
+        show_message(stderr,"Input file does not exist!");
334
+        exit(1);
335
+      }
336
+    }
337
+    layers = (layer *)calloc(n,sizeof(layer));
338
+    for(i=0; i<n; i++) {
339
+
340
+      fname = get_file_name(input->sval[i]);
341
+      band = get_band_number(input->sval[i]);
342
+
343
+      layers[i].dataset_h = GDALOpenShared(fname,GA_ReadOnly);
344
+      if(!(layers[i].dataset_h)) {
345
+        show_message(stderr,"Problem with open input file!!");
346
+        exit(1);
347
+      }
348
+      layers[i].band_h = GDALGetRasterBand(layers[i].dataset_h,band);
349
+      if(!(layers[i].band_h)) {
350
+        show_message(stderr,"Problem with open band from input file!!");
351
+        exit(1);
352
+      }
353
+
354
+      if(cols==0) {
355
+        cols = GDALGetRasterBandXSize(layers[i].band_h);
356
+        rows = GDALGetRasterBandYSize(layers[i].band_h);
357
+      }
358
+
359
+      layers[i].no_data = GDALGetRasterNoDataValue(layers[i].band_h, &(layers[i].is_no_data));
360
+      layers[i].buffer = (double *)malloc(cols*sizeof(double));
361
+      layers[i].iobuffer = (double *)malloc(cols*sizeof(double));
362
+
363
+      fprintf(stderr,"Input layer %s, band: %d", fname, band);
364
+      if(layers[i].is_no_data==1)
365
+        fprintf(stderr,", no_data: %lf",layers[i].no_data);
366
+      fprintf(stderr,"\n");
367
+    }
368
+  }
369
+  return layers;
370
+}
371
+
372
+void close_inputs(layer **layers) {
373
+  int i;
374
+  for(i=0; i<ninputs; i++) {
375
+	GDALClose((*layers)[i].dataset_h);
376
+	free((*layers)[i].buffer);
377
+	free((*layers)[i].iobuffer);
378
+  }
379
+  free(*layers);
380
+  *layers = NULL;
381
+}
382
+
383
+GDALDataType gdal_data_type(char *data) {
384
+  if(data==NULL)
385
+    return GDT_Float64;
386
+  if(strcmp(data,"Byte")==0)
387
+    return GDT_Byte;
388
+  else if(strcmp(data,"UInt16")==0)
389
+    return GDT_UInt16;
390
+  else if(strcmp(data,"Int16")==0)
391
+    return GDT_Int16;
392
+  else if(strcmp(data,"UInt32")==0)
393
+    return GDT_UInt32;
394
+  else if(strcmp(data,"Int32")==0)
395
+    return GDT_Int32;
396
+  else if(strcmp(data,"Float32")==0)
397
+    return GDT_Float32;
398
+  else if(strcmp(data,"Float64")==0)
399
+    return GDT_Float64;
400
+  else
401
+    return GDT_Float64;
402
+}
403
+
404
+double read_no_data(struct arg_dbl *output_no_data) {
405
+  if(output_no_data->count==0)
406
+    return DBL_MIN;
407
+  return output_no_data->dval[0];
408
+}
409
+
410
+
411
+void create_outputs(struct arg_str *outputs, 
412
+                   layer **out, layer *inp) {
413
+  double geo_transform[6];
414
+  char *proj, *type;
415
+  int i;
416
+  layer *o;
417
+  
418
+  int is_no_data;
419
+  double no_data;
420
+  GDALDataType data_type;
421
+  char *fname; 
422
+  char *cname = NULL;
423
+  char **opts = NULL;
424
+
425
+  
426
+  o = (layer *)malloc(outputs->count * sizeof(layer));
427
+
428
+  proj = (char *)GDALGetProjectionRef(inp[0].dataset_h);  
429
+  GDALGetGeoTransform(inp[0].dataset_h,geo_transform);
430
+
431
+  for(i=0; i<outputs->count; i++) {
432
+
433
+    GDALDriverH driver = GDALGetDriverByName("GTiff");
434
+    
435
+    fname = get_file_name(outputs->sval[i]);
436
+    type = get_type_name(outputs->sval[i]);
437
+    data_type = gdal_data_type(type);
438
+    no_data = get_nodata_value(outputs->sval[i]);
439
+    is_no_data = get_isnodata_value(outputs->sval[i]);
440
+    cname = get_compression_name(outputs->sval[i]);
441
+    opts = get_compression_opts(outputs->sval[i]);
442
+
443
+    fprintf(stderr,"Output layer %s, type: %s",fname,get_type_name(outputs->sval[i]));
444
+    if(is_no_data==1)
445
+      fprintf(stderr,", no_data: %lf",no_data);
446
+    if(cname!=NULL)
447
+      fprintf(stderr,", compression: %s",cname);
448
+    fprintf(stderr,"\n");
449
+
450
+    o[i].dataset_h = GDALCreate(driver,fname,
451
+                                cols,rows,1,
452
+                                data_type,
453
+                                opts);
454
+    free(type);
455
+    free(fname);
456
+    if(cname!=NULL) free(cname);
457
+    
458
+    if(!(o[i].dataset_h)) {
459
+      show_message(stderr,"Problem with creating an output file!!");
460
+      exit(1);
461
+    }
462
+     
463
+    o[i].band_h = GDALGetRasterBand(o[i].dataset_h,1);
464
+
465
+    o[i].no_data = no_data;
466
+    o[i].is_no_data = is_no_data;
467
+    if(is_no_data)
468
+      GDALSetRasterNoDataValue(o[i].band_h,no_data);
469
+
470
+    o[i].buffer = (double *)malloc(cols*sizeof(double));
471
+    o[i].iobuffer = (double *)malloc(cols*sizeof(double));
472
+
473
+    GDALSetProjection(o[i].dataset_h,proj);
474
+    GDALSetGeoTransform(o[i].dataset_h,geo_transform);
475
+  
476
+  }
477
+  
478
+  *out = o;
479
+}
480
+
481
+void close_outputs(layer **layers) {
482
+  int i;
483
+  if(noutputs==0) return;
484
+  for(i=0; i<noutputs; i++) {
485
+	GDALClose((*layers)[i].dataset_h);
486
+	free((*layers)[i].buffer);
487
+	free((*layers)[i].iobuffer);
488
+  }
489
+  free(*layers);
490
+  *layers = NULL;
491
+}
492
+
493
+void read_buffers(int ninputs, layer *layers, int row) {
494
+  int i;
495
+  CPLErr res;
496
+  for(i=0; i<ninputs; i++) {
497
+
498
+    res=GDALRasterIO(layers[i].band_h, GF_Read, 0, row, cols, 1,
499
+                       layers[i].buffer, cols, 1, GDT_Float64, 0, 0);
500
+    if(res>2) {
501
+      show_message(stderr, "Error in data reading!");
502
+      exit(1);
503
+    }
504
+  }
505
+}
506
+
507
+void write_buffers(int noutputs, layer *layers, int row) {
508
+  int i;
509
+  CPLErr res;
510
+  if(noutputs==0) return;
511
+  for(i=0; i<noutputs; i++) {
512
+
513
+    res=GDALRasterIO(layers[i].band_h, GF_Write, 0, row, cols, 1,
514
+                     layers[i].buffer, cols, 1, GDT_Float64, 0, 0);
515
+    if(res>2) {
516
+      show_message(stderr, "Error in data writting!");
517
+      exit(1);
518
+    }
519
+  }
520
+}
521
+
522
+
523
+void read_iobuffer(layer *l, int cols, int row) {
524
+  CPLErr res;
525
+  res=GDALRasterIO(l->band_h, GF_Read, 0, row, cols, 1,
526
+                   l->iobuffer, cols, 1, GDT_Float64, 0, 0);
527
+  if(res>2) {
528
+    show_message(stderr, "Error in data reading!");
529
+    exit(1);
530
+  }
531
+}
532
+
533
+void write_iobuffer(layer *l, int cols, int row) {
534
+  CPLErr res;
535
+  res=GDALRasterIO(l->band_h, GF_Write,0, row, cols, 1,
536
+              	   l->iobuffer, cols, 1, GDT_Float64, 0, 0);
537
+  if(res>2) {
538
+    show_message(stderr, "Error in data writting!");
539
+    exit(1);
540
+  }
541
+}
542
+
543
+void swap_buffers(layer *l) {
544
+  double *d;
545
+  d = l->buffer;
546
+  l->buffer = l->iobuffer;
547
+  l->iobuffer = d;
548
+}
549
+
550
+char *empty = "\0";
551
+
552
+void get_code(struct arg_file *file, struct arg_str *prog, int *is_file, long *len, char **buffer) {
553
+  *len = 0;
554
+  *is_file = 0;
555
+  
556
+  if(file->count==0 && prog->count==0)
557
+    return;
558
+  if(file->count>0) {
559
+    if(strcmp("mc",file->extension[0])==0)
560
+      return;
561
+    FILE *f = fopen(file->filename[0],"r");
562
+    if(f) {
563
+      fseek(f,0,SEEK_END);
564
+      *len=ftell(f);
565
+      fseek(f,0,SEEK_SET);
566
+      *buffer=(char*)malloc(*len);
567
+      *is_file=1;
568
+      fread(*buffer,1,*len,f);
569
+      fclose(f);
570
+    } else {
571
+      show_message(stderr, "Cannot read a macro file!");
572
+      exit(2);
573
+    }
574
+  } else {
575
+    *len=(long)strlen(prog->sval[0]);
576
+    *buffer=(char *)prog->sval[0];
577
+  }
578
+}
579
+
580
+
581
+char *prepare_code(struct arg_file *file, struct arg_str *prog,
582
+                   struct arg_file *file_begin, struct arg_str *prog_begin,
583
+                   struct arg_file *file_end, struct arg_str *prog_end) {
584
+  char prog_template[] = 
585
+       "#include <math.h>\n" 
586
+       "#include <stdio.h>\n" 
587
+       "int start_count = 1;\n"
588
+       "int restart_flag = 0;\n"
589
+       "void RESTART() {start_count++; restart_flag=-1;}\n" 
590
+       "int ITERATION() {return start_count;}\n" 
591
+       "int exec_begin(int COLS, int ROWS, int MEMNUM, double *MEM, double* GEOTRANS) {\n"
592
+       "  restart_flag = 0;\n"
593
+       "  %s\n"
594
+       "  return 0;\n"
595
+       "}\n"
596
+       "int exec_cell(int COLS, int ROWS, int COL, int ROW, int INPNUM, int OUTNUM, int MEMNUM, double *IN, double *OUT, double *MEM, double* GEOTRANS) {"
597
+       "  restart_flag = 0;\n"
598
+       "  %s\n"
599
+       "  return restart_flag;\n"
600
+       "}\n"
601
+       "int exec_end(int COLS, int ROWS, int MEMNUM, double *MEM, double* GEOTRANS) {\n"
602
+       "  restart_flag = 0;\n"
603
+       "  %s\n"
604
+       "  return restart_flag;\n"
605
+       "}\n\0";
606
+  char *code = NULL;
607
+  char *code_cell = empty;
608
+  char *code_begin = empty;
609
+  char *code_end = empty;
610
+  long l = (long)strlen(prog_template);
611
+  long ll;
612
+
613
+  int is_file_cell = 0;
614
+  int is_file_begin = 0;
615
+  int is_file_end = 0;
616
+
617
+  get_code(file_begin, prog_begin, &is_file_begin, &ll, &code_begin);
618
+  l+=ll;
619
+  get_code(file, prog, &is_file_cell, &ll, &code_cell);
620
+  l+=ll;
621
+  get_code(file_end, prog_end, &is_file_end, &ll, &code_end);
622
+  l+=ll;
623
+  l++;
624
+  code=malloc(l);
625
+  sprintf(code, prog_template, code_begin, code_cell, code_end);
626
+  if(is_file_begin)
627
+    free(code_begin);
628
+  if(is_file_cell)
629
+    free(code_cell);
630
+  if(is_file_end)
631
+    free(code_end);
632
+
633
+  return code;
634
+}
635
+
636
+void compile_code(TCCState* tcc, char *code) {
637
+
638
+  if (!tcc) {
639
+    show_message(stderr, "Cannot create executable code (stage 1)");
640
+    exit(1);
641
+  }
642
+
643
+  char *path = malloc(strlen(libtcc_path) + 30);
644
+
645
+  tcc_set_lib_path(tcc, libtcc_path);
646
+
647
+  strcpy(path, libtcc_path);
648
+  strcat(path, "include");
649
+  tcc_add_include_path(tcc, path);
650
+
651
+  strcpy(path, libtcc_path);
652
+  strcat(path, "lib");
653
+  tcc_add_library_path(tcc, path);
654
+
655
+  free(path);
656
+// #else
657
+  /* Linux 64 section */
658
+  //tcc_add_library_path(tcc, "/usr/share/mapcalc/");
659
+//  tcc_set_lib_path(tcc, "/usr/local/share/plmapcalc");
660
+//  tcc_add_include_path(tcc, "/usr/loacl/share/plmapcalc/include");
661
+//  tcc_add_include_path(tcc, "/usr/local/share/plmapcalc/tcc_include");
662
+//  tcc_set_lib_path(tcc, "/usr/local/lib/tcc");
663
+//  tcc_add_include_path(tcc, "/usr/local/lib/tcc/include");
664
+//  tcc_add_include_path(tcc, "/usr/local/include");
665
+// #endif
666
+
667
+  tcc_set_output_type(tcc, TCC_OUTPUT_MEMORY);
668
+
669
+  if (tcc_compile_string(tcc, code) == -1) {
670
+    show_message(stderr, "Cannot create executable code (stage 2)");
671
+    exit(1);
672
+  }
673
+
674
+  if (tcc_relocate(tcc, TCC_RELOCATE_AUTO) < 0) {
675
+    show_message(stderr, "Cannot create executable code (stage 3)");
676
+    exit(1);
677
+  }
678
+}
679
+
680
+
681
+exec_type get_cell_function(TCCState* tcc) {
682
+
683
+  exec_type e = tcc_get_symbol(tcc, "exec_cell");
684
+  if (!e) {
685
+    show_message(stderr, "Cannot create CELL executable");
686
+    exit(1);
687
+  }
688
+  
689
+  return e;
690
+}
691
+
692
+begin_end_exec_type get_begin_function(TCCState* tcc) {
693
+
694
+  begin_end_exec_type e = tcc_get_symbol(tcc, "exec_begin");
695
+  if (!e) {
696
+    show_message(stderr, "Cannot create BEGIN executable");
697
+    exit(1);
698
+  }
699
+  
700
+  return e;
701
+}
702
+
703
+begin_end_exec_type get_end_function(TCCState* tcc) {
704
+
705
+  begin_end_exec_type e = tcc_get_symbol(tcc, "exec_end");
706
+  if (!e) {
707
+    show_message(stderr, "Cannot create END executable");
708
+    exit(1);
709
+  }
710
+  
711
+  return e;
712
+}
713
+
714
+int is_null(layer *l, double v) {
715
+  if((l->is_no_data) && (v==l->no_data))
716
+    return TRUE;
717
+  return FALSE;
718
+}
719
+
720
+void save_memory_cells(char *fname, double *mem, int nmem, int withzeros) {
721
+  int i;
722
+  FILE *f = fopen(fname,"w");
723
+  if(f==NULL) {
724
+    fprintf(stderr, "\022[1;31mWarning: Can not store memory data into file: %s\n",fname);
725
+  } else {
726
+    for(i=0; i<nmem; i++)
727
+      if(mem[i]==0.0) {
728
+        if(withzeros!=0)
729
+          fprintf(f, "%d %.18lf\n", i, mem[i]);
730
+      } else
731
+        fprintf(f, "%d %.18lf\n", i, mem[i]);
732
+    fclose(f);
733
+  }
734
+}
735
+
736
+void read_memory_cells(char *fname, double *mem, int nmem) {
737
+  int i,k;
738
+  double d;
739
+  FILE *f = fopen(fname,"r");
740
+  if(f==NULL) {
741
+    fprintf(stderr, "\022[1;31mWarning:\033[0m Can not read memory data from file: %s\n",fname);
742
+  } else {
743
+    i=0;
744
+    while(!feof(f)) {
745
+      k = fscanf(f, "%d %lf\n", &i, &d);
746
+      if(k==2 && i>=0 && i<nmem)
747
+        mem[i]=d;
748
+    }
749
+    fclose(f);
750
+  }
751
+}
752
+
753
+int read_max_memory(char *fname) {
754
+  int i,k, max;
755
+  double d;
756
+  FILE *f = fopen(fname,"r");
757
+  i=0;
758
+  max = -1;
759
+  while(!feof(f)) {
760
+    k = fscanf(f, "%d %lf\n", &i, &d);
761
+    if(k==2 && i>max) max = i;
762
+  }
763
+  fclose(f);
764
+  return max+1;
765
+}
766
+
767
+int main(int argc,char **argv) {
768
+    TCCState* tcc; 
769
+    exec_type exec;
770
+    begin_end_exec_type exec_begin = NULL;
771
+    begin_end_exec_type exec_end = NULL;
772
+    char *code;
773
+    int nerr;
774
+    int row;
775
+    double *in_data;
776
+    double *out_data = NULL;
777
+    double *memory = NULL;
778
+    int memnum = 0;
779
+    int ip;
780
+    int remove_nan = FALSE;
781
+
782
+
783
+    /* args */
784
+    struct arg_lit  *help = arg_lit0("h", "help", "program usage");
785
+    struct arg_lit  *quiet = arg_lit0("q", "quiet", "quiet mode");
786
+    struct arg_lit  *check = arg_lit0(NULL, "check", "display parameters and check their correctness");
787
+    struct arg_lit  *overwrite = arg_lit0("f", "force", "force to overwrite output file");
788
+    struct arg_lit  *nan = arg_lit0(NULL, "use-nan", "force to treat NAN as a value (default: no-data)");
789
+    struct arg_int  *threads = arg_int0("t", "threads", "<n>","number of threads");
790
+    struct arg_str  *input = arg_strn("i", "input", "file.tif[:band]",1,MAX_INPUTS,"input layer(s) (GeoTIFF)");
791
+    struct arg_str  *output = arg_strn("o", "output", "file.tif[:type[:no_data:[compression]]]",0,MAX_OUTPUTS,"output layer(s): file name, data type (Byte, Int16, UInt16, Int32, UInt32, Float32, default Float64), no_data value (default 0.0), compress (NONE, DEFLATE, DEFLATE2, DEFLATE3, LZW, LZW2, LZW3). (GeoTIFF)");
792
+    struct arg_int  *mem = arg_int0("m", "memory", "<n>","number of memory cells to store temporary data");
793
+    struct arg_str  *memstore = arg_str0("s", "memory-store", "<file name>","file to store memory cells (TXT)");
794
+    struct arg_str  *memread  = arg_str0("r", "memory-read", "<file name>","file to read memory cells (TXT)");
795
+    struct arg_lit  *memzero  = arg_lit0("0", "store-zeroes", "store all memory cells including zeros (defalt: no)");
796
+    struct arg_str  *prog = arg_str0("e", "execute", "' code '","code to execute");
797
+    struct arg_file *file = arg_file0("p", "program", "<file>.mc","file with code to execute");
798
+    struct arg_str  *prog_begin = arg_str0(NULL, "execute-begin", "' code '","code to execute at the start");
799
+    struct arg_file *file_begin = arg_file0(NULL, "program-begin", "<file>.mc","file with code to execute at the start");
800
+    struct arg_str  *prog_end = arg_str0(NULL, "execute-end", "' code '","code to execute at the end");
801
+    struct arg_file *file_end = arg_file0(NULL, "program-end", "<file>.mc","file with code to execute at the end");
802
+    struct arg_str  *path = arg_str0(NULL, "path", "<directory path>","path to TCC library and resurces");
803
+    struct arg_end  *end = arg_end(20);
804
+    void *argtable[] = {help, quiet, check, overwrite, nan,
805
+		                threads,
806
+		                input, output, 
807
+		                mem, memread, memstore, memzero,
808
+		                prog, file,
809
+		                prog_begin, file_begin,
810
+		                prog_end, file_end,
811
+		                path,
812
+		                end};
813
+
814
+    nerr = arg_parse(argc,argv,argtable);
815
+
816
+    if(nerr!=0 || help->count>0) {
817
+      show_help(argv[0],argtable);
818
+      arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0]));
819
+      return 1;
820
+    }
821
+
822
+    if(prog->count==0 && file->count==0 &&
823
+       prog_begin->count==0 && file_begin->count==0 &&
824
+       prog_end->count==0 && file_end->count==0) {
825
+      printf("\nNo program code to execute!\n\n");
826
+      arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0]));
827
+      return 1;
828
+    }
829
+
830
+    if(path->count>0) {
831
+      strcpy(libtcc_path, path->sval[0]);
832
+    } else {
833
+      char *p = getenv("PLMAPCALCPATH");
834
+      if(p!=NULL && strcmp(p,"")!=0)
835
+        strcpy(libtcc_path, p);
836
+    }
837
+
838
+    remove_nan = (nan->count==0);
839
+
840
+      fl_quiet = (quiet->count>0);
841
+      
842
+      ninputs = input->count;
843
+      noutputs = output->count;
844
+
845
+      in_data = (double *)malloc(ninputs*sizeof(double));
846
+      if(noutputs>0) {
847
+        out_data = (double *)malloc(noutputs*sizeof(double));
848
+
849
+        /* Checking of the existance of output files */
850
+        if(overwrite->count==0 && file_exists(output->sval[0])) {
851
+          for(ip=0; ip<noutputs; ip++) {
852
+            char *s = get_file_name(output->sval[ip]);
853
+            if(file_exists(s)) {
854
+              show_message(stderr,"Output file already exists. Use -f flag to force owerwrite.");
855
+              exit(1);
856
+            }
857
+            free(s);
858
+          }
859
+        }
860
+      }
861
+
862
+      /* Compile code to run */
863
+      code = prepare_code(file, prog, file_begin, prog_begin, file_end, prog_end);
864
+      if(code==NULL) {
865
+        show_message(stderr, "Could not read code to execute.");
866
+        exit(1);
867
+      }
868
+
869
+      tcc = tcc_new();
870
+
871
+      compile_code(tcc,code);
872
+      exec_begin = get_begin_function(tcc);
873
+      exec = get_cell_function(tcc);
874
+      exec_end = get_end_function(tcc);
875
+
876
+      /* Open input layers, checking projection and extent */
877
+      GDALAllRegister();
878
+      input_layers = open_inputs(input);
879
+      if(!is_pojection_ok(input_layers,ninputs)) {
880
+        show_message(stderr, "All input files should have the same projection.");
881
+        exit(1);
882
+      };
883
+      if(!is_bbox_ok(input_layers,ninputs)) {
884
+        show_message(stderr, "All input files should have the same extent and resolution.");
885
+        exit(1);
886
+      };
887
+
888
+      /* Creating output layers */
889
+      if(noutputs>0) {
890
+        create_outputs(output,&output_layers,&(input_layers[0]));
891
+      }
892
+
893
+      if(mem->count>0) {
894
+        memnum = mem->ival[0];
895
+        if(memnum<1) 
896
+          memnum=0;
897
+        else
898
+          memory = (double *)calloc(memnum,sizeof(double));
899
+      }
900
+
901
+      if(memread->count>0) {
902
+        if(file_exists((char *)(memread->sval[0]))) {
903
+          fprintf(stderr, "Memory data will be read from file: %s\n",memread->sval[0]);
904
+          if(memory==NULL) {
905
+		    memnum = read_max_memory((char *)(memread->sval[0]));
906
+            if(memnum==0) {
907
+              show_message(stderr, "File with memory data is not properly formated!");
908
+              exit(1);
909
+            } else 
910
+              memory = (double *)calloc(memnum,sizeof(double));
911
+          }
912
+          read_memory_cells((char *)(memread->sval[0]), memory, memnum);
913
+        } else {
914
+          show_message(stderr, "File with memory data does not exist!");
915
+          exit(1);
916
+        }
917
+      }
918
+
919
+      if(memory!=NULL && memstore->count>0)
920
+        fprintf(stderr, "Memory data will be stored into file: %s\n",memstore->sval[0]);
921
+
922
+      if(threads->count>0 && threads->ival[0]>0 && threads->ival[0]<100) {
923
+        if(threads->ival[0]>ninputs+noutputs+1 && memory!=NULL)
924
+		  omp_set_num_threads(ninputs+noutputs+1);
925
+        else
926
+		  omp_set_num_threads(threads->ival[0]);
927
+      } else 
928
+        omp_set_num_threads(1);
929
+
930
+      int data_reset;
931
+
932
+	  double *geotransform = malloc(6*sizeof(double));
933
+	  GDALGetGeoTransform(input_layers[0].dataset_h, geotransform);
934
+
935
+double t1 = omp_get_wtime();
936
+
937
+      data_reset = exec_begin(cols,rows,memnum,memory,geotransform);
938
+      do {
939
+        data_reset = 0;
940
+        show_progress(0,rows);
941
+
942
+        int i;
943
+        for(i=0; i<ninputs; i++) {
944
+		  read_iobuffer(&(input_layers[i]), cols, 0);
945
+          swap_buffers(&(input_layers[i]));
946
+        }
947
+
948
+        for(row=0; row<rows; row++) {
949
+          show_progress(row,rows);
950
+
951
+#ifndef WIN64
952
+		  /* Linux 64 section - OpenMP 5*/
953
+#pragma omp parallel default(none) shared(ninputs, noutputs, row, rows, cols, memory, memnum, input_layers, output_layers, data_reset, remove_nan, exec, geotransform) 
954
+{
955
+#pragma omp single 
956
+{
957
+#pragma omp task shared(ninputs, noutputs, row, rows, cols, memory, memnum, input_layers, output_layers, data_reset, remove_nan, exec, geotransform) 
958
+{
959
+#endif
960
+
961
+#pragma omp parallel for default(shared) schedule(dynamic,100) if(memory==NULL)
962
+          for(int col=0; col<cols; col++) {
963
+
964
+            if(data_reset==0) {
965
+              double in[MAX_INPUTS];
966
+              double out[MAX_OUTPUTS];
967
+              double v;
968
+              layer *l = NULL;
969
+              int data_ok = TRUE;
970
+              int i, res;
971
+
972
+
973
+              for(i=0; data_ok && i<ninputs; i++) { 
974
+                l = input_layers + i;
975
+                v = l->buffer[col];
976
+                if(is_null(l,v) || (remove_nan && (isnan(v) || isinf(v)))) {
977
+                  data_ok = FALSE;
978
+                  break;
979
+                } else
980
+                  in[i] = v;
981
+              }
982
+
983
+              if(data_ok) {
984
+                if(noutputs>0)
985
+                  memset(out,0,noutputs*sizeof(double));
986
+
987
+                res = exec(cols,rows,col,row,ninputs,noutputs,memnum,in,out,memory,geotransform);
988
+                if(data_reset==0 && res!=0) {
989
+                  #pragma omp critical 
990
+                  {
991
+                    data_reset = res;
992
+                  }
993
+                }
994
+                for(i=0; i<noutputs; i++)
995
+                  output_layers[i].buffer[col] = out[i];
996
+              } else {
997
+                for(i=0; i<noutputs; i++) {
998
+                  l = output_layers + i;
999
+                  l->buffer[col] = l->no_data;
1000
+                }
1001
+              }
1002
+            }
1003
+          }
1004
+
1005
+#ifndef WIN64
1006
+}
1007
+#endif
1008
+          int i;
1009
+          if(row<rows-1)
1010
+            for(i=0; i<ninputs; i++)
1011
+#ifndef WIN64
1012
+#pragma omp task shared(input_layers,i,cols,row)
1013
+#endif
1014
+{
1015
+			  read_iobuffer(&(input_layers[i]), cols, row+1);
1016
+}
1017
+          if(row>0)
1018
+			for(i=0; i<noutputs; i++)
1019
+#ifndef WIN64
1020
+#pragma omp task shared(input_layers,i,cols,row)
1021
+#endif
1022
+{
1023
+			  write_iobuffer(&(output_layers[i]), cols, row-1);
1024
+}
1025
+#ifndef WIN64
1026
+#pragma omp taskwait
1027
+}
1028
+}
1029
+#endif
1030
+	  for (i = 0; i<ninputs; i++)
1031
+  		  swap_buffers(&(input_layers[i]));
1032
+        for(i=0; i<noutputs; i++)
1033
+  		  swap_buffers(&(output_layers[i]));
1034
+      }
1035
+      for(i=0; i<noutputs; i++)
1036
+		write_iobuffer(&(output_layers[i]), cols, rows-1);
1037
+
1038
+      show_progress(rows,rows);
1039
+      if(data_reset==0)
1040
+        data_reset = exec_end(cols,rows,memnum,memory,geotransform);
1041
+
1042
+    } while(data_reset!=0);
1043
+
1044
+      if(memory!=NULL) {
1045
+        if(memstore->count>0)
1046
+          save_memory_cells((char *)(memstore->sval[0]), memory, memnum, memzero->count);
1047
+        free(memory);
1048
+      }
1049
+
1050
+      close_inputs(&input_layers); 
1051
+      close_outputs(&output_layers); 
1052
+
1053
+double t2 = omp_get_wtime();
1054
+if(quiet->count==0) {
1055
+  fprintf(stderr,"\nTime: %lf\n\n",t2-t1);
1056
+  fprintf(stderr,"  plMapcalc version: %s\n\n", VERSION);
1057
+}
1058
+      tcc_delete(tcc);
1059
+//      free(in);
1060
+//      free(out);
1061
+      free(in_data);
1062
+      free(out_data);
1063
+      free(code);
1064
+
1065
+    arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0]));
1066
+
1067
+    return 0;
1068
+}
0 1069