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

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/source/fitz/getopt.c	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,226 @@
+/*
+ * This is a version of the public domain getopt implementation by
+ * Henry Spencer originally posted to net.sources.
+ *
+ * This file is in the public domain.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "mupdf/fitz/getopt.h"
+#include "mupdf/fitz/string-util.h"
+
+char *fz_optarg; /* Global argument pointer. */
+int fz_optind = 0; /* Global argv index. */
+const fz_getopt_long_options *fz_optlong = NULL;
+int fz_optitem = 0; /* Which item in a long opt list is selected? */
+
+static int
+match_long_option(int argc, char * const *argv, const fz_getopt_long_options *longopts, char *opt)
+{
+	if (longopts == NULL)
+	{
+		fprintf(stderr, "%s: unknown option --%s\n", argv[0], opt);
+		return '?';
+	}
+
+	while (longopts->option)
+	{
+		const char *s = longopts->option;
+		const char *eq = strchr(s, '=');
+		size_t z = eq ? (size_t)(eq-s) : strlen(s);
+		int arg = 0; /* No arg */
+
+		if (s[z] == '=')
+			arg = 1; /* arg = 1 => Arg list given */
+		else if (z && s[z-1] == ':')
+			arg = 2, z--; /* arg = 2 -> argument expected */
+
+		/* If we don't match, try the next one. */
+		/* If we aren't expecting an argument, and the given string is longer than expected, try the next one. */
+		/* If we are expecting an argument, and the given string doesn't either terminate or end in '=', try the next one. */
+		if (strncmp(s, opt, z) || (arg == 0 && opt[z] != 0) || (arg != 0 && opt[z] != 0 && opt[z] != '='))
+		{
+			longopts++;
+			continue;
+		}
+
+		/* So we have a match. */
+		fz_optind++;
+		if (opt[z])
+			fz_optarg = &opt[z+1];
+		else if (fz_optind < argc)
+			fz_optarg = argv[fz_optind++];
+		else
+		{
+			fprintf(stderr, "%s: option requires argument --%s\n", argv[0], s);
+			return ':';
+		}
+
+		/* If there is an arg from a predefined list, try to match that here. */
+		if (arg == 1)
+		{
+			fz_optitem = fz_opt_from_list(&opt[z+1], &s[z+1]);
+			if (longopts->flag)
+				*longopts->flag = fz_optitem;
+			if (fz_optitem < 0)
+				return '?';
+		}
+		else if (arg == 2 && longopts->flag)
+		{
+			char *p = strchr(fz_optarg, ',');
+			if (*fz_optarg == 0)
+			{
+				fprintf(stderr, "%s: option requires argument --%s\n", argv[0], s);
+				return ':';
+			}
+			else if (!fz_strcasecmp(fz_optarg, "yes") || !fz_strcasecmp(fz_optarg, "on") || !fz_strcasecmp(fz_optarg, "true"))
+				*longopts->flag = 1;
+			else if (!fz_strcasecmp(fz_optarg, "no") || !fz_strcasecmp(fz_optarg, "off") || !fz_strcasecmp(fz_optarg, "false"))
+				*longopts->flag = 0;
+			else
+				*longopts->flag = fz_atoi(fz_optarg);
+			fz_optarg = p ? p+1 : NULL;
+		}
+		fz_optlong = longopts;
+		return 0;
+	}
+
+	fprintf(stderr, "%s: unknown option --%s\n", argv[0], opt);
+	return '?';
+}
+
+static char *scan = NULL; /* Private scan pointer. */
+
+int
+fz_getopt_long(int argc, char * const *argv, const char *optstring, const fz_getopt_long_options *longopts)
+{
+	int c;
+	const char *place;
+
+	fz_optarg = NULL;
+	fz_optlong = NULL;
+	fz_optitem = -1;
+
+	while (!scan || *scan == '\0')
+	{
+		if (fz_optind == 0)
+			fz_optind++;
+
+		if (fz_optind >= argc || argv[fz_optind][0] != '-' || argv[fz_optind][1] == '\0')
+			return EOF;
+		if (argv[fz_optind][1] == '-' && argv[fz_optind][2] == '\0') {
+			fz_optind++;
+			return EOF;
+		}
+		if (argv[fz_optind][1] == '-')
+		{
+			scan = NULL;
+			return match_long_option(argc, argv, longopts, &argv[fz_optind][2]);
+		}
+
+		scan = argv[fz_optind]+1;
+		fz_optind++;
+	}
+
+	c = *scan++;
+	place = strchr(optstring, c);
+
+	if (!place || c == ':') {
+		fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
+		return '?';
+	}
+
+	place++;
+	if (*place == ':') {
+		if (*scan != '\0') {
+			fz_optarg = scan;
+			scan = NULL;
+		} else if( fz_optind < argc ) {
+			fz_optarg = argv[fz_optind];
+			fz_optind++;
+		} else {
+			fprintf(stderr, "%s: option requires argument -%c\n", argv[0], c);
+			return ':';
+		}
+	}
+
+	return c;
+}
+
+int
+fz_getopt(int argc, char *const *argv, const char *optstring)
+{
+	return fz_getopt_long(argc, argv, optstring, NULL);
+}
+
+int
+fz_opt_from_list(char *opt, const char *optlist)
+{
+	int n = 0;
+
+	while (*optlist)
+	{
+		const char *optend = optlist;
+
+		if (*optend == '*')
+		{
+			fz_optarg = opt;
+			return n;
+		}
+
+		while (*optend != 0 && *optend != '|' && *optend != ':')
+			optend++;
+
+		if (fz_strncasecmp(optlist, opt, optend-optlist))
+		{
+			/* We didn't match. Carry on. */
+		}
+		else if (opt[optend-optlist] == 0)
+		{
+			/* We matched, ending in NUL */
+			fz_optarg = NULL;
+			return n;
+		}
+		else if (*optend == ':' && opt[optend-optlist] == ':')
+		{
+			/* We matched, and we both have some arguments and expected some. */
+			fz_optarg = &opt[optend-optlist+1];
+			return n;
+		}
+
+		n++;
+		if (*optend == ':')
+		{
+			optend++;
+			if (*optend == '|')
+				optend++;
+			else if (*optend != 0)
+			{
+				fprintf(stderr, "Malformed options string");
+				return -1;
+			}
+		}
+		if (*optend == '|')
+			optend++;
+		optlist = optend;
+	}
+
+	fprintf(stderr, "Unrecognised option argument: %s\n", opt);
+	return -1;
+}
+
+char *
+fz_optpath(char *opt)
+{
+	if (!strcmp(opt, "-"))
+		return "/dev/stdout";
+#ifdef _WIN32
+	if (!fz_strcasecmp(opt, "con"))
+		return "/dev/stdout";
+	if (!fz_strcasecmp(opt, "nul"))
+		return "/dev/null";
+#endif
+	return opt;
+}