- /* just an ordinary option */
- else
- new_commandline=g_strconcat(m4_commandline,
- " ",
- argv[i],
- NULL);
-
- /* free old commandline */
- g_free(m4_commandline);
- m4_commandline=new_commandline;
-
- } else if(no_opts ||
- argv[i][0] != '-') {
- /*must be a file*/
- if(got_file) {
- fprintf(stderr, "Specify only one file!\n");
- print_help();
- exit(1);
- }
- filename = argv[i];
- got_file = TRUE;
- } else if(strcmp(argv[i], "--help")==0) {
- print_help();
- exit(0);
- } else if(strcmp(argv[i], "--version")==0) {
- fprintf(stderr, "Gob version %s\n", VERSION);
- exit(0);
- } else if(strcmp(argv[i], "--exit-on-warn")==0) {
- exit_on_warn = TRUE;
- } else if(strcmp(argv[i], "--no-exit-on-warn")==0) {
- exit_on_warn = FALSE;
- } else if(strcmp(argv[i], "--for-cpp")==0) {
- for_cpp = TRUE;
- } else if(strcmp(argv[i], "--no-touch")==0) {
- no_touch = TRUE;
- no_touch_headers = TRUE;
- } else if(strcmp(argv[i], "--no-touch-headers")==0) {
- no_touch_headers = TRUE;
- } else if(strcmp(argv[i], "--ondemand-private-header")==0) {
- private_header = PRIVATE_HEADER_ONDEMAND;
- } else if(strcmp(argv[i], "--always-private-header")==0) {
- private_header = PRIVATE_HEADER_ALWAYS;
- } else if(strcmp(argv[i], "--no-private-header")==0) {
- private_header = PRIVATE_HEADER_NEVER;
- } else if(strcmp(argv[i], "--no-gnu")==0) {
- no_gnu = TRUE;
- } else if(strcmp(argv[i], "--no-extern-c")==0) {
- no_extern_c = TRUE;
- } else if(strcmp(argv[i], "--no-write")==0) {
+/*
+ * Given a long option, return the corresponding short option character,
+ * or 0 if there is no such character.
+ */
+static char lopt_to_sopt(const char *sopts, const struct option *opt)
+{
+ int val = opt->val;
+ const char *c;
+
+ if (val <= 0 || val > CHAR_MAX)
+ return 0;
+
+ if (val == ':' || val == '+' || val == '-')
+ return 0;
+
+ c = strchr(sopts, opt->val);
+ if (c)
+ return *c;
+ return 0;
+}
+
+/*
+ * Print a string, with each line indented by i spaces. The first line
+ * will be indented by w fewer spaces (to account for the cursor being in
+ * some other column).
+ */
+static void print_block(const char *s, int i, int w)
+{
+ for (; *s; w = 0) {
+ const char *nl = strchr(s, '\n');
+ int n = (nl ? nl-s : -1);
+
+ printf("%*s%.*s\n", i-w, "", n, s);
+ if (!nl)
+ break;
+
+ s = nl+1;
+ }
+}
+
+static void print_help(void)
+{
+ const struct option *opt;
+
+ print_usage(stdout);
+
+ puts("This is \"GObject Builder\": a simple preprocessor to help with\n"
+ "implementing GObject types in C.");
+
+ puts("\nOptions:");
+ for (opt = lopts; opt->name; opt++) {
+ struct lopt_help help;
+ char sopt;
+ int w;
+
+ /* Don't display obsolete options that don't do anything */
+ if (!opt->flag && !opt->val)
+ continue;
+
+ if (!lopt_get_help(opt, &help))
+ continue;
+
+ if ((sopt = lopt_to_sopt(sopts, opt))) {
+ w = printf(opt->has_arg == 0 ? " -%c, --%s"
+ : opt->has_arg == 1 ? " -%c, --%s=%s"
+ : " -%c, --%s[=%s]",
+ sopt, opt->name, help.arg);
+ } else {
+ w = printf(opt->has_arg == 0 ? " --%s"
+ : opt->has_arg == 1 ? " --%s=%s"
+ : " --%s[=%s]",
+ opt->name, help.arg);
+ }
+
+ if (w < 0 || w > 18) {
+ putchar('\n');
+ w = 0;
+ }
+
+ print_block(help.desc, 20, w);
+ }
+ putchar('\n');
+
+ puts("End world hunger, donate to the World Food Programme: https://www.wfp.org/");
+}
+
+/*
+ * Called after getopt_long receives an --m4 argument. Immediately stop
+ * processing options. Then all non-option arguments seen so far together
+ * with all remaining arguments are appended to M4_COMMANDLINE. If m4_clean
+ * is false, then M4_FLAGS is inserted before the first non-option argument,
+ * if any.
+ *
+ * The resulting string is returned, which should be freed by the caller.
+ */
+static char *parse_m4_options(int argc, char **argv, gboolean m4_clean)
+{
+ char **nonopt = NULL, *save_argv0, *ret;
+ int opt;
+
+ /* First, conclude getopt run and reset with remaining args */
+ getopt_long(optind, argv, sopts, lopts, NULL);
+ argv += optind-1;
+ argc -= optind-1;
+ optind = 0;
+
+ save_argv0 = argv[0];
+ argv[0] = M4_COMMANDLINE;
+
+ if (m4_clean) {
+ ret = g_strjoinv(" ", argv);
+ argv[0] = save_argv0;
+ return ret;
+ }
+
+ /* Locate first non-option argument, if any. */
+ while ((opt = getopt_long(argc, argv, "-", NULL, NULL)) != -1) {
+ if (opt == 1) {
+ nonopt = &argv[optind-2];
+ break;
+ }
+ }
+
+ /* If there is a non-option but the above didn't see it, must be "--" */
+ if (!nonopt && argv[optind])
+ nonopt = &argv[optind-2];
+
+ if (nonopt) {
+ /* Found non-option, insert M4_FLAGS just before it. */
+ char *save_argv[3] = { nonopt[0], nonopt[1], nonopt[2] };
+
+ nonopt[1] = M4_FLAGS;
+ nonopt[2] = NULL;
+ nonopt[0] = g_strjoinv(" ", argv);
+
+ nonopt[1] = save_argv[1];
+ nonopt[2] = save_argv[2];
+ ret = g_strjoinv(" ", nonopt);
+
+ g_free(nonopt[0]);
+ nonopt[0] = save_argv[0];
+ } else {
+ /* Only options, not inserting M4_FLAGS. */
+ ret = g_strjoinv(" ", argv);
+ }
+
+ argv[0] = save_argv0;
+ return ret;
+}
+
+static int parse_options(int argc, char **argv)
+{
+ gboolean show_m4_dir = FALSE, m4_clean = FALSE;
+ char *raw_file_sep = "-";
+ int opt;
+
+ opterr = 0;
+ while ((opt = getopt_long(argc, argv, sopts, lopts, NULL)) != -1) {
+ switch (opt) {
+ case 'n':