Path: utzoo!telly!philmtl!uunet!tut.cis.ohio-state.edu!uunet.uu.net!rwthinf!norbert%rwthi3 From: rwthinf!norbert%rwthi3@uunet.uu.net (Norbert Kiesel) Newsgroups: gnu.utils.bug Subject: (none) Message-ID: <8911241605.AA02268@rwthi3.informatik.rwth-aachen.de> Date: 24 Nov 89 16:05:50 GMT Sender: daemon@tut.cis.ohio-state.edu Distribution: gnu Organization: GNUs Not Usenet Lines: 670 The follwing patch to DIFF-1.7 adds a -v option for printing the version number and gives a better usage message. It's not perfect, but better than no documentation at all. so long Norbert *** Makefile~ Fri Nov 24 16:07:17 1989 --- Makefile Fri Nov 24 16:07:18 1989 *************** *** 35,43 **** # All source files srcs=diff.c analyze.c io.c context.c ed.c normal.c util.c dir.c diff.h \ ! regex.c regex.h limits.h diff3.c # Object files for diff only. ! objs=diff.o analyze.o io.o context.o ed.o normal.o util.o dir.o regex.o tapefiles = $(srcs) README diagmeet.note Makefile COPYING all: diff diff3 --- 35,44 ---- # All source files srcs=diff.c analyze.c io.c context.c ed.c normal.c util.c dir.c diff.h \ ! regex.c regex.h limits.h diff3.c version.c getopt.c # Object files for diff only. ! objs=diff.o analyze.o io.o context.o ed.o normal.o util.o dir.o regex.o\ ! version.o getopt.o tapefiles = $(srcs) README diagmeet.note Makefile COPYING all: diff diff3 *** diff.c~ Fri Nov 24 16:07:18 1989 --- diff.c Fri Nov 24 16:07:18 1989 *************** *** 76,81 **** --- 76,82 ---- extern int optind; extern char *optarg; + extern char *version_string; program = argv[0]; *************** *** 103,111 **** msg_chain_end = NULL; no_discards = 0; /* Decode the options. */ ! while ((c = getopt (argc, argv, "0123456789abBcC:defF:hHiI:lnNprsS:tTw")) != EOF) { switch (c) --- 104,113 ---- msg_chain_end = NULL; no_discards = 0; + /* Decode the options. */ ! while ((c = getopt (argc, argv, "v0123456789abBcC:defF:hHiI:lnNprsS:tTw")) != EOF) { switch (c) *************** *** 266,275 **** --- 268,328 ---- tab_align_flag = 1; break; + case 'v': + /* Print version number and exit. */ + printf("%s",version_string); + exit(0); + break; + case 'w': /* Ignore horizontal whitespace when comparing lines. */ ignore_all_space_flag = 1; length_varies = 1; + break; + + case '?': + /* Give a list of all possible options and exit */ + printf("%s",version_string); + printf("-[0-9]+\tSpecify context length.\n"); + printf("-a\tTreat all files as text files; never treat as binary.\n"); + printf("-b\tIgnore changes in amount of whitespace.\n"); + printf("-B\tIgnore changes affecting only blank lines.\n"); + printf("-c\tMake context-style output.\n"); + printf("-C\tDon't discard lines. This makes things slower (sometimes much\ + \n\tslower) but will find a guaranteed minimal set of changes.\n"); + printf("-e\tMake output that is a valid `ed' script.\n"); + printf("-f\tMake output that looks vaguely like an `ed' script\ + \n\tbut has changes in the order they appear in the file.\n"); + printf("-F\tShow, for each set of changes, the previous line that\ + \n\tmatches the specified regexp. Currently affects only\ + \n\tcontext-style output.\n"); + printf("-h\tSplit the files into chunks of around 1500 lines\ + \n\tfor faster processing. Usually does not change the result.\ + \n\tThis currently has no effect.\n"); + printf("-H\tTurn on heuristics that speed processing of large files\ + \n\twith a small density of changes.\n"); + printf("-i\tIgnore changes in case.\n"); + printf("-I\tIgnore changes affecting only lines that match the\ + \n\tspecified regexp.\n"); + printf("-l\tPass the output through `pr' to paginate it.\n"); + printf("-n\tOutput RCS-style diffs, like `-f' except that each command\ + \n\tspecifies the number of lines affected.\n"); + printf("-N\tWhen comparing directories, if a file appears only in one\ + \n\tdirectory, treat it as present but empty in the other.\n"); + printf("-p\tMake context-style output and show name of last C function.\n"); + printf("-r\tWhen comparing directories, \ + \n\trecursively compare any subdirectories found.\n"); + printf("-s\tPrint a message if the files are the same.\n"); + printf("-S\tWhen comparing directories, start with the specified\ + \n\tfile name. This is used for resuming an aborted comparison.\n"); + printf("-t\tExpand tabs to spaces in the output so that it preserves\ + \n\tthe alignment of the input files.\n"); + printf("-T\tUse a tab in the output, rather than a space, before the\ + \n\ttext of an input line, so as to keep the proper alignment\ + \n\tin the input line without changing the characters in it.\n"); + printf("-v\tPrint version number and exit.\n"); + printf("-w\tIgnore horizontal whitespace when comparing lines.\n"); + exit(0); break; } prev = c; *** /dev/null Fri Nov 24 15:00:58 1989 --- version.c Fri Nov 24 16:07:18 1989 *************** *** 0 **** --- 1,23 ---- + /* GNU DIFF main routine. + Copyright (C) 1988, 1989 Free Software Foundation, Inc. + + This file is part of GNU DIFF. + + GNU DIFF 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 1, or (at your option) + any later version. + + GNU DIFF 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 GNU DIFF; see the file COPYING. If not, write to + the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + + /* GNU DIFF was written by Mike Haertel, David Hayes, + Richard Stallman and Len Tower. */ + + char *version_string="GNU Diff version 1.7\n"; *** /dev/null Fri Nov 24 15:00:58 1989 --- getopt.c Fri Nov 24 16:07:18 1989 *************** *** 0 **** --- 1,489 ---- + /* Getopt for GNU. + Copyright (C) 1987, 1989 Free Software Foundation, Inc. + + 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 + the Free Software Foundation; either version 1, or (at your option) + any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + + + + /* 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 _POSIX_OPTION_ORDER 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 + + /* If compiled with GNU C, use the built-in alloca */ + #ifdef __GNUC__ + #define alloca __builtin_alloca + #else /* not __GNUC__ */ + #ifdef sparc + #include + #endif + #endif /* not __GNUC__ */ + + #ifdef USG + #define bcopy(s, d, l) memcpy((d), (s), (l)) + #define index strchr + #endif + + /* 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. */ + + char *optarg = 0; + + /* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + + int optind = 0; + + /* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + + static char *nextchar; + + /* Callers store zero here to inhibit the error message + for unrecognized options. */ + + int opterr = 1; + + /* Describe how to deal with options that follow non-option ARGV-elements. + + UNSPECIFIED means the caller did not specify anything; + the default is then REQUIRE_ORDER if the environment variable + _OPTIONS_FIRST 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. + + PERMUTE is the default. We permute the contents of `argv' as we scan, + so that eventually all the 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 zero. + Using `-' as the first character of the list of option characters + requests 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; + + /* Describe the long-named options requested by the application. + _GETOPT_LONG_OPTIONS is a vector of `struct option' terminated by an + element containing a name which is zero. + The field `has_arg' is 1 if the option takes an argument, + 2 if it takes an optional argument. */ + + struct option + { + char *name; + int has_arg; + int *flag; + int val; + }; + + struct option *_getopt_long_options; + + /* Name of long-named option actually found. */ + + char *_getopt_option_name = '\0'; + + int option_index = 0; + + /* Handle permutation of arguments. */ + + /* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + + 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. */ + + bcopy (&argv[first_nonopt], temp, nonopts_size); + bcopy (&argv[last_nonopt], &argv[first_nonopt], + (optind - last_nonopt) * sizeof (char *)); + 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. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of theoption characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + A colon in OPTSTRING means that the previous character is an option + that wants an argument. The argument is taken from the rest of the + current ARGV-element, or from the following ARGV-element, + and returned in `optarg'. + + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg'. + + If OPTSTRING starts with `-', it requests a different method of handling the + non-option ARGV-elements. See the comments about RETURN_IN_ORDER, above. */ + + int + getopt (argc, argv, optstring) + int argc; + char **argv; + char *optstring; + { + optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (optind == 0) + { + first_nonopt = last_nonopt = optind = 1; + + nextchar = 0; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + ordering = RETURN_IN_ORDER; + else if (getenv ("_POSIX_OPTION_ORDER") != 0) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } + + if (nextchar == 0 || *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 (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) + && (argv[optind][0] != '+' + || argv[optind][1] == 0)) + 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 (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. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* 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) + && (argv[optind][0] != '+' || argv[optind][1] == 0)) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 0; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = argv[optind] + 1; + } + + if (_getopt_long_options != 0 && argv[optind][0] == '+') { + struct option *p; + char *s = nextchar; + while (*s && *s != '=') s++; + + for (p = _getopt_long_options, option_index = 0; p->name; + p++, option_index++) { + + if (!strncmp (p->name, nextchar, s - nextchar)) + { + optind++; + if (*s) + { + if (p->has_arg > 0) + optarg = s + 1; + else { + fprintf (stderr, "%s: option +%s doesn't allow an argument\n", + argv[0], p->name); + nextchar += strlen (nextchar); + return '?'; + } + } + else if (p->has_arg) + { + if (optind + 1 < argc) + optarg = argv[optind++]; + else if (p->has_arg != 2) { + fprintf (stderr, "%s: option +%s requires an argument\n", + argv[0], p->name); + nextchar += strlen (nextchar); + return '?'; + } + } + _getopt_option_name = p->name; + nextchar += strlen (nextchar); + if (p->flag) + *(p->flag) = p->val; + return 0; + } + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = (char *) index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == 0) + optind++; + + if (temp == 0 || c == ':') + { + if (opterr != 0) + { + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", + argv[0], c); + } + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != 0) + { + optarg = nextchar; + optind++; + } + else + optarg = 0; + nextchar = 0; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != 0) + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr != 0) + fprintf (stderr, "%s: no argument for `-%c' option\n", + argv[0], c); + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = 0; + } + } + return c; + } + } + + #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; + { + char c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind; + if ((c = getopt (argc, argv, "abc:d:0123456789")) == 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"); + } + + return 0; + } + + #endif /* TEST */ ******************************************************************************* * Norbert Kiesel NN NN KK KK * * Institut fuer Informatik III NNN NN KK KK * * RWTH Aachen NN N NN KK KK * * NN N NN KKKK * * Tel.: (0241) 80-7266 NN N NN KKKK * * NN N NN KK KK * * EUNET: norbert@rwthi3.uucp NN N NN KK KK * * ...!mcvax!unido!rwthi3!norbert NN NNN KK KK * *******************************************************************************