From 0fcdfef28498700e974c9b9444087f2773571b36 Mon Sep 17 00:00:00 2001 From: Jan Nieuwenhuizen Date: Sun, 19 Nov 2017 16:48:37 +0100 Subject: [PATCH] mlibc: Mescc-tools support: getopt, getopt_long. * mlibc/getopt.c: Move to ANSI C. Remove GETOPT_COMPAT and non-POSIXLY_CORRECT options. * mlibc/include/getopt.h: New file. * mlibc/libc-gcc+tcc.c: Include getopt.c. * mlibc/libc-mes+tcc.c: Likewise. --- mlibc/getopt.c | 333 ++--------------------------------------- mlibc/include/getopt.h | 60 ++++++++ mlibc/libc-gcc+tcc.c | 1 + mlibc/libc-mes+tcc.c | 1 + 4 files changed, 78 insertions(+), 317 deletions(-) create mode 100644 mlibc/include/getopt.h diff --git a/mlibc/getopt.c b/mlibc/getopt.c index e13fac3b..91555ab1 100644 --- a/mlibc/getopt.c +++ b/mlibc/getopt.c @@ -1,9 +1,6 @@ /* Getopt for GNU. - NOTE: getopt is now part of the C library, so if you don't know what - "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu - before changing it! - Copyright (C) 1987, 88, 89, 90, 91, 1992 Free Software Foundation, Inc. + Copyright (C) 2017 Jan Nieuwenhuizen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,68 +16,18 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* AIX requires this to be the first thing in the file. */ -#ifdef __GNUC__ -#define alloca __builtin_alloca -#else /* not __GNUC__ */ -#ifdef sparc -#include -#else -#ifdef _AIX - #pragma alloca -#else -char *alloca (); -#endif -#endif /* sparc */ -#endif /* not __GNUC__ */ - -#ifdef LIBC -/* For when compiled as part of the GNU C library. */ -#include -#endif #include +#include +#include -/* This needs to come after some library #include - to get __GNU_LIBRARY__ defined. */ -#ifdef __GNU_LIBRARY__ -#undef alloca -#include -#else /* Not GNU C library. */ -#define __alloca alloca -#endif /* GNU C library. */ - - -#ifndef __STDC__ -#define const +#if __MESC__ +#define static #endif -/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a - long-named option. Because this is not POSIX.2 compliant, it is - being phased out. */ -#define GETOPT_COMPAT - -/* This version of `getopt' appears to the caller like standard Unix `getopt' - but it behaves differently for the user, since it allows the user - to intersperse the options with the other arguments. - - As `getopt' works, it permutes the elements of ARGV so that, - when it is done, all the options precede everything else. Thus - all application programs are extended to handle flexible argument order. - - Setting the environment variable POSIXLY_CORRECT disables permutation. - Then the behavior is completely standard. - - GNU application programs can use a third alternative mode in which - they can distinguish the relative order of options and other arguments. */ - -#include "getopt.h" - /* For communication from `getopt' to the caller. When `getopt' finds an option that takes an argument, - the argument value is returned here. - Also, when `ordering' is RETURN_IN_ORDER, - each non-option ARGV-element is returned here. */ + the argument value is returned here. */ char *optarg = 0; @@ -112,75 +59,6 @@ static char *nextchar; int opterr = 1; -/* Describe how to deal with options that follow non-option ARGV-elements. - - If the caller did not specify anything, - the default is REQUIRE_ORDER if the environment variable - POSIXLY_CORRECT is defined, PERMUTE otherwise. - - REQUIRE_ORDER means don't recognize them as options; - stop option processing when the first non-option is seen. - This is what Unix does. - This mode of operation is selected by either setting the environment - variable POSIXLY_CORRECT, or using `+' as the first character - of the list of option characters. - - PERMUTE is the default. We permute the contents of ARGV as we scan, - so that eventually all the non-options are at the end. This allows options - to be given in any order, even with programs that were not written to - expect this. - - RETURN_IN_ORDER is an option available to programs that were written - to expect options and other ARGV-elements in any order and that care about - the ordering of the two. We describe each non-option ARGV-element - as if it were the argument of an option with character code 1. - Using `-' as the first character of the list of option characters - selects this mode of operation. - - The special argument `--' forces an end of option-scanning regardless - of the value of `ordering'. In the case of RETURN_IN_ORDER, only - `--' can cause `getopt' to return EOF with `optind' != ARGC. */ - -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER -} ordering; - -#ifdef __GNU_LIBRARY__ -#include -#define my_index strchr -#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n)) -#else - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -char *getenv (); - -static char * -my_index (string, chr) - char *string; - int chr; -{ - while (*string) - { - if (*string == chr) - return string; - string++; - } - return 0; -} - -static void -my_bcopy (from, to, size) - char *from, *to; - int size; -{ - int i; - for (i = 0; i < size; i++) - to[i] = from[i]; -} -#endif /* GNU C library. */ /* Handle permutation of arguments. */ @@ -191,34 +69,6 @@ my_bcopy (from, to, size) static int first_nonopt; static int last_nonopt; -/* Exchange two adjacent subsequences of ARGV. - One subsequence is elements [first_nonopt,last_nonopt) - which contains all the non-options that have been skipped so far. - The other is elements [last_nonopt,optind), which contains all - the options processed since those non-options were skipped. - - `first_nonopt' and `last_nonopt' are relocated so that they describe - the new indices of the non-options in ARGV after they are moved. */ - -static void -exchange (argv) - char **argv; -{ - int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); - char **temp = (char **) __alloca (nonopts_size); - - /* Interchange the two blocks of data in ARGV. */ - - my_bcopy (&argv[first_nonopt], temp, nonopts_size); - my_bcopy (&argv[last_nonopt], &argv[first_nonopt], - (optind - last_nonopt) * sizeof (char *)); - my_bcopy (temp, &argv[first_nonopt + optind - last_nonopt], nonopts_size); - - /* Update records for the slots the non-options now occupy. */ - - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; -} /* Scan elements of ARGV (whose length is ARGC) for option characters given in OPTSTRING. @@ -251,7 +101,6 @@ exchange (argv) If OPTSTRING starts with `-' or `+', it requests different methods of handling the non-option ARGV-elements. - See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. Long-named options begin with `--' instead of `-'. Their names may be abbreviated as long as the abbreviation is unique @@ -277,13 +126,8 @@ exchange (argv) long-named options. */ int -_getopt_internal (argc, argv, optstring, longopts, longind, long_only) - int argc; - char *const *argv; - const char *optstring; - const struct option *longopts; - int *longind; - int long_only; +_getopt_internal (int argc, char *const + *argv, char const *optstring, struct option const *longopts, int *longind, int long_only) { int option_index; @@ -299,69 +143,10 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) first_nonopt = last_nonopt = optind = 1; nextchar = NULL; - - /* Determine how to handle the ordering of options and nonoptions. */ - - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (getenv ("POSIXLY_CORRECT") != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; } if (nextchar == NULL || *nextchar == '\0') { - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Now skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc - && (argv[optind][0] != '-' || argv[optind][1] == '\0') -#ifdef GETOPT_COMPAT - && (longopts == NULL - || argv[optind][0] != '+' || argv[optind][1] == '\0') -#endif /* GETOPT_COMPAT */ - ) - optind++; - last_nonopt = optind; - } - - /* Special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - /* If we have done all the ARGV-elements, stop the scan and back over any non-options that we skipped and permuted. */ @@ -377,18 +162,8 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) /* If we have come to a non-option and did not permute it, either stop the scan or describe it to the caller and pass it by. */ - if ((argv[optind][0] != '-' || argv[optind][1] == '\0') -#ifdef GETOPT_COMPAT - && (longopts == NULL - || argv[optind][0] != '+' || argv[optind][1] == '\0') -#endif /* GETOPT_COMPAT */ - ) - { - if (ordering == REQUIRE_ORDER) - return EOF; - optarg = argv[optind++]; - return 1; - } + if ((argv[optind][0] != '-' || argv[optind][1] == '\0')) + return EOF; /* We have found another option-ARGV-element. Start decoding its characters. */ @@ -399,11 +174,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) if (longopts != NULL && ((argv[optind][0] == '-' - && (argv[optind][1] == '-' || long_only)) -#ifdef GETOPT_COMPAT - || argv[optind][0] == '+' -#endif /* GETOPT_COMPAT */ - )) + && (argv[optind][1] == '-' || long_only)))) { const struct option *p; char *s = nextchar; @@ -506,10 +277,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) option, then it's an error. Otherwise interpret it as a short option. */ if (!long_only || argv[optind][1] == '-' -#ifdef GETOPT_COMPAT - || argv[optind][0] == '+' -#endif /* GETOPT_COMPAT */ - || my_index (optstring, *nextchar) == NULL) + || strchr (optstring, *nextchar) == NULL) { if (opterr) { @@ -532,7 +300,7 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) { char c = *nextchar++; - char *temp = my_index (optstring, c); + char *temp = strchr (optstring, c); /* Increment `optind' when we start to process its last character. */ if (*nextchar == '\0') @@ -593,85 +361,16 @@ _getopt_internal (argc, argv, optstring, longopts, longind, long_only) } int -getopt (argc, argv, optstring) - int argc; - char *const *argv; - const char *optstring; +getopt (int argc, char *const *argv, char const *optstring) { return _getopt_internal (argc, argv, optstring, (const struct option *) 0, (int *) 0, 0); } - -#ifdef TEST - -/* Compile with -DTEST to make an executable for use in testing - the above definition of `getopt'. */ int -main (argc, argv) - int argc; - char **argv; +getopt_long (int argc, char *const *argv, const char *options, struct option const *long_options, int *opt_index) { - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == EOF) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } - } - - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); - } - - exit (0); + return _getopt_internal (argc, argv, options, long_options, opt_index, 0); } - -#endif /* TEST */ diff --git a/mlibc/include/getopt.h b/mlibc/include/getopt.h new file mode 100644 index 00000000..85e4b50c --- /dev/null +++ b/mlibc/include/getopt.h @@ -0,0 +1,60 @@ +/* -*-comment-start: "//";comment-end:""-*- + * Mes --- Maxwell Equations of Software + * Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. + * Copyright © 2017 Jan Nieuwenhuizen + * + * This file is part of Mes. + * + * Mes is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * Mes is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Mes. If not, see . + */ +#ifndef __MES_GETOPT_H +#define __MES_GETOPT_H 1 + +#if __GNUC__ && POSIX +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#undef __MES_GETOPT_H +#include_next + +#else // ! (__GNUC__ && POSIX) +#include +int isdigit (int); +int isxdigit (int); +#endif // ! (__GNUC__ && POSIX) + +char *optarg; +int optind; +int opterr; +struct option +{ + char const *name; + int has_arg; + int *flag; + int val; +}; + +enum _argtype +{ + no_argument, + required_argument, + optional_argument +}; + +int getopt (int argc, char *const *argv, char const *shortopts); +int getopt_long (int argc, char *const *argv, char const *shortopts, + struct option const *longopts, int *longind); + +#endif // __MES_GETOPT_H + diff --git a/mlibc/libc-gcc+tcc.c b/mlibc/libc-gcc+tcc.c index d6ed603b..18ac36dc 100644 --- a/mlibc/libc-gcc+tcc.c +++ b/mlibc/libc-gcc+tcc.c @@ -20,6 +20,7 @@ #include #include +#include int errno; diff --git a/mlibc/libc-mes+tcc.c b/mlibc/libc-mes+tcc.c index 5aff1360..087253a2 100644 --- a/mlibc/libc-mes+tcc.c +++ b/mlibc/libc-mes+tcc.c @@ -31,6 +31,7 @@ #if !__GNUC__ && !__TINYC__ #include +#include int errno;