From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Mon, 2 Sep 2019 13:46:59 +0900 Subject: Initial commit --- web/glasgow/lit2x-0.16/grasp-utils/Jmakefile | 6 + web/glasgow/lit2x-0.16/grasp-utils/Makefile.BOOT | 58 + web/glasgow/lit2x-0.16/grasp-utils/PATCHLEVEL | 1 + web/glasgow/lit2x-0.16/grasp-utils/README | 48 + web/glasgow/lit2x-0.16/grasp-utils/etags/Jmakefile | 5 + web/glasgow/lit2x-0.16/grasp-utils/etags/README | 2 + web/glasgow/lit2x-0.16/grasp-utils/etags/etags.c | 1757 ++++++++++++++++++++ web/glasgow/lit2x-0.16/grasp-utils/etags/jbw-fixes | 568 +++++++ .../lit2x-0.16/grasp-utils/etags/wells-fixes | 545 ++++++ web/glasgow/lit2x-0.16/grasp-utils/msub/Jmakefile | 7 + web/glasgow/lit2x-0.16/grasp-utils/msub/msub.c | 520 ++++++ web/glasgow/lit2x-0.16/grasp-utils/msub/msub.ms | 128 ++ .../lit2x-0.16/grasp-utils/msub/test.makefile | 18 + .../lit2x-0.16/grasp-utils/msub/test.stdout | 11 + web/glasgow/lit2x-0.16/grasp-utils/msub/testfile | 11 + .../lit2x-0.16/grasp-utils/perl-4.035-fixes | 180 ++ .../lit2x-0.16/grasp-utils/scripts/Jmakefile | 79 + .../lit2x-0.16/grasp-utils/scripts/fastmake.prl | 126 ++ .../lit2x-0.16/grasp-utils/scripts/lmake.sh | 2 + web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.c | 217 +++ .../lit2x-0.16/grasp-utils/scripts/lndir.man | 61 + .../lit2x-0.16/grasp-utils/scripts/lndir.sh | 85 + web/glasgow/lit2x-0.16/grasp-utils/scripts/ltx.prl | 215 +++ web/glasgow/lit2x-0.16/grasp-utils/scripts/m5.prl | 502 ++++++ .../lit2x-0.16/grasp-utils/scripts/mkdependC.prl | 186 +++ .../lit2x-0.16/grasp-utils/scripts/mkdirhier.man | 15 + .../lit2x-0.16/grasp-utils/scripts/mkdirhier.sh | 24 + .../lit2x-0.16/grasp-utils/scripts/mkshadowfile.sh | 26 + .../lit2x-0.16/grasp-utils/scripts/moan-if-old.prl | 49 + .../lit2x-0.16/grasp-utils/scripts/perltags.prl | 69 + .../lit2x-0.16/grasp-utils/scripts/runstdtest.prl | 184 ++ .../lit2x-0.16/grasp-utils/scripts/zap-if-same.prl | 50 + .../lit2x-0.16/grasp-utils/verbatim/Jmakefile | 4 + .../lit2x-0.16/grasp-utils/verbatim/verbatim.c | 533 ++++++ .../lit2x-0.16/grasp-utils/verbatim/verbatim.lex | 57 + 35 files changed, 6349 insertions(+) create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/Jmakefile create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/Makefile.BOOT create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/PATCHLEVEL create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/README create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/etags/Jmakefile create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/etags/README create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/etags/etags.c create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/etags/jbw-fixes create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/etags/wells-fixes create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/msub/Jmakefile create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/msub/msub.c create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/msub/msub.ms create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/msub/test.makefile create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/msub/test.stdout create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/msub/testfile create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/perl-4.035-fixes create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/Jmakefile create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/fastmake.prl create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/lmake.sh create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.c create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.man create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.sh create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/ltx.prl create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/m5.prl create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdependC.prl create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.man create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.sh create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/mkshadowfile.sh create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/moan-if-old.prl create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/perltags.prl create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/runstdtest.prl create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/scripts/zap-if-same.prl create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/verbatim/Jmakefile create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.c create mode 100644 web/glasgow/lit2x-0.16/grasp-utils/verbatim/verbatim.lex (limited to 'web/glasgow/lit2x-0.16/grasp-utils') diff --git a/web/glasgow/lit2x-0.16/grasp-utils/Jmakefile b/web/glasgow/lit2x-0.16/grasp-utils/Jmakefile new file mode 100644 index 0000000000..96625e3d52 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/Jmakefile @@ -0,0 +1,6 @@ +#define IHaveSubdirs + +SUBDIRS = scripts \ + msub \ + etags \ + verbatim diff --git a/web/glasgow/lit2x-0.16/grasp-utils/Makefile.BOOT b/web/glasgow/lit2x-0.16/grasp-utils/Makefile.BOOT new file mode 100644 index 0000000000..16179c7df1 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/Makefile.BOOT @@ -0,0 +1,58 @@ +# hand-hacked Makefile to boot the "make world" process +#--------------------------------------------------------------------- + +# Platform-specific configuration stuff was read from: sun.cf + +SHELL = /bin/sh +PATHSEP = / + +TOP = .. +CURRENT_DIR = ./grasp-utils + +RM=rm -f +MV=mv -f +BOOTSTRAPCFLAGS = + +# Project identification -- name, version, and stuff + +PROJECTNAME = Booting the Make World System +PROJECTVERSION = none +PROJECTLABEL = none +SETUPLABEL = std + +PROJECTCONFIGDIR = + +########################################################################### +# Configuration stuff (jmake, its friends and templates) + +JMKMF = jmkmf_used_only_with_installed_utils +JRESTOREDEPS = $(JMAKESRC)/jrestoredeps +JMAKE = $(JMAKESRC)/jmake +JMAKE_DEFINES = + +JMAKESRC = $(TOP)/mkworld + +JMAKE_CMD = $(NEWTOP)$(JMAKE) -I$(NEWTOP)$(JMAKESRC) $(BOOTSTRAPCFLAGS) -DTopDir=$(TOP) -DCurDir=$(CURRENT_DIR) $(BOOT_DEFINES) + +########################################################################### + +Makefile:: $(JMAKE) + +$(JMAKE): + @(cd $(JMAKESRC); if [ -f Makefile ]; then \ + echo "checking $@ in $(JMAKESRC) first..."; $(MAKE) all; else \ + echo "bootstrapping $@ from Makefile.BOOT in $(JMAKESRC) first..."; \ + $(MAKE) -f Makefile.BOOT BOOTSTRAPCFLAGS=$(BOOTSTRAPCFLAGS); fi; \ + echo "okay, continuing in $(CURRENT_DIR)") + +Makefile:: + -@if [ -f Makefile ]; then \ + echo " $(RM) Makefile.bak; $(MV) Makefile Makefile.bak"; \ + $(RM) Makefile.bak; $(MV) Makefile Makefile.bak; \ + else exit 0; fi + $(JMAKE_CMD) + $(JRESTOREDEPS) + @if cmp -s Makefile Makefile.bak; then $(RM) Makefile.bak ; fi + @chmod 444 Makefile + @echo ==== The new Makefile is for\: ==== + @$(MAKE) whoami diff --git a/web/glasgow/lit2x-0.16/grasp-utils/PATCHLEVEL b/web/glasgow/lit2x-0.16/grasp-utils/PATCHLEVEL new file mode 100644 index 0000000000..9667fc05ed --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/PATCHLEVEL @@ -0,0 +1 @@ +Miscellaneous GRASP-project tools, version 0.16, patchlevel 0 diff --git a/web/glasgow/lit2x-0.16/grasp-utils/README b/web/glasgow/lit2x-0.16/grasp-utils/README new file mode 100644 index 0000000000..a98feebe81 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/README @@ -0,0 +1,48 @@ +This directory tree's worth of stuff are utility bits that are used in +more than one of our GRASP projects. (For the project-specific bits, +try /utils/.) + +msub/ a utility from Paul DuBois, that lets you substitute + for make variables (e.g., $(CC) ) in any old document. + Given that, with the "make world" configuration + system, Makefiles have loads of useful config info in + them, this is the program used to sneak that info into + other files. + +ugen/ A utility from the LML-compiler distrib to support + poor man's abstract data types for C. Used in the + parser ($(TOP)/parsers/hsp). + +scripts/ little utility scripts + + lndir from X imake stuff (via DuBois); make a shadow tree + of symbolic links + mkdirhier "mkdir a/b/c/d" will do "mkdir a; mkdir a/b; ..." + (assuming none of those dirs exist) + + runstdtest runs a pgm with some flags & some stdin; checks for an + expected exit code, expected stdout, and expected + stderr. (Expect this to change :-) + + newer "newer a b" (obsolete?) exit code 0 if file "a" newer + than "b", or something like that... + + tidycpp, hscpp cpp (C pre-processor) wrappers, the latter for + Haskell, the former obsolete? + + mkdependC script version of C makedepend (from X11R4 via DuBois) + mkdependHS "make depend" (perl) script for Haskell code. + + mkdependLML simon's makedepend1 script (needs work to function here) + (NOT BUILT) + + fastmake a "make" wrapper for compiling Haskell programs; + essentially, strips out the "make depend"ed + dependencies to avoid so much re-checking. + + update_iface a REALLY HORRIBLE hack, for updating the new Haskell + compiler's interface files; covers for deficiencies in + "nhc" (prototype compiler) i/face handling. + + ltx a "latex" wrapper. Re-runs latex/bibtex/makeindex + enough times to "do the right thing." diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/Jmakefile b/web/glasgow/lit2x-0.16/grasp-utils/etags/Jmakefile new file mode 100644 index 0000000000..cadc4636d6 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/Jmakefile @@ -0,0 +1,5 @@ +BuildPgmFromOneCFile(etags) + +InstallBinaryTarget(etags,$(INSTBINDIR)) + +CDependTarget( $(SRCS_C) ) diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/README b/web/glasgow/lit2x-0.16/grasp-utils/etags/README new file mode 100644 index 0000000000..fb033eabe1 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/README @@ -0,0 +1,2 @@ +This is the "etags" program from the GNU emacs (18.??) distribution. +Kevin Hammond has hacked it slightly to recognise more kinds of files. diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/etags.c b/web/glasgow/lit2x-0.16/grasp-utils/etags/etags.c new file mode 100644 index 0000000000..5abb1990a1 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/etags.c @@ -0,0 +1,1757 @@ +/* Tags file maker to go with GNUmacs + Copyright (C) 1984, 1987, 1988 Free Software Foundation, Inc. and Ken Arnold + + NO WARRANTY + + BECAUSE THIS PROGRAM IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY +NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICABLE STATE LAW. EXCEPT +WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, +RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE THIS PROGRAM "AS IS" +WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, +BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY +AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE +DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR +CORRECTION. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. +STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY +WHO MAY MODIFY AND REDISTRIBUTE THIS PROGRAM AS PERMITTED BELOW, BE +LIABLE TO YOU FOR DAMAGES, INCLUDING ANY LOST PROFITS, LOST MONIES, OR +OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR +DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR +A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) THIS +PROGRAM, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. + + GENERAL PUBLIC LICENSE TO COPY + + 1. You may copy and distribute verbatim copies of this source file +as you receive it, in any medium, provided that you conspicuously +and appropriately publish on each copy a valid copyright notice +"Copyright (C) 1986 Free Software Foundation"; and include +following the copyright notice a verbatim copy of the above disclaimer +of warranty and of this License. + + 2. You may modify your copy or copies of this source file or +any portion of it, and copy and distribute such modifications under +the terms of Paragraph 1 above, provided that you also do the following: + + a) cause the modified files to carry prominent notices stating + that you changed the files and the date of any change; and + + b) cause the whole of any work that you distribute or publish, + that in whole or in part contains or is a derivative of this + program or any part thereof, to be licensed at no charge to all + third parties on terms identical to those contained in this + License Agreement (except that you may choose to grant more extensive + warranty protection to some or all third parties, at your option). + + c) You may charge a distribution fee for the physical act of + transferring a copy, and you may at your option offer warranty + protection in exchange for a fee. + +Mere aggregation of another unrelated program with this program (or its +derivative) on a volume of a storage or distribution medium does not bring +the other program under the scope of these terms. + + 3. You may copy and distribute this program (or a portion or derivative +of it, under Paragraph 2) in object code or executable form under the terms +of Paragraphs 1 and 2 above provided that you also do one of the following: + + a) accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of + Paragraphs 1 and 2 above; or, + + b) accompany it with a written offer, valid for at least three + years, to give any third party free (except for a nominal + shipping charge) a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of + Paragraphs 1 and 2 above; or, + + c) accompany it with the information you received as to where the + corresponding source code may be obtained. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form alone.) + +For an executable file, complete source code means all the source code for +all modules it contains; but, as a special exception, it need not include +source code for modules which are standard libraries that accompany the +operating system on which the executable file runs. + + 4. You may not copy, sublicense, distribute or transfer this program +except as expressly provided under this License Agreement. Any attempt +otherwise to copy, sublicense, distribute or transfer this program is void and +your rights to use the program under this License agreement shall be +automatically terminated. However, parties who have received computer +software programs from you with this License Agreement will not have +their licenses terminated so long as such parties remain in full compliance. + +In other words, you are welcome to use, share and improve this program. +You are forbidden to forbid anyone else to use, share and improve +what you give them. Help stamp out software-hoarding! */ + +#include +#include + +/* Define the symbol ETAGS to make the program "etags", + which makes emacs-style tag tables by default. + Define CTAGS to make the program "ctags" compatible with the usual one. + Define neither one to get behavior that depends + on the name with which the program is invoked + (but we don't normally compile it that way). */ + +/* On VMS, CTAGS is not useful, so always do ETAGS. */ +#ifdef VMS +#ifndef ETAGS +#define ETAGS +#endif +#endif + +/* Exit codes for success and failure. */ + +#ifdef VMS +#define GOOD (1) +#define BAD (0) +#else +#define GOOD (0) +#define BAD (1) +#endif + +#define reg register +#define logical char + +#define TRUE (1) +#define FALSE (0) + +#define iswhite(arg) (_wht[arg]) /* T if char is white */ +#define begtoken(arg) (_btk[arg]) /* T if char can start token */ +#define intoken(arg) (_itk[arg]) /* T if char can be in token */ +#define endtoken(arg) (_etk[arg]) /* T if char ends tokens */ +#define isgood(arg) (_gd[arg]) /* T if char can be after ')' */ + +#define max(I1,I2) (I1 > I2 ? I1 : I2) + +/* cause token checking for typedef, struct, union, enum to distinguish + keywords from identifier-prefixes (e.g. struct vs struct_tag). */ +#define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len)))) + +struct nd_st { /* sorting structure */ + char *name; /* function or type name */ + char *file; /* file name */ + logical f; /* use pattern or line no */ + int lno; /* line number tag is on */ + long cno; /* character number line starts on */ + char *pat; /* search pattern */ + logical been_warned; /* set if noticed dup */ + struct nd_st *left,*right; /* left and right sons */ +}; + +long ftell(); +typedef struct nd_st NODE; + +int number; /* tokens found so far on line starting with # (including #) */ +logical gotone, /* found a func already on line */ + /* boolean "func" (see init) */ + _wht[0177],_etk[0177],_itk[0177],_btk[0177],_gd[0177]; + + /* typedefs are recognized using a simple finite automata, + * tydef is its state variable. + */ +typedef enum {none, begin, tag_ok, middle, end } TYST; + +TYST tydef = none; + +char searchar = '/'; /* use /.../ searches */ + +int lineno; /* line number of current line */ +long charno; /* current character number */ +long linecharno; /* character number of start of line */ + +char *curfile, /* current input file name */ + *outfile= 0, /* output file */ + *white = " \f\t\n", /* white chars */ + *endtk = " \t\n\"'#()[]{}=-+%*/&|^~!<>;,.:?", + /* token ending chars */ + *begtk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$", + /* token starting chars */ + *intk = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz$0123456789", + /* valid in-token chars */ + *notgd = ",;"; /* non-valid after-function chars */ + +int file_num = 0; /* current file number */ +int aflag = 0; /* -a: append to tags */ +int tflag = 0; /* -t: create tags for typedefs */ +int uflag = 0; /* -u: update tags */ +int wflag = 0; /* -w: suppress warnings */ +int vflag = 0; /* -v: create vgrind style index output */ +int xflag = 0; /* -x: create cxref style output */ +int eflag = 0; /* -e: emacs style output */ + +/* Name this program was invoked with. */ +char *progname; + +FILE *inf, /* ioptr for current input file */ + *outf; /* ioptr for tags file */ + +NODE *head; /* the head of the sorted binary tree */ + +char *savestr(); +char *savenstr (); +char *rindex(); +char *index(); +char *concat (); +void initbuffer (); +long readline (); + +/* A `struct linebuffer' is a structure which holds a line of text. + `readline' reads a line from a stream into a linebuffer + and works regardless of the length of the line. */ + +struct linebuffer + { + long size; + char *buffer; + }; + +struct linebuffer lb, lb1; + +#if 0 /* VMS now provides the `system' function. */ +#ifdef VMS + +#include + +void +system (buf) + char *buf; +{ + struct dsc$descriptor_s command = + { + strlen(buf), DSC$K_DTYPE_T, DSC$K_CLASS_S, buf + }; + + LIB$SPAWN(&command); +} +#endif /* VMS */ +#endif /* 0 */ + +main(ac,av) + int ac; + char *av[]; +{ + char cmd[100]; + int i; + int fflag = 0; + char *this_file; +#ifdef VMS + char got_err; + + extern char *gfnames(); + extern char *massage_name(); +#endif + + progname = av[0]; + +#ifdef ETAGS + eflag = 1; +#else +#ifdef CTAGS + eflag = 0; +#else + { + char *subname = rindex (progname, '/'); + if (subname++ == NULL) + subname = progname; + eflag = ! strcmp(subname, "ctags"); + } +#endif +#endif + + while (ac > 1 && av[1][0] == '-') + { + for (i=1; av[1][i]; i++) + { + switch(av[1][i]) + { +#ifndef VMS /* These options are useful only with ctags, + and VMS can't input them, so just omit them. */ + case 'B': + searchar='?'; + eflag = 0; + break; + case 'F': + searchar='/'; + eflag = 0; + break; +#endif + case 'a': + aflag++; + break; + case 'e': + eflag++; + break; + case 'f': + if (fflag > 0) + { + fprintf(stderr, + "%s: -f flag may only be given once\n", progname); + goto usage; + } + fflag++, ac--; av++; + if (ac <= 1 || av[1][0] == '\0') + { + fprintf(stderr, + "%s: -f flag must be followed by a filename\n", + progname); + goto usage; + } + outfile = av[1]; + goto end_loop; + case 't': + tflag++; + break; +#ifndef VMS + case 'u': + uflag++; + eflag = 0; + break; +#endif + case 'w': + wflag++; + break; + case 'v': + vflag++; + xflag++; + eflag = 0; + break; + case 'x': + xflag++; + eflag = 0; + break; + default: + goto usage; + } + } + end_loop: ; + ac--; av++; + } + + if (ac <= 1) + { + usage: +#ifdef VMS + fprintf (stderr, "Usage: %s [-aetwvx] [-f outfile] file ...\n", progname); +#else + fprintf (stderr, "Usage: %s [-BFaetuwvx] [-f outfile] file ...\n", progname); +#endif + exit(BAD); + } + + if (outfile == 0) + { + outfile = eflag ? "TAGS" : "tags"; + } + + init(); /* set up boolean "functions" */ + + initbuffer (&lb); + initbuffer (&lb1); + /* + * loop through files finding functions + */ + if (eflag) + { + outf = fopen (outfile, aflag ? "a" : "w"); + if (!outf) + { + fprintf (stderr, "%s: ", progname); + perror (outfile); + exit (BAD); + } + } + + file_num = 1; +#ifdef VMS + for (ac--, av++; + (this_file = gfnames (&ac, &av, &got_err)) != NULL; file_num++) + { + if (got_err) + { + error("Can't find file %s\n", this_file); + ac--, av++; + } + else + { + this_file = massage_name (this_file); +#else + for (; file_num < ac; file_num++) + { + this_file = av[file_num]; + if (1) + { +#endif + find_entries (this_file); + if (eflag) + { + fprintf (outf, "\f\n%s,%d\n", + this_file, total_size_of_entries (head)); + put_entries (head); + free_tree (head); + head = NULL; + } + } + } + + if (eflag) + { + fclose (outf); + exit (GOOD); + } + + if (xflag) + { + put_entries(head); + exit(GOOD); + } + if (uflag) + { + for (i=1; i%s;rm OTAGS", + outfile, av[i], outfile); + system(cmd); + } + aflag++; + } + outf = fopen(outfile, aflag ? "a" : "w"); + if (outf == NULL) + { + fprintf (stderr, "%s: ", outfile); + perror(outfile); + exit(BAD); + } + put_entries(head); + fclose(outf); +#ifndef VMS + if (uflag) + { + sprintf(cmd, "sort %s -o %s", outfile, outfile); + system(cmd); + } +#endif + exit(GOOD); +} + +/* + * This routine sets up the boolean psuedo-functions which work + * by seting boolean flags dependent upon the corresponding character + * Every char which is NOT in that string is not a white char. Therefore, + * all of the array "_wht" is set to FALSE, and then the elements + * subscripted by the chars in "white" are set to TRUE. Thus "_wht" + * of a char is TRUE if it is the string "white", else FALSE. + */ +init() +{ + + reg char *sp; + reg int i; + + for (i = 0; i < 0177; i++) + { + _wht[i] = _etk[i] = _itk[i] = _btk[i] = FALSE; + _gd[i] = TRUE; + } + for (sp = white; *sp; sp++) + _wht[*sp] = TRUE; + for (sp = endtk; *sp; sp++) + _etk[*sp] = TRUE; + for (sp = intk; *sp; sp++) + _itk[*sp] = TRUE; + for (sp = begtk; *sp; sp++) + _btk[*sp] = TRUE; + for (sp = notgd; *sp; sp++) + _gd[*sp] = FALSE; + _wht[0] = _wht['\n']; + _etk[0] = _etk['\n']; + _btk[0] = _btk['\n']; + _itk[0] = _itk['\n']; + _gd[0] = _gd['\n']; +} + +/* + * This routine opens the specified file and calls the function + * which finds the function and type definitions. + */ +find_entries (file) + char *file; +{ + char *cp; + + if ((inf=fopen(file,"r")) == NULL) + { + fprintf (stderr, "%s: ", progname); + perror(file); + return; + } + curfile = savestr(file); + cp = rindex(file, '.'); + /* .tex, .aux or .bbl implies LaTeX source code */ + if (cp && (!strcmp (cp + 1, "tex") || !strcmp (cp + 1, "aux") + || !strcmp (cp + 1, "bbl"))) + { + TEX_funcs(inf); + fclose(inf); + return; + } + /* .l or .el or .lisp (or .cl or .clisp or ...) implies lisp source code */ + if (cp && (!strcmp (cp + 1, "l") || + !strcmp (cp + 1, "el") || + !strcmp (cp + 1, "lsp") || + !strcmp (cp + 1, "lisp") || + !strcmp (cp + 1, "cl") || + !strcmp (cp + 1, "clisp"))) + { + L_funcs(inf); + fclose(inf); + return; + } + /* .scm or .sm or .scheme implies scheme source code */ + if (cp && (!strcmp (cp + 1, "sm") + || !strcmp (cp + 1, "scm") + || !strcmp (cp + 1, "scheme") + || !strcmp (cp + 1, "t") + || !strcmp (cp + 1, "sch") + || !strcmp (cp + 1, "SM") + || !strcmp (cp + 1, "SCM") + /* The `SCM' or `scm' prefix with a version number */ + || (cp[-1] == 'm' && cp[-2] == 'c' && cp[-3] == 's') + || (cp[-1] == 'M' && cp[-2] == 'C' && cp[-3] == 'S'))) + { + Scheme_funcs(inf); + fclose(inf); + return; + } + /* .M implies Mcode source code */ + if (cp && !strcmp (cp + 1, "M")) + { + Mcode_funcs(inf); + fclose(inf); + return; + } + + /* if not a .c or .h or .y file, try fortran */ + if (cp && (cp[1] != 'c' && cp[1] != 'h' && cp[1] != 'y') + && cp[2] == '\0') + { + if (PF_funcs(inf) != 0) + { + fclose(inf); + return; + } + rewind(inf); /* no fortran tags found, try C */ + } + C_entries(); + fclose(inf); +} + +/* Record a tag on the current line. + name is the tag name, + f is nonzero to use a pattern, zero to use line number instead. */ + +pfnote (name, f, linestart, linelen, lno, cno) + char *name; + logical f; /* f == TRUE when function */ + char *linestart; + int linelen; + int lno; + long cno; +{ + register char *fp; + register NODE *np; + char *altname; + char tem[51]; + + if ((np = (NODE *) malloc (sizeof (NODE))) == NULL) + { + fprintf(stderr, "%s: too many entries to sort\n", progname); + put_entries(head); + free_tree(head); + head = NULL; + np = (NODE *) xmalloc(sizeof (NODE)); + } + /* Change name "main" to M. */ + if (!eflag && !xflag && !strcmp(name, "main")) + { + fp = rindex(curfile, '/'); + if (fp == 0) + fp = curfile; + else + fp++; + altname = concat ("M", fp, ""); + fp = rindex(altname, '.'); + if (fp && fp[2] == 0) + *fp = 0; + name = altname; + } + np->name = savestr(name); + np->file = curfile; + np->f = f; + np->lno = lno; + np->cno = cno; + np->left = np->right = 0; + if (eflag) + { + linestart[linelen] = 0; + } + else if (xflag == 0) + { + sprintf (tem, strlen (linestart) < 50 ? "%s$" : "%.50s", linestart); + linestart = tem; + } + np->pat = savestr (linestart); + if (head == NULL) + head = np; + else + add_node(np, head); +} + +free_tree(node) + NODE *node; +{ + while (node) + { + free_tree(node->right); + free(node); + node = node->left; + } +} + +add_node(node, cur_node) + NODE *node,*cur_node; +{ + register int dif; + + dif = strcmp(node->name, cur_node->name); + + /* If this tag name matches an existing one, then + unless -e was given, do not add the node, but maybe print a warning */ + if (!eflag && !dif) + { + if (node->file == cur_node->file) + { + if (!wflag) + { + fprintf(stderr,"%s: Duplicate entry in file %s, line %d: %s\n", + progname, node->file,lineno,node->name); + fprintf(stderr,"Second entry ignored\n"); + } + return; + } + if (!cur_node->been_warned) + if (!wflag) + fprintf(stderr,"%s: Duplicate entry in files %s and %s: %s (Warning only)\n", + progname, node->file, cur_node->file, node->name); + cur_node->been_warned = TRUE; + return; + } + + /* Actually add the node */ + if (dif < 0) + { + if (cur_node->left != NULL) + add_node(node,cur_node->left); + else + cur_node->left = node; + return; + } + if (cur_node->right != NULL) + add_node(node,cur_node->right); + else + cur_node->right = node; +} + +put_entries(node) + reg NODE *node; +{ + reg char *sp; + + if (node == NULL) + return; + + /* Output subentries that precede this one */ + put_entries (node->left); + + /* Output this entry */ + + if (eflag) + { + fprintf (outf, "%s%c%d,%d\n", + node->pat, 0177, node->lno, node->cno); + } + else if (!xflag) + { + fprintf (outf, "%s\t%s\t", + node->name, node->file); + + if (node->f) + { /* a function */ + putc (searchar, outf); + putc ('^', outf); + + for (sp = node->pat; *sp; sp++) + { + if (*sp == '\\' || *sp == searchar) + putc ('\\', outf); + putc (*sp, outf); + } + putc (searchar, outf); + } + else + { /* a typedef; text pattern inadequate */ + fprintf (outf, "%d", node->lno); + } + putc ('\n', outf); + } + else if (vflag) + fprintf (stdout, "%s %s %d\n", + node->name, node->file, (node->lno+63)/64); + else + fprintf (stdout, "%-16s%4d %-16s %s\n", + node->name, node->lno, node->file, node->pat); + + /* Output subentries that follow this one */ + put_entries (node->right); +} + +/* Return total number of characters that put_entries will output for + the nodes in the subtree of the specified node. + Works only if eflag is set, but called only in that case. */ + +total_size_of_entries(node) + reg NODE *node; +{ + reg int total = 0; + reg long num; + + if (node == NULL) + return 0; + + /* Count subentries that precede this one */ + total = total_size_of_entries (node->left); + + /* Count subentries that follow this one */ + total += total_size_of_entries (node->right); + + /* Count this entry */ + + total += strlen (node->pat) + 3; + + num = node->lno; + while (num) + { + total++; + num /= 10; + } + + num = node->cno; + if (!num) total++; + while (num) + { + total++; + num /= 10; + } + return total; +} + +/* + * This routine finds functions and typedefs in C syntax and adds them + * to the list. + */ +#ifdef VMS +long vmslinecharno; +#define VMS_SET_LINECHARNO (vmslinecharno = ftell(inf)) +#else +#define VMS_SET_LINECHARNO +#endif + +#define CNL_SAVE_NUMBER \ +{ \ + VMS_SET_LINECHARNO; \ + linecharno = charno; lineno++; \ + charno += 1 + readline (&lb, inf); \ + lp = lb.buffer; \ +} + +#define CNL \ +{ \ + CNL_SAVE_NUMBER; \ + number = 0; \ +} + +C_entries () +{ + register int c; + register char *token, *tp, *lp; + logical incomm, inquote, inchar, midtoken; + int level; + char tok[BUFSIZ]; + + lineno = 0; + charno = 0; + lp = lb.buffer; + *lp = 0; + + number = 0; + gotone = midtoken = inquote = inchar = incomm = FALSE; + level = 0; + + while (!feof (inf)) + { + c = *lp++; + if (c == 0) + { + CNL; + gotone = FALSE; + } + if (c == '\\') + { + c = *lp++; + if (c == 0) + CNL_SAVE_NUMBER; + c = ' '; + } + else if (incomm) + { + if (c == '*') + { + while ((c = *lp++) == '*') + continue; + if (c == 0) + CNL; + if (c == '/') + incomm = FALSE; + } + } + else if (inquote) + { + /* + * Too dumb to know about \" not being magic, but + * they usually occur in pairs anyway. + */ + if (c == '"') + inquote = FALSE; + continue; + } + else if (inchar) + { + if (c == '\'') + inchar = FALSE; + continue; + } + else switch (c) + { + case '"': + inquote = TRUE; + continue; + case '\'': + inchar = TRUE; + continue; + case '/': + if (*lp == '*') + { + lp++; + incomm = TRUE; + } + continue; + case '#': + if (lp == lb.buffer + 1) + number = 1; + continue; + case '{': + if (tydef == tag_ok) + { + tydef=middle; + } + level++; + continue; + case '}': + if (lp == lb.buffer + 1) + level = 0; /* reset */ + else + level--; + if (!level && tydef==middle) + { + tydef=end; + } + continue; + } + if (!level && !inquote && !incomm && gotone == FALSE) + { + if (midtoken) + { + if (endtoken(c)) + { + int f; + char *buf = lb.buffer; + int endpos = lp - lb.buffer; + char *lp1 = lp; + int line = lineno; + long linestart = linecharno; +#ifdef VMS + long vmslinestart = vmslinecharno; +#endif + int tem = consider_token (&lp1, token, &f, level); + lp = lp1; + if (tem) + { + if (linestart != linecharno) + { +#ifdef VMS + getline (vmslinestart); +#else + getline (linestart); +#endif + strncpy (tok, token + (lb1.buffer - buf), + tp-token+1); + tok[tp-token+1] = 0; + pfnote(tok, f, lb1.buffer, endpos, line, linestart); + } + else + { + strncpy (tok, token, tp-token+1); + tok[tp-token+1] = 0; + pfnote(tok, f, lb.buffer, endpos, line, linestart); + } + gotone = f; /* function */ + } + midtoken = FALSE; + token = lp - 1; + } + else if (intoken(c)) + tp++; + } + else if (begtoken(c)) + { + token = tp = lp - 1; + midtoken = TRUE; + } + } + if (c == ';' && tydef==end) /* clean with typedefs */ + tydef=none; + } +} + +/* + * This routine checks to see if the current token is + * at the start of a function, or corresponds to a typedef + * It updates the input line * so that the '(' will be + * in it when it returns. + */ +consider_token (lpp, token, f, level) + char **lpp, *token; + int *f, level; +{ + reg char *lp = *lpp; + reg char c; + static logical next_token_is_func; + logical firsttok; /* T if have seen first token in ()'s */ + int bad, win; + + *f = 1; /* a function */ + c = lp[-1]; + bad = FALSE; + if (!number) + { /* space is not allowed in macro defs */ + while (iswhite(c)) + { + c = *lp++; + if (c == 0) + { + if (feof (inf)) + break; + CNL; + } + } + } + else + { + /* the following tries to make it so that a #define a b(c) */ + /* doesn't count as a define of b. */ + + number++; + if (number >= 4 || (number==2 && strncmp (token, "define", 6)==0)) + { + /* Force the next symbol to be recognised, even if it is #define a b(c)! */ + if(number == 2) next_token_is_func = 1; + else + gotone = TRUE; + badone: + bad = TRUE; + goto ret; + } + } + /* check for the typedef cases */ + if (tflag && istoken(token, "typedef", 7)) + { + tydef=begin; + goto badone; + } + if (tydef==begin && (istoken(token, "struct", 6) || + istoken(token, "union", 5) || istoken(token, "enum", 4))) + { + tydef=tag_ok; + goto badone; + } + if (tydef==tag_ok) + { + tydef=middle; + goto badone; + } + if (tydef==begin) /* e.g. typedef ->int<- */ + { + tydef=end; + goto badone; + } + if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */ + { + tydef=end; + } + if (tydef==end) + { + *f = 0; + win = 1; + goto ret; + } + /* Detect GNUmacs's function-defining macros. */ + if (!number && !strncmp (token, "DEF", 3)) + + { + next_token_is_func = 1; + goto badone; + } + if (next_token_is_func) + { + next_token_is_func = 0; + win = 1; + goto ret; + } + if (c != '(') + goto badone; + firsttok = FALSE; + while ((c = *lp++) != ')') + { + if (c == 0) + { + if (feof (inf)) + break; + CNL; + } + /* + * This line used to confuse ctags: + * int (*oldhup)(); + * This fixes it. A nonwhite char before the first + * token, other than a / (in case of a comment in there) + * makes this not a declaration. + */ + if (begtoken(c) || c=='/') firsttok++; + else if (!iswhite(c) && !firsttok) goto badone; + } + while (iswhite (c = *lp++)) + { + if (c == 0) + { + if (feof (inf)) + break; + CNL; + } + } + win = isgood (c); +ret: + *lpp = lp - 1; + return !bad && win; +} + +getline (atchar) + long atchar; +{ + long saveftell = ftell (inf); + + fseek (inf, atchar, 0); + readline (&lb1, inf); + fseek (inf, saveftell, 0); +} + +/* Fortran parsing */ + +char *dbp; +int pfcnt; + +PF_funcs(fi) + FILE *fi; +{ + lineno = 0; + charno = 0; + pfcnt = 0; + + while (!feof (fi)) + { + lineno++; + linecharno = charno; + charno += readline (&lb, fi) + 1; + dbp = lb.buffer; + if (*dbp == '%') dbp++ ; /* Ratfor escape to fortran */ + while (isspace(*dbp)) + dbp++; + if (*dbp == 0) + continue; + switch (*dbp |' ') + { + case 'i': + if (tail("integer")) + takeprec(); + break; + case 'r': + if (tail("real")) + takeprec(); + break; + case 'l': + if (tail("logical")) + takeprec(); + break; + case 'c': + if (tail("complex") || tail("character")) + takeprec(); + break; + case 'd': + if (tail("double")) + { + while (isspace(*dbp)) + dbp++; + if (*dbp == 0) + continue; + if (tail("precision")) + break; + continue; + } + break; + } + while (isspace(*dbp)) + dbp++; + if (*dbp == 0) + continue; + switch (*dbp|' ') + { + case 'f': + if (tail("function")) + getit(); + continue; + case 's': + if (tail("subroutine")) + getit(); + continue; + case 'p': + if (tail("program")) + { + getit(); + continue; + } + if (tail("procedure")) + getit(); + continue; + } + } + return (pfcnt); +} + +tail(cp) + char *cp; +{ + register int len = 0; + + while (*cp && (*cp&~' ') == ((*(dbp+len))&~' ')) + cp++, len++; + if (*cp == 0) + { + dbp += len; + return (1); + } + return (0); +} + +takeprec() +{ + while (isspace(*dbp)) + dbp++; + if (*dbp != '*') + return; + dbp++; + while (isspace(*dbp)) + dbp++; + if (!isdigit(*dbp)) + { + --dbp; /* force failure */ + return; + } + do + dbp++; + while (isdigit(*dbp)); +} + +getit() +{ + register char *cp; + char c; + char nambuf[BUFSIZ]; + + while (isspace(*dbp)) + dbp++; + if (*dbp == 0 || !isalpha(*dbp)) + return; + for (cp = dbp+1; *cp && (isalpha(*cp) || isdigit(*cp)); cp++) + continue; + c = cp[0]; + cp[0] = 0; + strcpy(nambuf, dbp); + cp[0] = c; + pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); + pfcnt++; +} + +/* + * lisp tag functions + * just look for (def or (DEF + */ + +L_funcs (fi) + FILE *fi; +{ + lineno = 0; + charno = 0; + pfcnt = 0; + + while (!feof (fi)) + { + lineno++; + linecharno = charno; + charno += readline (&lb, fi) + 1; + dbp = lb.buffer; + if (dbp[0] == '(' && + (dbp[1] == 'D' || dbp[1] == 'd') && + (dbp[2] == 'E' || dbp[2] == 'e') && + (dbp[3] == 'F' || dbp[3] == 'f')) + { + while (!isspace(*dbp)) dbp++; + while (isspace(*dbp)) dbp++; + L_getit(); + } + } +} + +L_getit() +{ + register char *cp; + char c; + char nambuf[BUFSIZ]; + + if (*dbp == 0) return; + for (cp = dbp+1; *cp && *cp != '(' && *cp != ' '; cp++) + continue; + c = cp[0]; + cp[0] = 0; + strcpy(nambuf, dbp); + cp[0] = c; + pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); + pfcnt++; +} + +/* + * Scheme tag functions + * look for (def... xyzzy + * look for (def... (xyzzy + * look for (def ... ((...(xyzzy .... + * look for (set! xyzzy + */ + +static get_scheme (); +Scheme_funcs (fi) + FILE *fi; +{ + lineno = 0; + charno = 0; + pfcnt = 0; + + while (!feof (fi)) + { + lineno++; + linecharno = charno; + charno += readline (&lb, fi) + 1; + dbp = lb.buffer; + if (dbp[0] == '(' && + (dbp[1] == 'D' || dbp[1] == 'd') && + (dbp[2] == 'E' || dbp[2] == 'e') && + (dbp[3] == 'F' || dbp[3] == 'f')) + { + while (!isspace(*dbp)) dbp++; + /* Skip over open parens and white space */ + while (*dbp && (isspace(*dbp) || *dbp == '(')) dbp++; + get_scheme (); + } + if (dbp[0] == '(' && + (dbp[1] == 'S' || dbp[1] == 's') && + (dbp[2] == 'E' || dbp[2] == 'e') && + (dbp[3] == 'T' || dbp[3] == 't') && + (dbp[4] == '!' || dbp[4] == '!') && + (isspace(dbp[5]))) + { + while (!isspace(*dbp)) dbp++; + /* Skip over white space */ + while (isspace(*dbp)) dbp++; + get_scheme (); + } + } +} + +static +get_scheme() +{ + register char *cp; + char c; + char nambuf[BUFSIZ]; + + if (*dbp == 0) return; + /* Go till you get to white space or a syntactic break */ + for (cp = dbp+1; *cp && *cp != '(' && *cp != ')' && !isspace(*cp); cp++) + continue; + /* Null terminate the string there. */ + c = cp[0]; + cp[0] = 0; + /* Copy the string */ + strcpy(nambuf, dbp); + /* Unterminate the string */ + cp[0] = c; + /* Announce the change */ + pfnote(nambuf, TRUE, lb.buffer, cp - lb.buffer + 1, lineno, linecharno); + pfcnt++; +} +static get_mcode (); +Mcode_funcs (fi) + FILE *fi; +{ + lineno = 0; + charno = 0; + pfcnt = 0; + + while (!feof (fi)) + { + lineno++; + linecharno = charno; + charno += readline (&lb, fi) + 1; + dbp = lb.buffer; + + while (*dbp != 0) + { + /* Skip over white space */ + while (isspace(*dbp)) dbp++; + get_mcode(); + } + } +} + +static +get_mcode() +{ + register char *cp; + char c; + char nambuf[BUFSIZ]; + + if (*dbp == 0) return; + /* Go till you get to white space or a syntactic break */ + for (cp = dbp; *cp && *cp != ':' && *cp != ';' && !isspace(*cp); cp++) + continue; + + if(*cp == ':') + { + /* Null terminate the string there. */ + c = cp[0]; + cp[0] = 0; + /* Copy the string */ + strcpy(nambuf, dbp); + /* Unterminate the string */ + cp[0] = c; + /* Announce the change */ + pfnote(nambuf, TRUE, lb.buffer, strlen(lb.buffer), lineno, linecharno); + pfcnt++; + *dbp = 0; + } + if (*cp == ';') + *dbp = 0; + else + dbp = cp; +} + +/* Find tags in TeX and LaTeX input files. */ + +/* TEX_toktab is a table of TeX control sequences that define tags. + Each TEX_tabent records one such control sequence. */ + +struct TEX_tabent +{ + char *name; + int len; +}; + +struct TEX_tabent *TEX_toktab = NULL; /* Table with tag tokens */ + +/* Default set of control sequences to put into TEX_toktab. + The value of environment var TEXTAGS is prepended to this. */ + +static char *TEX_defenv = + ":chapter:section:subsection:subsubsection:eqno:label:ref:cite:bibitem:typeout"; + +struct TEX_tabent *TEX_decode_env (); + +static char TEX_esc = '\\'; +static char TEX_opgrp = '{'; +static char TEX_clgrp = '}'; + +/* + * TeX/LaTeX scanning loop. + */ + +TEX_funcs (fi) + FILE *fi; +{ + char *lasthit; + + lineno = 0; + charno = 0; + pfcnt = 0; + + /* Select either \ or ! as escape character. */ + TEX_mode (fi); + + /* Initialize token table once from environment. */ + if (!TEX_toktab) + TEX_toktab = TEX_decode_env ("TEXTAGS", TEX_defenv); + + while (!feof (fi)) + { + lineno++; + linecharno = charno; + charno += readline (&lb, fi) + 1; + dbp = lb.buffer; + lasthit = dbp; + + while (!feof (fi)) + { /* Scan each line in file */ + lineno++; + linecharno = charno; + charno += readline (&lb, fi) + 1; + dbp = lb.buffer; + lasthit = dbp; + while (dbp = index (dbp, TEX_esc)) /* Look at each escape in line */ + { + register int i; + + if (! *(++dbp)) + break; + linecharno += dbp - lasthit; + lasthit = dbp; + i = TEX_Token (lasthit); + if (0 <= i) + { + TEX_getit (lasthit, TEX_toktab[i].len); + break; /* We only save a line once */ + } + } + } + } +} + +#define TEX_LESC '\\' +#define TEX_SESC '!' + +/* Figure out whether TeX's escapechar is '\\' or '!' and set grouping */ +/* chars accordingly. */ + +TEX_mode (f) + FILE *f; +{ + int c; + + while ((c = getc (f)) != EOF) + if (c == TEX_LESC || c == TEX_SESC) + break; + + if (c == TEX_LESC) + { + TEX_esc = TEX_LESC; + TEX_opgrp = '{'; + TEX_clgrp = '}'; + } + else + { + TEX_esc = TEX_SESC; + TEX_opgrp = '<'; + TEX_clgrp = '>'; + } + rewind (f); +} + +/* Read environment and prepend it to the default string. */ +/* Build token table. */ + +struct TEX_tabent * +TEX_decode_env (evarname, defenv) + char *evarname; + char *defenv; +{ + register char *env, *p; + extern char *savenstr (), *index (); + + struct TEX_tabent *tab; + int size, i; + + /* Append deafult string to environment. */ + env = (char *) getenv (evarname); + if (!env) + env = defenv; + else + env = concat (env, defenv, ""); + + /* Allocate a token table */ + for (size = 1, p=env; p;) + if ((p = index (p, ':')) && *(++p)) + size++; + tab = (struct TEX_tabent *) xmalloc (size * sizeof (struct TEX_tabent)); + + /* Unpack environment string into token table. Be careful about */ + /* zero-length strings (leading ':', "::" and trailing ':') */ + for (i = 0; *env;) + { + p = index (env, ':'); + if (!p) /* End of environment string. */ + p = env + strlen (env); + if (p - env > 0) + { /* Only non-zero strings. */ + tab[i].name = savenstr (env, p - env); + tab[i].len = strlen (tab[i].name); + i++; + } + if (*p) + env = p + 1; + else + { + tab[i].name = NULL; /* Mark end of table. */ + tab[i].len = 0; + break; + } + } + return tab; +} + +/* Record a tag defined by a TeX command of length LEN and starting at NAME. + The name being defined actually starts at (NAME + LEN + 1). + But we seem to include the TeX command in the tag name. */ + +TEX_getit (name, len) + char *name; + int len; +{ + char *p = name + len; + char nambuf[BUFSIZ]; + + if (*name == 0) return; + + /* Let tag name extend to next group close (or end of line) */ + while (*p && *p != TEX_clgrp) + p++; + strncpy (nambuf, name, p - name); + nambuf[p - name] = 0; + + pfnote (nambuf, TRUE, lb.buffer, strlen (lb.buffer), lineno, linecharno); + pfcnt++; +} + +/* If the text at CP matches one of the tag-defining TeX command names, + return the index of that command in TEX_toktab. + Otherwise return -1. */ + +/* Keep the capital `T' in `Token' for dumb truncating compilers + (this distinguishes it from `TEX_toktab' */ +TEX_Token (cp) + char *cp; +{ + int i; + + for (i = 0; TEX_toktab[i].len > 0; i++) + if (strncmp (TEX_toktab[i].name, cp, TEX_toktab[i].len) == 0) + return i; + return -1; +} + +/* Initialize a linebuffer for use */ + +void +initbuffer (linebuffer) + struct linebuffer *linebuffer; +{ + linebuffer->size = 200; + linebuffer->buffer = (char *) xmalloc (200); +} + +/* Read a line of text from `stream' into `linebuffer'. + Return the length of the line. */ + +long +readline (linebuffer, stream) + struct linebuffer *linebuffer; + register FILE *stream; +{ + char *buffer = linebuffer->buffer; + register char *p = linebuffer->buffer; + register char *pend = p + linebuffer->size; + + while (1) + { + int c = getc (stream); + if (p == pend) + { + linebuffer->size *= 2; + buffer = (char *) xrealloc (buffer, linebuffer->size); + p += buffer - linebuffer->buffer; + pend = buffer + linebuffer->size; + linebuffer->buffer = buffer; + } + if (c < 0 || c == '\n') + { + *p = 0; + break; + } + *p++ = c; + } + + return p - buffer; +} + +char * +savestr(cp) + char *cp; +{ + return savenstr (cp, strlen (cp)); +} + +char * +savenstr(cp, len) + char *cp; + int len; +{ + register char *dp; + + dp = (char *) xmalloc (len + 1); + strncpy (dp, cp, len); + dp[len] = '\0'; + return dp; +} + +/* + * Return the ptr in sp at which the character c last + * appears; NULL if not found + * + * Identical to v7 rindex, included for portability. + */ + +char * +rindex(sp, c) + register char *sp, c; +{ + register char *r; + + r = NULL; + do + { + if (*sp == c) + r = sp; + } while (*sp++); + return(r); +} + +/* + * Return the ptr in sp at which the character c first + * appears; NULL if not found + * + * Identical to v7 index, included for portability. + */ + +char * +index(sp, c) + register char *sp, c; +{ + do + { + if (*sp == c) + return (sp); + } while (*sp++); + return (NULL); +} + +/* Print error message and exit. */ + +fatal (s1, s2) + char *s1, *s2; +{ + error (s1, s2); + exit (BAD); +} + +/* Print error message. `s1' is printf control string, `s2' is arg for it. */ + +error (s1, s2) + char *s1, *s2; +{ + fprintf (stderr, "%s: ", progname); + fprintf (stderr, s1, s2); + fprintf (stderr, "\n"); +} + +/* Return a newly-allocated string whose contents concatenate those of s1, s2, s3. */ + +char * +concat (s1, s2, s3) + char *s1, *s2, *s3; +{ + int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3); + char *result = (char *) xmalloc (len1 + len2 + len3 + 1); + + strcpy (result, s1); + strcpy (result + len1, s2); + strcpy (result + len1 + len2, s3); + *(result + len1 + len2 + len3) = 0; + + return result; +} + +/* Like malloc but get fatal error if memory is exhausted. */ + +int +xmalloc (size) + int size; +{ + int result = malloc (size); + if (!result) + fatal ("virtual memory exhausted", 0); + return result; +} + +int +xrealloc (ptr, size) + char *ptr; + int size; +{ + int result = realloc (ptr, size); + if (!result) + fatal ("virtual memory exhausted"); + return result; +} diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/jbw-fixes b/web/glasgow/lit2x-0.16/grasp-utils/etags/jbw-fixes new file mode 100644 index 0000000000..324c0d447e --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/jbw-fixes @@ -0,0 +1,568 @@ +From jbw@bigbird.bu.edu Tue Aug 18 08:07:53 1992 +From: jbw@bigbird.bu.edu (Joe Wells) +Newsgroups: comp.emacs +Subject: Re: How do I include symbols defined with #define in TAGS ? +Date: 16 Aug 92 23:27:25 GMT +Distribution: comp.emacs +Organization: Boston University Computer Science Department +In-reply-to: podi@ESD.3Com.COM's message of 14 Aug 92 17:53:29 GMT + +In article podi@ESD.3Com.COM (Podibanda Kuruppu) writes: + + Keywords: Symbols defined by #defines in TAGS + + I would greatly appreciate it if someone could tell me if I could + include symbols ( defined in .h files with #defines ) in a TAG file. + +Enclosed below is an earlier article with my solution to this. + +-- +Enjoy, + +Joe Wells +Member of the League for Programming Freedom --- send e-mail for details + +---------------------------------------------------------------------- +Date: Sat, 4 Apr 92 00:46:52 -0500 +From: jbw@bigbird.bu.edu (Joe Wells) +Message-Id: <9204040546.AA15208@bigbird.bu.edu> +To: bug-gnu-emacs@prep.ai.mit.edu +Subject: numerous bug fixes for etags + +Enclosed is a patch with numerous changes for etags. The following are +the changes and bugs fixed: + +1. Improvement: don't waste time calling strncmp (with "struct", "union", + "enum", "typedef") if the lengths are different. + +2. Bug: pfnote placed a NUL in the line buffer after the tag token which caused + things like `{' or `/*' to be ignored, thus severely screwing up the + parser. Or it did something horrible, I don't remember for sure. + +3. Improvement: record defining occurrences of struct/union/enum tags. + This works even if combined with a typedef definition, for example: + + typedef struct XXX { + ..... + } YYY; + +4. Bug: when a tag token was the last item on the line before the newline + character, garbage would be seen as the token. This is because when a + NUL was seen in the buffer the buffer was replaced with the next line. + +5. Bug: tag tokens immediately followed by a `{' with no intervening space + were not recorded. This was only a problem because of improvement 3 + above. + +6. Bug: a newline in the middle of a comment zeroed the `number' variable. + (Just for good measure I made it not zero `number' in strings even when + the newline is not preceded by `\', in case someone wants to run etags + on illegal code :-) (`number' is used only on lines that begin with + `#'.) + +7. Bug: handling of #define lines was severely broken. I don't actually + remember what etags did with them, but it was really bad. It now + records macro definitions. + +8. Bug: when a tag token was the last item on the line except for + whitespace, etags would replace the contents of the line buffer and + then later do various string comparisons and inspections against + garbage values instead of against the token. Fixing this required + copying the token into a buffer. (This is roughly the same as bug 4 + above, but in a different function.) + +9. Bug: when a tag token was the last item on the line before the newline + (and under various other circumstances), etags would skip over the NUL + in the buffer and skip to the first non-whitespace character in the + buffer. + +10. Improvement (possibly bug fix): parse typedefs even when we aren't + going to print them out. I seem to remember that this fixed some bug, + but I don't remember the specific case that would trigger the bug. + +11. An unfinished attempt to detect and record global variable + definitions. + +The changes are to the 18.57 version of etags, but the only change in +18.58 to the C code handling is to initialize some variables when starting +on a new file, so these changes are orthogonal. + +-- +Enjoy, + +Joe Wells + +Member of the League for Programming Freedom --- send e-mail for details + +---------------------------------------------------------------------- +--- etags.c-dist Tue Jan 8 14:08:38 1991 ++++ etags.c Sat Apr 4 00:41:22 1992 +@@ -62,7 +62,10 @@ + + /* cause token checking for typedef, struct, union, enum to distinguish + keywords from identifier-prefixes (e.g. struct vs struct_tag). */ +-#define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len)))) ++#define istoken(s, t, len) \ ++ (((len) == (sizeof (t) -1)) && \ ++ ((strncmp(s, t, len)) == 0) && \ ++ (endtoken(*((s)+(len))))) + + struct nd_st { /* sorting structure */ + char *name; /* function or type name */ +@@ -505,6 +508,7 @@ + { + register char *fp; + register NODE *np; ++ char save; + char *altname; + char tem[51]; + +@@ -538,6 +542,7 @@ + np->left = np->right = 0; + if (eflag) + { ++ save = linestart[linelen]; + linestart[linelen] = 0; + } + else if (xflag == 0) +@@ -546,6 +551,7 @@ + linestart = tem; + } + np->pat = savestr (linestart); ++ linestart[linelen] = save; + if (head == NULL) + head = np; + else +@@ -725,6 +731,17 @@ + number = 0; \ + } + ++/* These two are part of a never-finished attempt to record global */ ++/* variable definitions. This is nearly impossible in C without the full */ ++/* power of a C compiler due to C's stupid grammar. */ ++logical infunc; ++int idents_in_decl; ++ ++/* indicates whether the next token (if any) is the tag corresponding to */ ++/* `struct', `union', or `enum' */ ++logical next_token_is_tag; ++ ++ + C_entries () + { + register int c; +@@ -731,6 +748,15 @@ + register char *token, *tp, *lp; + logical incomm, inquote, inchar, midtoken; + int level; ++ ++ /* there are certain things that must be done when the end of line is */ ++ /* encountered, but they must be delayed until after other things are */ ++ /* done. */ ++ logical new_line_flag; ++ ++ /* same as new_line_flag for left braces. */ ++ logical left_brace_flag; ++ + char tok[BUFSIZ]; + + lineno = 0; +@@ -739,17 +765,22 @@ + *lp = 0; + + number = 0; +- gotone = midtoken = inquote = inchar = incomm = FALSE; ++ gotone = midtoken = inquote = inchar = incomm = infunc = FALSE; ++ new_line_flag = FALSE; ++ left_brace_flag = FALSE; + level = 0; ++ idents_in_decl = 0; ++ next_token_is_tag = FALSE; + + while (!feof (inf)) + { + c = *lp++; + if (c == 0) +- { +- CNL; +- gotone = FALSE; +- } ++ new_line_flag = TRUE; ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "E: c: [%c], lp[-2]: [%c]\n", c, lp[-2]); ++#endif /* DEBUG */ + if (c == '\\') + { + c = *lp++; +@@ -756,15 +787,18 @@ + if (c == 0) + CNL_SAVE_NUMBER; + c = ' '; ++ /* is this correct? I thought escaped newlines disappeared even */ ++ /* before the token breaker got to see things. */ + } + else if (incomm) + { ++ new_line_flag = FALSE; + if (c == '*') + { + while ((c = *lp++) == '*') + continue; + if (c == 0) +- CNL; ++ CNL_SAVE_NUMBER; + if (c == '/') + incomm = FALSE; + } +@@ -771,6 +805,7 @@ + } + else if (inquote) + { ++ new_line_flag = FALSE; + /* + * Too dumb to know about \" not being magic, but + * they usually occur in pairs anyway. +@@ -781,6 +816,7 @@ + } + else if (inchar) + { ++ new_line_flag = FALSE; + if (c == '\'') + inchar = FALSE; + continue; +@@ -809,8 +845,8 @@ + { + tydef=middle; + } +- level++; +- continue; ++ left_brace_flag = TRUE; ++ break; + case '}': + if (lp == lb.buffer + 1) + level = 0; /* reset */ +@@ -820,8 +856,17 @@ + { + tydef=end; + } ++ if (level == 0 && infunc) ++ { ++ idents_in_decl = 0; ++ infunc = FALSE; ++ } + continue; + } ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "D: c: [%c], lp[-2]: [%c]\n", c, lp[-2]); ++#endif /* DEBUG */ + if (!level && !inquote && !incomm && gotone == FALSE) + { + if (midtoken) +@@ -852,6 +897,11 @@ + tp-token+1); + tok[tp-token+1] = 0; + pfnote(tok, f, lb1.buffer, endpos, line, linestart); ++#ifdef DEBUG ++ fprintf (stderr, ++ "f: %d, infunc %d, tok: %s\nlb1.buffer: %s\n", ++ f, infunc, tok, lb1.buffer); ++#endif /* DEBUG */ + } + else + { +@@ -858,8 +908,15 @@ + strncpy (tok, token, tp-token+1); + tok[tp-token+1] = 0; + pfnote(tok, f, lb.buffer, endpos, line, linestart); ++#ifdef DEBUG ++ fprintf (stderr, ++ "f: %d, infunc %d, tok: %s\nlb.buffer: %s\n", ++ f, infunc, tok, lb.buffer); ++#endif /* DEBUG */ + } + gotone = f; /* function */ ++ if (f) ++ infunc = TRUE; + } + midtoken = FALSE; + token = lp - 1; +@@ -873,8 +930,32 @@ + midtoken = TRUE; + } + } ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "F: c: [%c], lp[-2]: [%c]\n", c, lp[-2]); ++#endif /* DEBUG */ ++ if (left_brace_flag) ++ { ++ left_brace_flag = FALSE; ++ next_token_is_tag = FALSE; ++ level++; ++ } ++ if (new_line_flag) ++ { ++ new_line_flag = FALSE; ++ number = 0; ++ gotone = FALSE; ++ } ++ if (lp > lb.buffer && lp[-1] == 0) ++ CNL_SAVE_NUMBER; + if (c == ';' && tydef==end) /* clean with typedefs */ + tydef=none; ++ if (c == ';' && level == 0 && !infunc) ++ idents_in_decl = 0; ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "G: c: [%c], lp[-2]: [%c]\n", c, lp[-2]); ++#endif /* DEBUG */ + } + } + +@@ -891,70 +972,176 @@ + reg char *lp = *lpp; + reg char c; + static logical next_token_is_func; ++ ++ /* indicates that the next token will be a macro defined with #define */ ++ static logical next_token_is_macro; ++ + logical firsttok; /* T if have seen first token in ()'s */ +- int bad, win; ++ int bad = FALSE, win = FALSE; ++ int length = (lp - 1) - token; ++ ++ /* used to keep a copy of the token when we have to fill the line buffer */ ++ /* with the contents of the next line */ ++ static char *tok_buffer = NULL; ++ static long tok_buffer_size = 0; + + *f = 1; /* a function */ + c = lp[-1]; +- bad = FALSE; + if (!number) + { /* space is not allowed in macro defs */ +- while (iswhite(c)) ++ while ((c == 0) || iswhite(c)) + { +- c = *lp++; +- if (c == 0) ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "C: token: %s, c: [%c], lp - token: %d\n", ++ token, c, lp - token); ++#endif /* DEBUG */ ++ while (c == 0) + { + if (feof (inf)) +- break; ++ goto break_while_1; ++ if (token != tok_buffer) ++ { ++ if (length + 1 > tok_buffer_size) ++ if (tok_buffer_size == 0) ++ { ++ tok_buffer_size = length + 1; ++ tok_buffer = (char *) xmalloc (tok_buffer_size); ++ } ++ else ++ { ++ tok_buffer_size = length + 1; ++ tok_buffer = ++ (char *) xrealloc (tok_buffer, tok_buffer_size); ++ } ++ strncpy (tok_buffer, token, length); ++ tok_buffer[length] = '\0'; ++ token = tok_buffer; ++ } + CNL; ++ c = *lp++; + } ++ while ((c != 0) && iswhite(c)) ++ c = *lp++; + } +- /* the following tries to make it so that a #define a b(c) */ +- /* doesn't count as a define of b. */ ++ break_while_1: ++ ; + } + else + { ++ /* the following tries to make it so that a #define a b(c) */ ++ /* doesn't count as a define of b. */ + number++; +- if (number >= 4 || (number==2 && strncmp (token, "define", 6))) +- { +- gotone = TRUE; +- badone: ++#ifdef DEBUG ++ fprintf (stderr, "number: %d, n_t_i_m: %d, token: %s\n", ++ number, next_token_is_macro, token); ++#endif /* DEBUG */ ++ if (number == 2 && strncmp (token, "define", 6) == 0) ++ next_token_is_macro = TRUE; ++ else if (number == 3 && next_token_is_macro) ++ { ++ next_token_is_macro = FALSE; ++ while ((c != 0) && iswhite(c)) ++ { ++#ifdef DEBUG ++ fprintf (stderr, "c: %c, %d\n", c, c); ++#endif /* DEBUG */ ++ c = *lp++; ++ } ++#ifdef DEBUG ++ fprintf (stderr, "c: %c, %d\n", c, c); ++#endif /* DEBUG */ ++ if (c == 0) /* ignore plain "#define FLAG" */ + bad = TRUE; ++ else ++ win = TRUE; ++ /* speed up skipping the rest of this line */ ++ gotone = TRUE; ++ /* never treat a macro as a function, because it doesn't have a */ ++ /* function body, which is what "f" really stands for (now). */ ++ *f = FALSE; + goto ret; + } ++ else ++ /* speed up skipping the rest of this line */ ++ gotone = TRUE; ++ goto badone; + } ++ idents_in_decl ++; ++#ifdef DEBUG ++ fprintf (stderr, ++ "A: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n", ++ idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c, ++ length + 5, token); ++#endif /* DEBUG */ + /* check for the typedef cases */ +- if (tflag && istoken(token, "typedef", 7)) ++ if (istoken (token, "typedef", length)) + { + tydef=begin; + goto badone; + } +- if (tydef==begin && (istoken(token, "struct", 6) || +- istoken(token, "union", 5) || istoken(token, "enum", 4))) +- { ++#ifdef DEBUG ++ fprintf (stderr, "D\n"); ++#endif /* DEBUG */ ++ if (istoken (token, "struct", length) || ++ istoken (token, "union", length) || ++ istoken (token, "enum", length)) ++ { ++ next_token_is_tag = 1; ++#ifdef DEBUG ++ fprintf (stderr, "A: token: %s\n", token); ++#endif /* DEBUG */ ++ if (tydef == begin) + tydef=tag_ok; + goto badone; + } +- if (tydef==tag_ok) ++ else if (next_token_is_tag) + { ++#ifdef DEBUG ++ fprintf (stderr, "B: token: %s, c: [%c]\n", token, c); ++#endif /* DEBUG */ ++ if (tydef==tag_ok) + tydef=middle; +- goto badone; ++ next_token_is_tag = 0; ++ *f = 0; ++ /* only notice when a tag is being defined, not when it is merely */ ++ /* being used. */ ++ if (c == '{') ++ win = TRUE; ++ else ++ bad = TRUE; ++ goto ret; + } ++#ifdef DEBUG ++ fprintf (stderr, "E\n"); ++#endif /* DEBUG */ + if (tydef==begin) /* e.g. typedef ->int<- */ + { + tydef=end; + goto badone; + } ++#ifdef DEBUG ++ fprintf (stderr, "F\n"); ++#endif /* DEBUG */ + if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */ + { + tydef=end; + } ++#ifdef DEBUG ++ fprintf (stderr, "G\n"); ++#endif /* DEBUG */ + if (tydef==end) + { + *f = 0; +- win = 1; ++#ifdef DEBUG ++ fprintf (stderr, "C token: %s\n", token); ++#endif /* DEBUG */ ++ win = tflag; + goto ret; + } ++#ifdef DEBUG ++ fprintf (stderr, "H\n"); ++#endif /* DEBUG */ + /* Detect GNUmacs's function-defining macros. */ + if (!number && !strncmp (token, "DEF", 3)) + +@@ -962,6 +1149,9 @@ + next_token_is_func = 1; + goto badone; + } ++#ifdef DEBUG ++ fprintf (stderr, "I\n"); ++#endif /* DEBUG */ + if (next_token_is_func) + { + next_token_is_func = 0; +@@ -968,9 +1158,15 @@ + win = 1; + goto ret; + } ++#ifdef DEBUG ++ fprintf (stderr, "J\n"); ++#endif /* DEBUG */ + if (c != '(') + goto badone; + firsttok = FALSE; ++#ifdef DEBUG ++ fprintf (stderr, "K\n"); ++#endif /* DEBUG */ + while ((c = *lp++) != ')') + { + if (c == 0) +@@ -999,9 +1195,20 @@ + } + } + win = isgood (c); ++ + ret: ++#ifdef DEBUG ++ fprintf (stderr, ++ "B: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n", ++ idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c, ++ length + 5, token); ++#endif /* DEBUG */ + *lpp = lp - 1; + return !bad && win; ++ ++ badone: ++ bad = TRUE; ++ goto ret; + } + + getline (atchar) +---------------------------------------------------------------------- + diff --git a/web/glasgow/lit2x-0.16/grasp-utils/etags/wells-fixes b/web/glasgow/lit2x-0.16/grasp-utils/etags/wells-fixes new file mode 100644 index 0000000000..242e4e1002 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/etags/wells-fixes @@ -0,0 +1,545 @@ +From jbw@bigbird.bu.edu Sun Apr 5 14:58:19 1992 +From: jbw@bigbird.bu.edu (Joe Wells) +Newsgroups: gnu.emacs.bug +Subject: numerous bug fixes for etags +Date: 3 Apr 92 19:46:52 GMT +Distribution: gnu +Organization: GNUs Not Usenet + +Enclosed is a patch with numerous changes for etags. The following are +the changes and bugs fixed: + +1. Improvement: don't waste time calling strncmp (with "struct", "union", + "enum", "typedef") if the lengths are different. + +2. Bug: pfnote placed a NUL in the line buffer after the tag token which caused + things like `{' or `/*' to be ignored, thus severely screwing up the + parser. Or it did something horrible, I don't remember for sure. + +3. Improvement: record defining occurrences of struct/union/enum tags. + This works even if combined with a typedef definition, for example: + + typedef struct XXX { + ..... + } YYY; + +4. Bug: when a tag token was the last item on the line before the newline + character, garbage would be seen as the token. This is because when a + NUL was seen in the buffer the buffer was replaced with the next line. + +5. Bug: tag tokens immediately followed by a `{' with no intervening space + were not recorded. This was only a problem because of improvement 3 + above. + +6. Bug: a newline in the middle of a comment zeroed the `number' variable. + (Just for good measure I made it not zero `number' in strings even when + the newline is not preceded by `\', in case someone wants to run etags + on illegal code :-) (`number' is used only on lines that begin with + `#'.) + +7. Bug: handling of #define lines was severely broken. I don't actually + remember what etags did with them, but it was really bad. It now + records macro definitions. + +8. Bug: when a tag token was the last item on the line except for + whitespace, etags would replace the contents of the line buffer and + then later do various string comparisons and inspections against + garbage values instead of against the token. Fixing this required + copying the token into a buffer. (This is roughly the same as bug 4 + above, but in a different function.) + +9. Bug: when a tag token was the last item on the line before the newline + (and under various other circumstances), etags would skip over the NUL + in the buffer and skip to the first non-whitespace character in the + buffer. + +10. Improvement (possibly bug fix): parse typedefs even when we aren't + going to print them out. I seem to remember that this fixed some bug, + but I don't remember the specific case that would trigger the bug. + +11. An unfinished attempt to detect and record global variable + definitions. + +The changes are to the 18.57 version of etags, but the only change in +18.58 to the C code handling is to initialize some variables when starting +on a new file, so these changes are orthogonal. + +-- +Enjoy, + +Joe Wells + +Member of the League for Programming Freedom --- send e-mail for details + +---------------------------------------------------------------------- +--- etags.c-dist Tue Jan 8 14:08:38 1991 ++++ etags.c Sat Apr 4 00:41:22 1992 +@@ -62,7 +62,10 @@ + + /* cause token checking for typedef, struct, union, enum to distinguish + keywords from identifier-prefixes (e.g. struct vs struct_tag). */ +-#define istoken(s, tok, len) (!strncmp(s,tok,len) && endtoken(*((s)+(len)))) ++#define istoken(s, t, len) \ ++ (((len) == (sizeof (t) -1)) && \ ++ ((strncmp(s, t, len)) == 0) && \ ++ (endtoken(*((s)+(len))))) + + struct nd_st { /* sorting structure */ + char *name; /* function or type name */ +@@ -505,6 +508,7 @@ + { + register char *fp; + register NODE *np; ++ char save; + char *altname; + char tem[51]; + +@@ -538,6 +542,7 @@ + np->left = np->right = 0; + if (eflag) + { ++ save = linestart[linelen]; + linestart[linelen] = 0; + } + else if (xflag == 0) +@@ -546,6 +551,7 @@ + linestart = tem; + } + np->pat = savestr (linestart); ++ linestart[linelen] = save; + if (head == NULL) + head = np; + else +@@ -725,6 +731,17 @@ + number = 0; \ + } + ++/* These two are part of a never-finished attempt to record global */ ++/* variable definitions. This is nearly impossible in C without the full */ ++/* power of a C compiler due to C's stupid grammar. */ ++logical infunc; ++int idents_in_decl; ++ ++/* indicates whether the next token (if any) is the tag corresponding to */ ++/* `struct', `union', or `enum' */ ++logical next_token_is_tag; ++ ++ + C_entries () + { + register int c; +@@ -731,6 +748,15 @@ + register char *token, *tp, *lp; + logical incomm, inquote, inchar, midtoken; + int level; ++ ++ /* there are certain things that must be done when the end of line is */ ++ /* encountered, but they must be delayed until after other things are */ ++ /* done. */ ++ logical new_line_flag; ++ ++ /* same as new_line_flag for left braces. */ ++ logical left_brace_flag; ++ + char tok[BUFSIZ]; + + lineno = 0; +@@ -739,17 +765,22 @@ + *lp = 0; + + number = 0; +- gotone = midtoken = inquote = inchar = incomm = FALSE; ++ gotone = midtoken = inquote = inchar = incomm = infunc = FALSE; ++ new_line_flag = FALSE; ++ left_brace_flag = FALSE; + level = 0; ++ idents_in_decl = 0; ++ next_token_is_tag = FALSE; + + while (!feof (inf)) + { + c = *lp++; + if (c == 0) +- { +- CNL; +- gotone = FALSE; +- } ++ new_line_flag = TRUE; ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "E: c: [%c], lp[-2]: [%c]\n", c, lp[-2]); ++#endif /* DEBUG */ + if (c == '\\') + { + c = *lp++; +@@ -756,15 +787,18 @@ + if (c == 0) + CNL_SAVE_NUMBER; + c = ' '; ++ /* is this correct? I thought escaped newlines disappeared even */ ++ /* before the token breaker got to see things. */ + } + else if (incomm) + { ++ new_line_flag = FALSE; + if (c == '*') + { + while ((c = *lp++) == '*') + continue; + if (c == 0) +- CNL; ++ CNL_SAVE_NUMBER; + if (c == '/') + incomm = FALSE; + } +@@ -771,6 +805,7 @@ + } + else if (inquote) + { ++ new_line_flag = FALSE; + /* + * Too dumb to know about \" not being magic, but + * they usually occur in pairs anyway. +@@ -781,6 +816,7 @@ + } + else if (inchar) + { ++ new_line_flag = FALSE; + if (c == '\'') + inchar = FALSE; + continue; +@@ -809,8 +845,8 @@ + { + tydef=middle; + } +- level++; +- continue; ++ left_brace_flag = TRUE; ++ break; + case '}': + if (lp == lb.buffer + 1) + level = 0; /* reset */ +@@ -820,8 +856,17 @@ + { + tydef=end; + } ++ if (level == 0 && infunc) ++ { ++ idents_in_decl = 0; ++ infunc = FALSE; ++ } + continue; + } ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "D: c: [%c], lp[-2]: [%c]\n", c, lp[-2]); ++#endif /* DEBUG */ + if (!level && !inquote && !incomm && gotone == FALSE) + { + if (midtoken) +@@ -852,6 +897,11 @@ + tp-token+1); + tok[tp-token+1] = 0; + pfnote(tok, f, lb1.buffer, endpos, line, linestart); ++#ifdef DEBUG ++ fprintf (stderr, ++ "f: %d, infunc %d, tok: %s\nlb1.buffer: %s\n", ++ f, infunc, tok, lb1.buffer); ++#endif /* DEBUG */ + } + else + { +@@ -858,8 +908,15 @@ + strncpy (tok, token, tp-token+1); + tok[tp-token+1] = 0; + pfnote(tok, f, lb.buffer, endpos, line, linestart); ++#ifdef DEBUG ++ fprintf (stderr, ++ "f: %d, infunc %d, tok: %s\nlb.buffer: %s\n", ++ f, infunc, tok, lb.buffer); ++#endif /* DEBUG */ + } + gotone = f; /* function */ ++ if (f) ++ infunc = TRUE; + } + midtoken = FALSE; + token = lp - 1; +@@ -873,8 +930,32 @@ + midtoken = TRUE; + } + } ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "F: c: [%c], lp[-2]: [%c]\n", c, lp[-2]); ++#endif /* DEBUG */ ++ if (left_brace_flag) ++ { ++ left_brace_flag = FALSE; ++ next_token_is_tag = FALSE; ++ level++; ++ } ++ if (new_line_flag) ++ { ++ new_line_flag = FALSE; ++ number = 0; ++ gotone = FALSE; ++ } ++ if (lp > lb.buffer && lp[-1] == 0) ++ CNL_SAVE_NUMBER; + if (c == ';' && tydef==end) /* clean with typedefs */ + tydef=none; ++ if (c == ';' && level == 0 && !infunc) ++ idents_in_decl = 0; ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "G: c: [%c], lp[-2]: [%c]\n", c, lp[-2]); ++#endif /* DEBUG */ + } + } + +@@ -891,70 +972,176 @@ + reg char *lp = *lpp; + reg char c; + static logical next_token_is_func; ++ ++ /* indicates that the next token will be a macro defined with #define */ ++ static logical next_token_is_macro; ++ + logical firsttok; /* T if have seen first token in ()'s */ +- int bad, win; ++ int bad = FALSE, win = FALSE; ++ int length = (lp - 1) - token; ++ ++ /* used to keep a copy of the token when we have to fill the line buffer */ ++ /* with the contents of the next line */ ++ static char *tok_buffer = NULL; ++ static long tok_buffer_size = 0; + + *f = 1; /* a function */ + c = lp[-1]; +- bad = FALSE; + if (!number) + { /* space is not allowed in macro defs */ +- while (iswhite(c)) ++ while ((c == 0) || iswhite(c)) + { +- c = *lp++; +- if (c == 0) ++#ifdef DEBUG ++ if (next_token_is_tag) ++ fprintf (stderr, "C: token: %s, c: [%c], lp - token: %d\n", ++ token, c, lp - token); ++#endif /* DEBUG */ ++ while (c == 0) + { + if (feof (inf)) +- break; ++ goto break_while_1; ++ if (token != tok_buffer) ++ { ++ if (length + 1 > tok_buffer_size) ++ if (tok_buffer_size == 0) ++ { ++ tok_buffer_size = length + 1; ++ tok_buffer = (char *) xmalloc (tok_buffer_size); ++ } ++ else ++ { ++ tok_buffer_size = length + 1; ++ tok_buffer = ++ (char *) xrealloc (tok_buffer, tok_buffer_size); ++ } ++ strncpy (tok_buffer, token, length); ++ tok_buffer[length] = '\0'; ++ token = tok_buffer; ++ } + CNL; ++ c = *lp++; + } ++ while ((c != 0) && iswhite(c)) ++ c = *lp++; + } +- /* the following tries to make it so that a #define a b(c) */ +- /* doesn't count as a define of b. */ ++ break_while_1: ++ ; + } + else + { ++ /* the following tries to make it so that a #define a b(c) */ ++ /* doesn't count as a define of b. */ + number++; +- if (number >= 4 || (number==2 && strncmp (token, "define", 6))) +- { +- gotone = TRUE; +- badone: ++#ifdef DEBUG ++ fprintf (stderr, "number: %d, n_t_i_m: %d, token: %s\n", ++ number, next_token_is_macro, token); ++#endif /* DEBUG */ ++ if (number == 2 && strncmp (token, "define", 6) == 0) ++ next_token_is_macro = TRUE; ++ else if (number == 3 && next_token_is_macro) ++ { ++ next_token_is_macro = FALSE; ++ while ((c != 0) && iswhite(c)) ++ { ++#ifdef DEBUG ++ fprintf (stderr, "c: %c, %d\n", c, c); ++#endif /* DEBUG */ ++ c = *lp++; ++ } ++#ifdef DEBUG ++ fprintf (stderr, "c: %c, %d\n", c, c); ++#endif /* DEBUG */ ++ if (c == 0) /* ignore plain "#define FLAG" */ + bad = TRUE; ++ else ++ win = TRUE; ++ /* speed up skipping the rest of this line */ ++ gotone = TRUE; ++ /* never treat a macro as a function, because it doesn't have a */ ++ /* function body, which is what "f" really stands for (now). */ ++ *f = FALSE; + goto ret; + } ++ else ++ /* speed up skipping the rest of this line */ ++ gotone = TRUE; ++ goto badone; + } ++ idents_in_decl ++; ++#ifdef DEBUG ++ fprintf (stderr, ++ "A: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n", ++ idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c, ++ length + 5, token); ++#endif /* DEBUG */ + /* check for the typedef cases */ +- if (tflag && istoken(token, "typedef", 7)) ++ if (istoken (token, "typedef", length)) + { + tydef=begin; + goto badone; + } +- if (tydef==begin && (istoken(token, "struct", 6) || +- istoken(token, "union", 5) || istoken(token, "enum", 4))) +- { ++#ifdef DEBUG ++ fprintf (stderr, "D\n"); ++#endif /* DEBUG */ ++ if (istoken (token, "struct", length) || ++ istoken (token, "union", length) || ++ istoken (token, "enum", length)) ++ { ++ next_token_is_tag = 1; ++#ifdef DEBUG ++ fprintf (stderr, "A: token: %s\n", token); ++#endif /* DEBUG */ ++ if (tydef == begin) + tydef=tag_ok; + goto badone; + } +- if (tydef==tag_ok) ++ else if (next_token_is_tag) + { ++#ifdef DEBUG ++ fprintf (stderr, "B: token: %s, c: [%c]\n", token, c); ++#endif /* DEBUG */ ++ if (tydef==tag_ok) + tydef=middle; +- goto badone; ++ next_token_is_tag = 0; ++ *f = 0; ++ /* only notice when a tag is being defined, not when it is merely */ ++ /* being used. */ ++ if (c == '{') ++ win = TRUE; ++ else ++ bad = TRUE; ++ goto ret; + } ++#ifdef DEBUG ++ fprintf (stderr, "E\n"); ++#endif /* DEBUG */ + if (tydef==begin) /* e.g. typedef ->int<- */ + { + tydef=end; + goto badone; + } ++#ifdef DEBUG ++ fprintf (stderr, "F\n"); ++#endif /* DEBUG */ + if (tydef==middle && level == 0) /* e.g. typedef struct tag ->struct_t<- */ + { + tydef=end; + } ++#ifdef DEBUG ++ fprintf (stderr, "G\n"); ++#endif /* DEBUG */ + if (tydef==end) + { + *f = 0; +- win = 1; ++#ifdef DEBUG ++ fprintf (stderr, "C token: %s\n", token); ++#endif /* DEBUG */ ++ win = tflag; + goto ret; + } ++#ifdef DEBUG ++ fprintf (stderr, "H\n"); ++#endif /* DEBUG */ + /* Detect GNUmacs's function-defining macros. */ + if (!number && !strncmp (token, "DEF", 3)) + +@@ -962,6 +1149,9 @@ + next_token_is_func = 1; + goto badone; + } ++#ifdef DEBUG ++ fprintf (stderr, "I\n"); ++#endif /* DEBUG */ + if (next_token_is_func) + { + next_token_is_func = 0; +@@ -968,9 +1158,15 @@ + win = 1; + goto ret; + } ++#ifdef DEBUG ++ fprintf (stderr, "J\n"); ++#endif /* DEBUG */ + if (c != '(') + goto badone; + firsttok = FALSE; ++#ifdef DEBUG ++ fprintf (stderr, "K\n"); ++#endif /* DEBUG */ + while ((c = *lp++) != ')') + { + if (c == 0) +@@ -999,9 +1195,20 @@ + } + } + win = isgood (c); ++ + ret: ++#ifdef DEBUG ++ fprintf (stderr, ++ "B: iid: %d, tydef: %d, ntit: %d, ntif: %d, c: %c, token: %.*s\n", ++ idents_in_decl, tydef, next_token_is_tag, next_token_is_func, c, ++ length + 5, token); ++#endif /* DEBUG */ + *lpp = lp - 1; + return !bad && win; ++ ++ badone: ++ bad = TRUE; ++ goto ret; + } + + getline (atchar) +---------------------------------------------------------------------- + diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/Jmakefile b/web/glasgow/lit2x-0.16/grasp-utils/msub/Jmakefile new file mode 100644 index 0000000000..cc855bd99e --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/Jmakefile @@ -0,0 +1,7 @@ +BuildPgmFromOneCFile(msub) + +InstallBinaryTarget(msub,$(INSTBINDIR)) + +CDependTarget( $(SRCS_C) ) + +RunStdTest(msub001,msub,-f test.makefile testfile -o1 test.stdout) diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.c b/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.c new file mode 100644 index 0000000000..dccefa990f --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.c @@ -0,0 +1,520 @@ +/* + msub - Read file(s) and perform substitutions using values of + variables defined in makefile. + + Syntax: msub [-f makefile] [file ...] + + Multiple -f options may be given. + + 27 Mar 1990 Paul DuBois dubois@primate.wisc.edu + + 27 Mar 1990 V1.0. Created. +*/ + +# include +# include + + +# define true (1) +# define false (0) + + +extern char *calloc (), *strcpy (); + + +char *NewString(); + + +typedef struct Def Def; + +struct Def +{ + char *var; /* variable name */ + char *val; /* variable value */ + int simple; /* whether value has been expanded */ + Def *nextDef; /* next definition in list */ +}; + + +char *usage = "Usage: msub [ -f makefile ] file"; +char *makefile = NULL; +Def *defList = NULL; /* list of definitions */ +int nDefs = 0; /* number of definitions */ +int changes; + +main (argc, argv) +int argc; +char **argv; +{ +FILE *f; +Def *dp; +int i, pass; + + --argc; + ++argv; + + while (argc > 0 && argv[0][0] == '-') + { + if (strcmp (argv[0], "-f") == 0) + { + if (argc < 2) + panic (usage); + if ((f = fopen (makefile = argv[1], "r")) == NULL) + panic ("Can't open makefile"); + ReadMake (f); + fclose (f); + argc -= 2; + argv += 2; + } + else + panic (usage); /* bad flag */ + } + + if (makefile == NULL) /* no -f options given */ + { + if ((f = fopen ("makefile", "r")) == NULL) + { + if ((f = fopen ("Makefile", "r")) == NULL) + panic ("Can't open makefile"); + } + ReadMake (f); + fclose (f); + } + + EncodeEscapes (); + + /* determine which values need expanding */ + for (dp = defList; dp != NULL; dp = dp->nextDef) + dp->simple = !FindVarRef (dp->val, NULL, NULL, false); + + /* expand values to eliminate embedded var references */ + for (pass = 0; pass < nDefs; pass++) + { + changes = 0; + for (dp = defList; dp != NULL; dp = dp->nextDef) + { + if (!dp->simple) + Expand (dp); + } + if (changes == 0) /* loop while values expand */ + break; + } + + /* sanity check: shouldn't have to make more than nDefs passes */ + if (pass >= nDefs) + panic ("Too many expansion passes. Something's wrong!"); + + DecodeEscapes (); + + /* partain addition: + args of form "foo=bar" are taken to be defs to add in + */ + while (argc > 0 && strchr(argv[0], '=') && isalpha(argv[0][0])) + { + char name[BUFSIZ], *np, *p; + int len; + p = argv[0]; + /* copied from below */ + np = name; + while (isalnum (*p) || *p == '_') + *np++ = *p++; + *np = '\0'; + while (isspace (*p)) /* skip whitespace */ + ++p; + if (*p++ == '=') /* it's a definition */ + { + /* skip leading/trailing whitespace */ + while (isspace (*p)) + ++p; + len = strlen (p); + while (len > 0 && isspace (p[len-1])) + p[--len] = '\0'; + AddDef (name, p, 1); + /* find var refs in value -- NUKED */ + /* FindAllVarRefs (p); */ + /* also NUKED: continue; */ + } + /* end of: copied from below */ + --argc; + ++argv; + } + /* end of partain addition */ + + /* read source file(s) and perform substitutions */ + if (argc == 0) + DoSub (stdin); + else while (argc > 0) + { + if ((f = fopen (*argv, "r")) == NULL) + { + fprintf (stderr, "Can't open \"%s\". ", *argv); + panic ("Quitting."); + } + DoSub (f); + fclose (f); + --argc; + ++argv; + } + + exit (0); +} + + +/* + Read a makefile. +*/ + +ReadMake (f) +FILE *f; +{ +char input[BUFSIZ * 4], name[BUFSIZ], *p, *np; +int i, len; + + while (GetLine (f, input)) /* get line, check whether def'n */ + { + for (p = input; isspace (*p); p++) { /* nop */ } + if (*p == '#' || *p == '\0') /* comment or blank line */ + continue; + if (isalpha (*p)) /* look for var name */ + { + np = name; + while (isalnum (*p) || *p == '_') + *np++ = *p++; + *np = '\0'; + while (isspace (*p)) /* skip whitespace */ + ++p; + if (*p++ == '=') /* it's a definition */ + { + /* skip leading/trailing whitespace */ + while (isspace (*p)) + ++p; + len = strlen (p); + while (len > 0 && isspace (p[len-1])) + p[--len] = '\0'; + AddDef (name, p, 1); + /* find var refs in value */ + FindAllVarRefs (p); + continue; + } + } + /* not a definition; find var refs anywhere in line */ + FindAllVarRefs (input); + } +} + + +/* + Find definition by variable name. +*/ + +Def *FindDefByVar (s) +char *s; +{ +Def *dp; + + for (dp = defList; dp != NULL; dp = dp->nextDef) + { + if (strcmp (dp->var, s) == 0) + return (dp); + } + return (NULL); +} + + +/* + Add a definition. If the name hasn't been seen yet, create a new + definition on the list. If the name has been seen, and replace is + non-zero, replace the current value with the new one. (replace will + be zero if we're just adding a variable which is known by its being + referenced somewhere.) +*/ + +AddDef (name, value, replace) +char *name, *value; +int replace; +{ +Def *dp; + + if ((dp = FindDefByVar (name)) == NULL) + { + if ((dp = (Def *) calloc (1, sizeof (Def))) == NULL) + panic ("AddDef: out of memory"); + dp->var = NewString (name); + dp->val = NewString (value); + dp->simple = 0; /* assume not */ + dp->nextDef = defList; + defList = dp; + ++nDefs; + } + else if (replace) + { + free (dp->val); + dp->val = NewString (value); + } +} + + +/* + Replace instances of '$$' with a single ^A. +*/ + +EncodeEscapes () +{ +Def *dp; +char *p, *q; + + for (dp = defList; dp != NULL; dp = dp->nextDef) + { + for (p = q = dp->val; *p != '\0'; p++, q++) + { + *q = *p; + if (*p == '$' && *(p+1) == '$') + { + *q = '\01'; + p++; + } + } + *q = '\0'; + } +} + + +/* + Replace instances of ^A with a '$'. +*/ + +DecodeEscapes () +{ +Def *dp; +char *p; + + for (dp = defList; dp != NULL; dp = dp->nextDef) + { + for (p = dp->val; *p != '\0'; p++) + { + if (*p == '\01') + *p = '$'; + } + } +} + + +/* + Find variable reference in variable value. begin is set to + the index of the '$' and end is set to the index of the closing + delimiter. (If either is NULL, it is not set.) + + recogEsc is non-zero (true) if '$$' is recognized as an escaped '$' + and skipped. It will be true during initial searching for var refs + and while substituting in source files, false while expanding variable + values. + + $v, ${}, ${1}, ${v), etc. are not accepted as valid and are ignored. +*/ + +FindVarRef (s, beg, end, recogEsc) +char *s; +int *beg, *end, recogEsc; +{ +int i; +char c, delim; + + i = 0; + for (;;) + { + while ((c = s[i]) != '\0') + { + if (c == '$') + { + if ((c = s[i+1]) == '{' || c == '(') + break; + if (recogEsc && c == '$') /* escaped $ */ + ++i; + } + ++i; + } + if (c == '\0') + return (0); /* no reference */ + if (beg != (int *) NULL) + *beg = i; + if (s[++i] == '{') + delim = '}'; + else + delim = ')'; + ++i; + if (!isalpha (s[i])) /* must have at least one char, must */ + continue; /* begin with letter */ + while ((c = s[++i]) != '\0') + { + if (c == delim) /* find matching delim */ + { + if (end != (int *) NULL) + *end = i; + return (1); + } + if (!isalnum (c) && c != '_') + break; + } + } +} + + +FindAllVarRefs (s) +char *s; +{ +char name[BUFSIZ]; +int begin, end; + + while (FindVarRef (s, &begin, &end, true)) + { + /* add with empty value if unknown, */ + /* but don't replace value if known */ + strncpy (name, s + begin + 2, end - begin - 2); + name[end-begin-2] = '\0'; + AddDef (name, "", 0); + s += end + 1; + } +} + + +/* + Pull out a variable reference, skipping leading '$(' or '${' and + trailing ')' or '}'. +*/ + +YankVarRef (dst, src, begin, end) +char *dst, *src; +int begin, end; +{ + strncpy (dst, src + begin + 2, end - begin - 2); + dst[end - begin - 2] = '\0'; +} + + +/* + Look for variable references in a variable value and expand them + when possible. If a variable is referenced but never defined, it + disappears. If a variable is referenced, but its value has not itself + been fully expanded, defer expansion of value until another pass, at + which time the referenced variable might then be expanded. This + prevents infinite expansions on circular references. +*/ + +Expand (dp) +Def *dp; +{ +Def *dp2; +/* partain: made 4 * BUFSIZ +char buf[BUFSIZ]; +*/ +char buf[4 * BUFSIZ]; +int begin, end, vn; + + while (FindVarRef (dp->val, &begin, &end, false)) + { + YankVarRef (buf, dp->val, begin, end); + if ((dp2 = FindDefByVar (buf)) == NULL) + { + fprintf (stderr, "Expand error: can't find %s, ", buf); + panic ("quitting"); + } + if (!dp2->simple) /* can't expand, give up for now */ + break; + dp->val[begin] = '\0'; + sprintf (buf, "%s%s%s", dp->val, dp2->val, &(dp->val)[end+1]); + free (dp->val); + dp->val = NewString (buf); + ++changes; + } + dp->simple = !FindVarRef (dp->val, NULL, NULL, false); +} + + +/* + Read through file, performing substitutions for any variables + known from Makefile. If a variable reference is found that is + for an unknown variable, leave it alone, as it may be a reference + to a real variable in a shell script. +*/ + +DoSub (f) +FILE *f; +{ +Def *dp; +char input[BUFSIZ], var[BUFSIZ], *p; +int begin, end; + + while (fgets (input, sizeof (input), f) != NULL) + { + p = input; + while (FindVarRef (p, &begin, &end, true)) + { + write (1, p, begin); /* write prefix */ + YankVarRef (var, p, begin, end); + /* if var is known from makefile, write */ + /* value, else just echo the reference */ + if ((dp = FindDefByVar (var)) != NULL) + write (1, dp->val, strlen (dp->val)); + else + write (1, p + begin, end - begin + 1); + p += end + 1; + } + write (1, p, strlen (p)); + } +} + + +/* + Get next line from Makefile (combines continuation lines into one). + No overflow checking, oops. +*/ + +GetLine (f, lbuf) +FILE *f; +char *lbuf; +{ +char buf[BUFSIZ]; +int loop = 1, haveLine = 0, len; + + *lbuf = '\0'; + while (loop && fgets (buf, sizeof (buf), f) != NULL) + { + loop = 0; + haveLine = 1; + len = strlen (buf); + if (len > 0 && buf[len-1] == '\n') /* trim newline */ + buf[--len] = '\0'; + if (len > 0 && buf[len-1] == '\\') /* need continuation */ + { + loop = 1; + buf[--len] = ' '; + } + strcat (lbuf, buf); + } + return (haveLine); +} + + +/* + Allocate space for a string, copy the string into it, and return + a pointer to the copy. +*/ + + +char *NewString (s) +char *s; +{ +char *p; + + if ((p = calloc (1, strlen (s) + 1)) == NULL) + panic ("NewString: out of space"); + return (strcpy (p, s)); +} + + +panic (s) +char *s; +{ + fprintf (stderr, "%s\n", s); + exit (1); +} diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.ms b/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.ms new file mode 100644 index 0000000000..7fe019f509 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/msub.ms @@ -0,0 +1,128 @@ +.SH +Theory of Operation +.LP +.I msub +reads the makefile in the current directory (or the file named after the +.B \-f +flag) and finds all variable definitions and references. +Definitions are lines of the form ``\fIname\fR = \fIvalue\fR''. +References are instances of ``$(\fIvar\fR)'' or ``${\fIvar\fR}'', either in +the value part of definition lines, or any part of dependency or command lines. +Then variable values are examined to eliminate references to other variables +by replacing the referenced variables with their values. +Variables which are referenced but never defined have a value of the empty +string. +.LP +Then +.I msub +reads any files named on the command line (or +.I stdin +if none) and looks for instances of ``$(\fIvar\fR)'' or ``${\fIvar\fR}'', +where +.I var +is known from the makefile, and substitutes the value of +.I var . +.SH +Purpose +.LP +The motivation for +.I msub +is that project configuration information is often contained in makefiles +and it is often desirable to make use of that information. +.I msub +allows files to be produced from templates that contain references +to makefile variables. +In this sense it is similar to the way that the C preprocessor +.I cpp +uses #define statements in header files; the +makefile is the implicit ``header'' file and definition lines are the +``#define'' statements. +.LP +Although it is possible to use +.I cpp +to perform substitutions on templates, a disadvantage of +.I cpp +is that it modifies its source in other ways (eg., lines beginning with +``#'' are special and comments (``/* ... */'') are deleted. +Also, it is necessary to pass a -D flag for every symbol to be substituted. +Similarly, for C programs it can be simpler to use +.I msub +to produce a single configuration header file from a template +than to pass a lot of -D flags to each invocation of +.I cc . +.LP +.I msub +performs no textual modification besides substitution of references +to makefile variables; it leaves everything else alone. +In particular, +references to variables not known from the makefile are left untouched. +This allows +.I msub +to be used to produce shell scripts that use variables of +their own. +.LP +.I msub +is particularly useful in software projects that use +.I imake . +Virtually all configuration information is propagated into makefiles +thus produced, so it is available for propagation into other files using +.I msub . +.SH +Problems +.LP +If +.I msub +is used to produce shell scripts, it is unwise for the script to use names +for its own variables that are the same as those in the makefile. +The problem can be avoided entirely if, for instance, variables in makefiles +are all uppercase and the scripts' own variables are lowercase or mixed case. +.LP +Circular references in makefile variables are not expanded. +If a makefile contains the definitions ``X = ${Y}'' and ``Y = ${X}'', +neither X nor Y will be expanded. +But that is really a problem with the makefile, not +.I msub . +.LP +.I make +recognizes +.B \-f\ \- +to mean the makefile should be read from +.I stdin . +.I msub +does not. +.LP +CC, YACC, etc., have implicit values in +.I make +even if not defined in the makefile. +Not true in +.I msub . +.LP +.I msub +is more restrictive in the variable names that it recognizes and +performs substitutions on. +Names that do not begin with a letter and +that contain any characters besides letters, digits and underscores are +ignored. +This means that variable names such as ``${1}'' are not recognized; +the reason for this is that shell scripts often use such variables and +they should be left untouched. +Also, +``$\fIx\fR'' is legal in +.I make +when +.I x +is a single character, but +.I msub +ignores such references. +.i msub +.LP +.I make +allows variables to be defined on the command line. +.I msub +does not. +.LP +If you try to be tricky with your variable references, e.g., by using +recursive references, you may get burned. +.LP +There is no way to prevent substitution, in a source file, of a reference to +a variable known from the makefile. diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/test.makefile b/web/glasgow/lit2x-0.16/grasp-utils/msub/test.makefile new file mode 100644 index 0000000000..b20a2b7868 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/test.makefile @@ -0,0 +1,18 @@ +foo = ${bar} +bar = ${ugh} +ugh = Huh? +space = x +a = ${wildcard x} + +# xyz should be found in next line, given empty value and then the +# value should be replaced later... + +c : ${xyz} + +xyz = abc + + +dollar = $$ +doubledollar = ${dollar}${dollar} + + diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/test.stdout b/web/glasgow/lit2x-0.16/grasp-utils/msub/test.stdout new file mode 100644 index 0000000000..506999f3c1 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/test.stdout @@ -0,0 +1,11 @@ +foo = Huh? +bar = Huh? +ugh = Huh? +xy +${wildcard x} + +This (abc) should be abc. + +This should be a single dollar: $ +This should be a double dollar: $$ +So should this: $$ diff --git a/web/glasgow/lit2x-0.16/grasp-utils/msub/testfile b/web/glasgow/lit2x-0.16/grasp-utils/msub/testfile new file mode 100644 index 0000000000..ba3f4ebbf0 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/msub/testfile @@ -0,0 +1,11 @@ +foo = ${foo} +bar = ${bar} +ugh = ${ugh} +${space}y +${a} + +This (${xyz}) should be abc. + +This should be a single dollar: ${dollar} +This should be a double dollar: ${dollar}${dollar} +So should this: ${doubledollar} diff --git a/web/glasgow/lit2x-0.16/grasp-utils/perl-4.035-fixes b/web/glasgow/lit2x-0.16/grasp-utils/perl-4.035-fixes new file mode 100644 index 0000000000..e456aa49e8 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/perl-4.035-fixes @@ -0,0 +1,180 @@ +From mjeffery@reed.edu Sun Nov 29 14:07:23 1992 +From: mjeffery@reed.edu (Mark Jefferys) +Newsgroups: comp.lang.perl +Subject: Re: Recursion error in perl 4.035 ? +Date: 28 Nov 92 23:31:14 GMT +Organization: Reed College, Portland, OR + +In article <1f7uvvINN9tp@roundup.crhc.uiuc.edu> parkes@uiuc.edu writes: + +% In cons.c, change the code at or around 1423 from +% +% if (willsave) +% (void)apush(tosave,arg->arg_ptr.arg_str); +% +% to +% +% if (willsave && arg->arg_ptr.arg_str ) +% (void)apush(tosave,arg->arg_ptr.arg_str); + +This is half of my patch to which Larry gave a "Looks OK to me." +It's been a few months, do I'll post it again. + + +Mark + + +Index: cons.c +*** Orig/cons.c Thu Jun 11 22:42:01 1992 +--- cons.c Sun Jun 28 18:31:20 1992 +*************** +*** 1353,1359 **** + + /* in any event, save the iterator */ + +! (void)apush(tosave,cmd->c_short); + } + shouldsave |= tmpsave; + } +--- 1353,1360 ---- + + /* in any event, save the iterator */ + +! if (cmd->c_short) /* Better safe than sorry */ +! (void)apush(tosave,cmd->c_short); + } + shouldsave |= tmpsave; + } +*************** +*** 1420,1426 **** + shouldsave = TRUE; + break; + } +! if (willsave) + (void)apush(tosave,arg->arg_ptr.arg_str); + return shouldsave; + } +--- 1421,1427 ---- + shouldsave = TRUE; + break; + } +! if (willsave && arg->arg_ptr.arg_str) + (void)apush(tosave,arg->arg_ptr.arg_str); + return shouldsave; + } +-- +Mark Jefferys Internet: mjeffery@reed.edu + +From ezk@cs.columbia.edu Fri Dec 4 19:44:03 1992 +From: ezk@cs.columbia.edu (Erez "HWank1" Zadok) +Newsgroups: comp.lang.perl +Subject: REPOST: FIXES to perl/makewhatis (core dump on OW3 man pages) +Date: 3 Dec 92 12:42:05 GMT + +[This is a repost... -Erez] + +I've found three small bugs in the the latest version of perl (4.035), which +I fixed. + +The bugs only appeared when I got Tom Christiansen's man package, and ran +the makewhatis script. Furthermore, it only occurred for one particular set +of manual pages -- SunOS's OpenWindows 3. + +Since it seemed related to DBM, I tried to recompile perl with several +possible combinations of Sun's /bin/cc, gcc (2.2.2), ndbm, gdbm, +- -DDEBUGGING, -traditional (for gcc), Perl's malloc, Sun's malloc, etc. to no +avail. Perl was still dumping core with a segmentation fault. "make test" +was ok. I was running on various Sun 4 machines, running SunOS 4.1.2. + +After debugging I found out that perl was trying to dereference pointers +that were not initialized. + +I fixed this by adding initialization to three declarations in perl.h. The +ones to rsfp and statstab were needed for non-compressed man pages. When I +started using compressed man pages I discovered I had to initialize fdpid as +well. Now everything works fine. Here is the diff file: + +*** array.h.orig Tue Nov 24 02:16:30 1992 +--- array.h Mon Nov 23 14:31:16 1992 +*************** +*** 17,22 **** +--- 17,33 ---- + * + */ + ++ #ifdef NULL ++ #undef NULL ++ #endif ++ #ifndef I286 ++ # define NULL 0 ++ #else ++ # define NULL 0L ++ #endif ++ #define Null(type) ((type)NULL) ++ #define Nullarray Null(ARRAY*) ++ + struct atbl { + STR **ary_array; + STR **ary_alloc; +*** perl.h.orig Tue Nov 24 02:16:10 1992 +--- perl.h Mon Nov 23 14:30:51 1992 +*************** +*** 868,874 **** + + EXT char *hexdigit INIT("0123456789abcdef0123456789ABCDEFx"); + EXT char *origfilename; +! EXT FILE * VOLATILE rsfp; + EXT char buf[1024]; + EXT char *bufptr; + EXT char *oldbufptr; +--- 868,874 ---- + + EXT char *hexdigit INIT("0123456789abcdef0123456789ABCDEFx"); + EXT char *origfilename; +! EXT FILE * VOLATILE rsfp INIT(Nullfp); + EXT char buf[1024]; + EXT char *bufptr; + EXT char *oldbufptr; +*************** +*** 952,958 **** + EXT struct stat statbuf; + EXT struct stat statcache; + EXT STAB *statstab INIT(Nullstab); +! EXT STR *statname; + #ifndef MSDOS + EXT struct tms timesbuf; + #endif +--- 952,958 ---- + EXT struct stat statbuf; + EXT struct stat statcache; + EXT STAB *statstab INIT(Nullstab); +! EXT STR *statname INIT(Nullstr); + #ifndef MSDOS + EXT struct tms timesbuf; + #endif +*************** +*** 1013,1019 **** + EXT ARRAY *lineary; /* lines of script for debugger */ + EXT ARRAY *dbargs; /* args to call listed by caller function */ + +! EXT ARRAY *fdpid; /* keep fd-to-pid mappings for mypopen */ + EXT HASH *pidstatus; /* keep pid-to-status mappings for waitpid */ + + EXT int *di; /* for tmp use in debuggers */ +--- 1013,1019 ---- + EXT ARRAY *lineary; /* lines of script for debugger */ + EXT ARRAY *dbargs; /* args to call listed by caller function */ + +! EXT ARRAY *fdpid INIT(Nullarray); /* keep fd-to-pid mappings for mypopen */ + EXT HASH *pidstatus; /* keep pid-to-status mappings for waitpid */ + + EXT int *di; /* for tmp use in debuggers */ + + +Erez Zadok. +Central Research Facilities. +Columbia University Department of Computer Science. +- --- +"A wank's morning starts one jiffy | Arpa: ezk@cs.columbia.edu + after midnight." | Usenet: ...!rutgers!columbia!cs!ezk + -HebrewWank #1 (US meaning, not UK!) | Bitnet: erzus@cuvmb.BITNET diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/Jmakefile b/web/glasgow/lit2x-0.16/grasp-utils/scripts/Jmakefile new file mode 100644 index 0000000000..22d1ccb32f --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/Jmakefile @@ -0,0 +1,79 @@ +PROGRAMS = lndir \ + mkdirhier \ + runstdtest \ + mkdependC \ + fastmake \ + lmake \ + zap-if-same \ + moan-if-old \ + ltx \ + perltags + +all:: $(PROGRAMS) +/* stuff to have before we get going */ +MsubNeededHere($(PROGRAMS)) + +/* === BUILD STUFF (installation, etc., below) ========== */ + +/* std X11 stuff */ +MsubProgramScriptTarget(BourneShell,mkdirhier,mkdirhier.sh,/*no flags*/,/*no dep*/) + +BuildPgmFromOneCFile(lndir) +#if 0 +MsubProgramScriptTarget(BourneShell,lndir,lndir.sh,/*no flags*/,/*no dep*/) +InstallScriptTarget(lndir, $(INSTSCRIPTDIR)) +#endif + +MsubMakefileDependentProgramScriptTarget(PerlCmd,runstdtest,runstdtest.prl,/*no flags*/,/*Makefile*/) +MsubMakefileDependentProgramScriptTarget(PerlCmd,ltx,ltx.prl,/*no flags*/,/*Makefile*/) +MsubProgramScriptTarget(PerlCmd,fastmake,fastmake.prl,/*no flags*/,/**/) +MsubProgramScriptTarget(PerlCmd,zap-if-same,zap-if-same.prl,/*no flags*/,/**/) +MsubProgramScriptTarget(PerlCmd,moan-if-old,moan-if-old.prl,/*no flags*/,/**/) +MsubProgramScriptTarget(PerlCmd,perltags,perltags.prl,/*no flags*/,/**/) + +MsubProgramScriptTarget(BourneShell,lmake,lmake.sh,/*no flags*/,/*no dep*/) + +/* +mkdependC has to go in "bin" directory, because there may be +machine-dependent ideas of what CC to use, etc. + +ltx, runstdtest: ditto, but only because of TMPDIR +*/ +MsubMakefileDependentProgramScriptTarget(PerlCmd,mkdependC,mkdependC.prl,/*noflags*/,/*Makefile*/) + +#ifdef UseCCMakeDepend +install:: + @echo "install makedepend (in ${CURRENT_DIR}) by hand..." +#endif +/* + lobotomized... install by hand... +#ifdef UseCCMakeDepend +InstallProgramTarget(makedepend,$(BINDIR)) +#endif +*/ + +/* === INSTALLATION ======== */ + +/* the rest of these vary from std/useful to hackish dans le extreme */ + +MakeDirectories(install, $(INSTBINDIR) $(INSTSCRIPTDIR)) +InstallScriptTarget(fastmake, $(INSTSCRIPTDIR)) +InstallScriptTarget(lmake, $(INSTSCRIPTDIR)) +InstallBinaryTarget(lndir, $(INSTBINDIR)) +InstallScriptTarget(ltx, $(INSTBINDIR)) +InstallScriptTarget(mkdependC, $(INSTBINDIR)) +InstallScriptTarget(mkdirhier, $(INSTSCRIPTDIR)) +InstallScriptTarget(perltags, $(INSTSCRIPTDIR)) +InstallScriptTarget(runstdtest, $(INSTBINDIR)) +InstallScriptTarget(zap-if-same, $(INSTSCRIPTDIR)) +InstallScriptTarget(moan-if-old, $(INSTSCRIPTDIR)) + +InstallManPageTarget(lndir,$(INSTCOMMANDIR),$(COMMANSUFFIX)) +InstallManPageTarget(mkdirhier,$(INSTCOMMANDIR),$(COMMANSUFFIX)) + +/* === OTHER STUFF ========= */ + +ExtraStuffToClean($(PROGRAMS)) + +ClearTagsFile() +PerlTagsTarget( *.prl ) /* nothing for the Bourne shell scripts */ diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/fastmake.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/fastmake.prl new file mode 100644 index 0000000000..388b4ed44d --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/fastmake.prl @@ -0,0 +1,126 @@ +#! /usr/local/bin/perl +# +($Pgm = $0) =~ s/.*\/([^\/]+)$/\1/; +$Usage = "\n" . <$Tmpfile") || die "Can't open $Tmpfile for output\n"; +select(OUTF); + +$_ = ; + +# copy through until ... +while ( $_ && ! /^# DO NOT DELETE: Beginning of Haskell dependencies/ ) { + print $_; + $_ = ; +} + +# now copy through 'til the end, omittin the %.[so] : %.hi dependencies +while ( $_ ) { + print $_ if ! /^\S+ : \S+\.hi$/; + $_ = ; +} + +close(INF); +close(OUTF); + +if ($Arch ne "sun3") { + $Make = 'make JMAKE=jmake LIT2PGM=lit2pgm LIT2LATEX=lit2latex LIT2TEXI=lit2texi MKDEPENDLIT=mkdependlit MAKEINFO=makeinfo POSTMAKEINFO=postmakeinfo'; +} else { + $Make = 'make'; +} +print STDERR "$Make $MakeFlags -f $Tmpfile $Target; rm $Tmpfile\n" if $Verbose; + +system( "$Make $MakeFlags -f $Tmpfile $Target; rm $Tmpfile" ); + +if ($Do_touch) { + print STDERR "$SleazyTouch -m 01010101 $DirMod\.hi\n" if $Verbose; + system( "$SleazyTouch -m 01010101 $DirMod\.hi" ); +} diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/lmake.sh b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lmake.sh new file mode 100644 index 0000000000..133405cb07 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lmake.sh @@ -0,0 +1,2 @@ +#! /bin/sh +make JMAKE=jmake LIT2PGM=lit2pgm LIT2LATEX=lit2latex LIT2TEXI=lit2texi MKDEPENDLIT=mkdependlit MAKEINFO=makeinfo POSTMAKEINFO=postmakeinfo $* diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.c b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.c new file mode 100644 index 0000000000..d365de6755 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.c @@ -0,0 +1,217 @@ +/* $XConsortium: lndir.c,v 1.5 91/07/21 15:52:11 rws Exp $ */ +/* Create shadow link tree (after X11R4 script of the same name) + Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */ + +/* Copyright 1990, Massachusetts Institute of Technology + + Permission to use, copy, modify, and distribute this program for any purpose + and without fee is hereby granted, provided that this copyright and + permission notice appear on all copies and supporting documentation, that + the name of MIT not be used in advertising or publicity pertaining to + distribution of this program without specific prior permission, and that + notice be given in supporting documentation that copying and distribution is + by permission of MIT. MIT makes no representations about the suitability of + this software for any purpose. It is provided "as is" without expressed or + implied warranty. +*/ + +/* From the original /bin/sh script: + + Used to create a copy of the a directory tree that has links for all + non-directories (except those named RCS or SCCS). If you are + building the distribution on more than one machine, you should use + this script. + + If your master sources are located in /usr/local/src/X and you would like + your link tree to be in /usr/local/src/new-X, do the following: + + % mkdir /usr/local/src/new-X + % cd /usr/local/src/new-X + % lndir ../X +*/ + +/*#include */ +#include +#include +#include +#include + +#ifndef X_NOT_POSIX +#include +#else +#ifdef SYSV +#include +#else +#ifdef USG +#include +#else +#include +#ifndef dirent +#define dirent direct +#endif +#endif +#endif +#endif + +extern int errno; +int silent; + +void +quit (code, fmt, a1, a2, a3) +char *fmt; +{ + fprintf (stderr, fmt, a1, a2, a3); + putc ('\n', stderr); + exit (code); +} + +void +quiterr (code, s) +char *s; +{ + perror (s); + exit (code); +} + +void +msg (fmt, a1, a2, a3) +char *fmt; +{ + fprintf (stderr, fmt, a1, a2, a3); + putc ('\n', stderr); +} + + +/* Recursively create symbolic links from the current directory to the "from" + directory. Assumes that files described by fs and ts are directories. */ + +dodir (fn, fs, ts, rel) +char *fn; /* name of "from" directory, either absolute or + relative to cwd */ +struct stat *fs, *ts; /* stats for the "from" directory and cwd */ +int rel; /* if true, prepend "../" to fn before using */ +{ + DIR *df; + struct dirent *dp; + char buf[MAXPATHLEN + 1], *p; + char symbuf[MAXPATHLEN + 1]; + struct stat sb, sc; + int n_dirs; + + if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) { + msg ("%s: From and to directories are identical!", fn); + return 1; + } + + if (rel) + strcpy (buf, "../"); + else + buf[0] = '\0'; + strcat (buf, fn); + + if (!(df = opendir (buf))) { + msg ("%s: Cannot opendir", buf); + return 1; + } + + p = buf + strlen (buf); + *p++ = '/'; + n_dirs = fs->st_nlink; + while (dp = readdir (df)) { + strcpy (p, dp->d_name); + + if (n_dirs > 0) { + if (stat (buf, &sb) < 0) { + perror (buf); + continue; + } + + if (sb.st_mode & S_IFDIR) { + /* directory */ + n_dirs--; + if (dp->d_name[0] == '.' && + (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && + dp->d_name[2] == '\0'))) + continue; + if (!strcmp (dp->d_name, "RCS")) + continue; + if (!strcmp (dp->d_name, "SCCS")) + continue; + if (!silent) + printf ("%s:\n", buf); + if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) { + if (mkdir (dp->d_name, 0777) < 0 || + stat (dp->d_name, &sc) < 0) { + perror (dp->d_name); + continue; + } + } + if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) { + msg ("%s: is a link instead of a directory\n", dp->d_name); + continue; + } + if (chdir (dp->d_name) < 0) { + perror (dp->d_name); + continue; + } + dodir (buf, &sb, &sc, (buf[0] != '/')); + if (chdir ("..") < 0) + quiterr (1, ".."); + continue; + } + } + + /* non-directory */ + if (symlink (buf, dp->d_name) < 0) { + int saverrno = errno; + int symlen; + symlen = readlink(dp->d_name, symbuf, sizeof(symbuf) - 1); + errno = saverrno; + if (symlen > 0) + symbuf[symlen] = '\0'; + if (symlen < 0 || strcmp(symbuf, buf)) + perror (dp->d_name); + } + } + + closedir (df); + return 0; +} + + +main (ac, av) +int ac; +char **av; +{ + char *fn, *tn; + struct stat fs, ts; + + silent = 0; + if (ac > 1 && !strcmp(av[1], "-silent")) { + silent = 1; + } + if (ac < silent + 2 || ac > silent + 3) + quit (1, "usage: %s [-silent] fromdir [todir]", av[0]); + + fn = av[silent + 1]; + if (ac == silent + 3) + tn = av[silent + 2]; + else + tn = "."; + + /* to directory */ + if (stat (tn, &ts) < 0) + quiterr (1, tn); + if (!(ts.st_mode & S_IFDIR)) + quit (2, "%s: Not a directory", tn); + if (chdir (tn) < 0) + quiterr (1, tn); + + /* from directory */ + if (stat (fn, &fs) < 0) + quiterr (1, fn); + if (!(fs.st_mode & S_IFDIR)) + quit (2, "%s: Not a directory", fn); + + exit (dodir (fn, &fs, &ts, 0)); +} diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.man b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.man new file mode 100644 index 0000000000..ae5b4285bd --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.man @@ -0,0 +1,61 @@ +.TH LNDIR 1 "Release 5" "X Version 11" +.SH NAME +lndir \- create a shadow directory of symbolic links to another directory tree +.SH SYNOPSIS +.B lndir +fromdir [todir] +.SH DESCRIPTION +.I Lndir +makes a shadow copy +.I todir +of a directory tree +.I fromdir, +except that the shadow is not +populated with real files but instead with symbolic links pointing at +the real files in the +.I fromdir +directory tree. This is usually useful for maintaining source code for +different machine architectures. You create a shadow directory +containing links to the real source which you will have usually NFS +mounted from a machine of a different architecture, and then recompile +it. The object files will be in the shadow directory, while the +source files in the shadow directory are just symlinks to the real +files. +.PP +This has the advantage that if you update the source, you need not +propagate the change to the other architectures by hand, since all +source in shadow directories are symlinks to the real thing: just cd +to the shadow directory and recompile away. +.PP +The +.I todir +argument is optional and defaults to the current directory. The +.I fromdir +argument may be relative (e.g., ../src) and is relative to +.I todir +(not the current directory). +.PP +.ft B +Note that RCS and SCCS directories are not shadowed. +.ft +.PP +Note that if you add files, you must run +.I lndir +again. Deleting files is a more painful problem; the symlinks will +just point into never never land. +.SH BUGS +.I Patch +gets upset if it cannot change the files. You should never run +.I patch +from a shadow directory anyway. +.PP +You need to use something like +.nf + find todir -type l -print | xargs rm +.fi +to clear out all files before you can relink (if fromdir moved, for instance). +Something like +.nf + find . \\! -type d -print +.fi +will find all files that are not directories. diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.sh b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.sh new file mode 100644 index 0000000000..f09bf7f590 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/lndir.sh @@ -0,0 +1,85 @@ +#! /bin/sh + +# lndir - create shadow link tree +# +# $XConsortium: lndir.sh,v 1.8 91/04/15 17:55:03 rws Exp $ +# +# Used to create a copy of the a directory tree that has links for all +# non- directories (except those named RCS or SCCS). If you are +# building the distribution on more than one machine, you should use +# this script. +# +# If your master sources are located in /usr/local/src/X and you would like +# your link tree to be in /usr/local/src/new-X, do the following: +# +# % mkdir /usr/local/src/new-X +# % cd /usr/local/src/new-X +# % lndir ../X + +USAGE="Usage: $0 fromdir [todir]" + +if [ $# -lt 1 -o $# -gt 2 ] +then + echo "$USAGE" + exit 1 +fi + +DIRFROM=$1 + +if [ $# -eq 2 ]; +then + DIRTO=$2 +else + DIRTO=. +fi + +if [ ! -d $DIRTO ] +then + echo "$0: $DIRTO is not a directory" + echo "$USAGE" + exit 2 +fi + +cd $DIRTO + +if [ ! -d $DIRFROM ] +then + echo "$0: $DIRFROM is not a directory" + echo "$USAGE" + exit 2 +fi + +pwd=`pwd` + +if [ `(cd $DIRFROM; pwd)` = $pwd ] +then + echo "$pwd: FROM and TO are identical!" + exit 1 +fi + +for file in `ls -af $DIRFROM` +do + if [ ! -d $DIRFROM/$file ] + then + ln -s $DIRFROM/$file . + else + if [ $file != RCS -a $file != SCCS -a $file != . -a $file != .. ] + then + echo $file: + mkdir $file + (cd $file + pwd=`pwd` + case "$DIRFROM" in + /*) ;; + *) DIRFROM=../$DIRFROM ;; + esac + if [ `(cd $DIRFROM/$file; pwd)` = $pwd ] + then + echo "$pwd: FROM and TO are identical!" + exit 1 + fi + $0 $DIRFROM/$file + ) + fi + fi +done diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/ltx.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/ltx.prl new file mode 100644 index 0000000000..1bce758270 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/ltx.prl @@ -0,0 +1,215 @@ +$Pgm = $0; $Pgm =~ s/.*\/([^\/]+)$/\1/; +# +# set up signal handler +sub quit_upon_signal { &rm_temp_files_and_exit(); } +$SIG{'INT'} = 'quit_upon_signal'; +$SIG{'QUIT'} = 'quit_upon_signal'; +# +$Verbose = 0; +if ($ARGV[0] eq '-v') { + $Verbose = 1; + shift(@ARGV); +} +# +die "$Pgm: must have exactly one argument\n" if $#ARGV != 0; +# figure out input file and its filename root +if (-f $ARGV[0]) { + $TeX_input = $ARGV[0]; + if ($TeX_input =~ /(.+)\.[^\.\/\n]+$/) { + $TeX_root = $1; + } else { + $TeX_root = $TeX_input; + } +} elsif (-f $ARGV[0].'.tex') { + $TeX_input = $ARGV[0].'.tex'; + $TeX_root = $ARGV[0]; +} else { + die "$Pgm: input file $ARGV[0] doesn't exist\n"; +} + +sub rm_temp_files { + system("rm -f $(TMPDIR)/ltx-*.$$"); +} +sub rm_temp_files_and_exit { + system("rm -f $(TMPDIR)/ltx-*.$$"); + exit(1); +} +$SIG{'INT'} = 'rm_temp_files_and_exit'; +$SIG{'QUIT'} = 'rm_temp_files_and_exit'; + +sub die_gracefully { + local($msg) = @_; + + print STDERR $msg; + &rm_temp_files_and_exit(); +} + +# must read through root file to see if a \bibliography +# is there... +$Bibliography_requested = 0; +open(TEXIF, "<$TeX_input") + || &die_gracefully("$Pgm: Can't read $TeX_input\n"); +while () { + $Bibliography_requested = 1 if /^\\bibliography/; +} +close(TEXIF); +&die_gracefully("$Pgm: reading $TeX_input had errors\n") if $? >> 8; + +# run latex first time (?) +&run_latex(); # sets $Says_labels_changed +$Times_run = 1; + +while (&something_more_needed()) { + + print STDERR "labels_changed=$Says_label_changed;bibtex_needed=$BibTeX_run_needed;makeindex_needed=$MakeIndex_run_needed\n" if $Verbose; + + if ($BibTeX_run_needed) { + &run_bibtex(); + } + if ($MakeIndex_run_needed) { + unlink "$TeX_root.ind"; + (system("makeindex $TeX_root.idx") >> 8) + && &die_gracefully("$Pgm: makeindex $TeX_root.idx had errors\n"); + } + + # save (copy) .aux file as .aux-prev file for future ref + # ditto for .idx file + unlink "$TeX_root.aux-prev"; + (system("cp $TeX_root.aux $TeX_root.aux-prev") >> 8) + && &die_gracefully("$Pgm: cp $TeX_root.aux $TeX_root.aux-prev failed\n"); + if (-f "$TeX_root.idx") { + unlink "$TeX_root.idx-prev"; + (system("cp $TeX_root.idx $TeX_root.idx-prev") >> 8) + && &die_gracefully("$Pgm: cp $TeX_root.idx $TeX_root.idx-prev failed\n"); + } + + # run latex again + &run_latex(); # sets $Says_labels_changed + $Times_run++; + + if ($Times_run >= 4) { + print STDERR "*** I don't run LaTeX more than four times;\n"; + print STDERR "*** Something is probably wrong...\n"; + &rm_temp_files_and_exit(); + } +} +&rm_temp_files(); +exit(0); + +sub run_latex { + $Says_labels_changed = 0; + $Multiply_defined_labels = 0; + + select(STDERR); $| = 1; select(STDOUT); # no buffering on STDERR + print STDERR "$Pgm: *** running LaTeX...\n" if $Verbose; + unlink "$TeX_root.dvi"; + + open(LTXPIPE, "latex $TeX_input 2>&1 |") + || &die_gracefully("$Pgm: Can't run latex pipe\n"); + while () { + $Multiply_defined_labels = 1 if /^LaTeX Warning: Label .* multiply defined/; + $Says_labels_changed = 1 if /^LaTeX Warning: Label\(s\) may have changed/ + && ! $Multiply_defined_labels; + print STDERR $_; + } + close(LTXPIPE); + &die_gracefully("$Pgm: LaTeX run had errors\n") if $? >> 8; + + # sort .idx file, because this helps makeindex + # (can you say `bug'?) + if (-f "$TeX_root.idx") { + print STDERR "$Pgm: *** sorting $TeX_root.idx...\n" if $Verbose; + (system("sort $TeX_root.idx -o $TeX_root.idx") >> 8) + && &die_gracefully("$Pgm: sorting $TeX_root.idx failed\n"); + } + +} + +sub run_bibtex { # ugly because bibtex doesn't return a correct error status + local($bibtex_had_errors) = 0; + + print STDERR "$Pgm: *** running BibTeX...\n" if $Verbose; + unlink "$TeX_root.bbl"; + + $| = 1; # no buffering + open(BIBTXPIPE, "bibtex $TeX_root 2>&1 |") + || &die_gracefully("$Pgm: Can't run bibtex pipe\n"); + while () { + $bibtex_had_errors = 1 if /^\(There.*error message(s)?\)$/; + print STDERR $_; + } + close(BIBTXPIPE); + &die_gracefully("$Pgm: BibTeX run had errors\n") + if $? >> 8 || $bibtex_had_errors; +} + +sub something_more_needed { + # returns 1 or 0 if we need to run LaTeX + # possibly preceded by bibtex and/or makeindex run + + # $Says_labels_changed was set by previous &run_latex... + $BibTeX_run_needed = 0; + $MakeIndex_run_needed = 0; + + if ( ! -f ($TeX_root . '.aux-prev')) { # this was the first run + + print STDERR "$Pgm: *** 'twas first run of LaTeX on $TeX_input\n" if $Verbose; + + # we need makeindex to run if a non-zero-sized .idx file exists + # + $MakeIndex_run_needed = 1 + if -f "$TeX_root.idx" && -s "$TeX_root.idx"; + + # we need bibtex to run if there are \citations in the .aux file + # + &slurp_aux_file('aux'); + $BibTeX_run_needed = 1 + if $Bibliography_requested && + -f "$(TMPDIR)/ltx-aux-cite.$$" && + -s "$(TMPDIR)/ltx-aux-cite.$$"; + + + } else { # ltx had been run before (.aux-prev/.idx-prev files exist) + + # slurp both .aux and .aux-prev files + &slurp_aux_file('aux'); + &slurp_aux_file('aux-prev'); + + local($tmp_pre) = "$(TMPDIR)/ltx"; + + if ((-s "$tmp_pre-.aux-cite.$$") # there are still \cite's in there + && (system("cmp -s $tmp_pre-.aux-cite.$$ $tmp_pre-.aux-prev-cite.$$") >> 8)) { + $BibTeX_run_needed = 1 if $Bibliography_requested; + if ($Verbose) { + system("diff -c1 $tmp_pre-.aux-prev-cite.$$ $tmp_pre-.aux-cite.$$"); + } + } + + if (-f "$TeX_root.idx") { + $MakeIndex_run_needed = + (system("cmp -s $TeX_root.idx $TeX_root.idx-prev") >> 8) ? 1 : 0; + if ($MakeIndex_run_needed && $Verbose) { + system("diff -c1 $TeX_root.idx-prev $TeX_root.idx"); + } + } + } + + $Says_labels_changed || $BibTeX_run_needed || $MakeIndex_run_needed; +} + +sub slurp_aux_file { + local($ext) = @_; + + # copy all citations from slurpfile into $(TMPDIR)/ltx-$ext-cite.$$ + + open(SLURPF,"< $TeX_root.$ext") + || &die_gracefully("$Pgm: Can't open $TeX_root.$ext for reading\n"); + open(CITEF,"> $(TMPDIR)/ltx-$ext-cite.$$") + || &die_gracefully("$Pgm: Can't open $(TMPDIR)/ltx-$ext-cite.$$ for writing\n"); + + while () { + print CITEF $_ if /\\citation/; + } + close(CITEF); + close(SLURPF); +} diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/m5.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/m5.prl new file mode 100644 index 0000000000..f352f64e48 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/m5.prl @@ -0,0 +1,502 @@ +#!/usr/local/bin/perl -- # -*-Perl-*- +############################################################################## +# +# m5 is a poor-man's m4 +# +# written in March of 1991 by Bill Mann; tested with v3.044 of perl +# bill@ksr.com (ksr!bill@uunet.uu.net) +# +# This program may be used or modified for any purpose, but I would +# appreciate it if you would reports bugs and fixes to me, and credit +# yourself with any modifications you make. -bill +# +# I have mailed Larry Wall a fix for the 'perl bug' mentioned in the +# comments below. Once this bug is fixed, removing the 'redundant' +# double-quotes will provide some improvement in speed; the speed-up +# will be application dependent. -bill +# +############################################################################## + +#-- where I got it ----------------------------------------------------------- +#From: Adrian F Clark +#To: partain +#Subject: Re: Macro-processor in Perl? +#Date: Thu, 25 Jul 91 09:43:05 BST +# +#"Ask and ye shall receive" ... this sounds like just what we both +#want! +# +#..a +# +#Date: Wed, 24 Jul 91 18:09:30 EDT +#From: bill%ksr.com@uk.ac.essex.mailhost +#To: "Adrian F Clark" +#In-Reply-To: alien@essex.ac.uk's message of 24 Jul 91 09:32:13 EDT +#Subject: Re: Macro-processor in Perl? +#Sender: bill%ksr.com%ksr%uunet.uu.net@uk.ac.essex.mailhost +# +#I wrote a m4 clone, with just a couple of features missing, and a +#couple added, because the versions of m4 we had in-house, mostly from +#SUN, were either very old or buggy. +# +#The major missing feature is multiple separate output files. The +#major addition is that eval() now does a full-fledged perl eval, which +#'just happens' to include everything the m4 eval includes, in the same +#syntax. +# +#This program is in daily use, and has been tested by the author, but +#it is only used for a few applications, so problems may still be +#lurking. I'll be happy to answer a few questions, but can't promise +#to spend too much time, and I provide no guarantees. I call it m5 +#just keep it distinct from m4. +#----------------------------------------------------------------------------- + +# Auto identification +#$program_path = $0; +#$program_name = $program_path; +#$program_name =~ s:^.*/::; +#$cmd_line = join(' ', $program_name, @ARGV); +#$rcs_id = '$Id: m5,v 1.1 1991/03/12 19:48:13 bill Exp $ '; +select (STDERR); $| = 1; select (STDOUT); +#print STDERR "$program_path ", '$Revision: 1.1 $ ', "\n"; +#print STDERR $rcs_id, "\n"; + + +#eval "print STDERR \$die='Unknown parameter $1\n' if !defined \$$1; \$$1=\$';" +# while ($ARGV[0] =~ /^(\w+)=/ && shift(@ARGV)); +#exit 255 if $die; # process any FOO=bar switches + +%D = ("changecom", "\000changecom", + "changequote", "\000changequote", + "decr", "\000decr", + "define", "\000define", + "defn", "\000defn", + "dnl", "\000dnl", + "dumpdef", "\000dumpdef", + "errprint", "\000errprint", + "eval", "\000eval", + "ifdef", "\000ifdef", + "ifelse", "\000ifelse", + "include", "\000include", + "incr", "\000incr", + "index", "\000index", + "len", "\000len", + "maketemp", "\000maketemp", + "m4exit", "\000m4exit", + "m4wrap", "\000m4wrap", + "popdef", "\000popdef", + "pushdef", "\000pushdef", + "repeat", "\000repeat", + "shift", "\000shift", + "substr", "\000substr", + "syscmd", "\000syscmd", + "undefine", "\000undefine", + "unix", "", + ); + +$ccp = 0; $file = ''; +@inc = ''; +while ($ARGV[0] =~ /^-./) { + $_ = shift(@ARGV); + /^-D(\w+)(=(.*))?$/ && ($D{$1} = (defined($3)? $3 : ''), next); + /^-U(\w+)$/ && (delete $D{$1}, next); + /^-e$/ && (next); # not implemented yet -bill + /^-s$/ && ($ccp = 1, next); + /^-I(.*)$/ && (push(@inc, ($1 || shift(@ARGV)) . '/'), next); + die "unrecognized switch: $_\n"; +} + +# other globals: @args, $ab, $mi, $lq, $rq, $skip +$ab = $mi = 0; # undef would be ok +$m4wrap = ''; + +$lcom = "\#"; +$rcom = "\n"; +&changequote; + +@ARGV || unshift(@ARGV, '-'); + +for (shift(@ARGV)) { # 'feature': each file must end cleanly + print &expand('', &openf($_)); +} +$m4wrap ne '' && print &expand($m4wrap, ''); +exit; + +sub openf { + $ARGV = $_[0]; + $FH = "F" . @FH; + open($FH, $ARGV) || die "Can't open '$ARGV': $@"; + $line = 0; + $ccp && printf ("#line %s \"%s\"\n", 1, $ARGV); + $FH; +} + +# $st states: +# 0: normal text, or reading macro arguments if $pf != 0 +# 1: quoted string +# 2: comment +# 3: starting to read an argument (skipping white space) + +# expand expands its input string, removing one layer of matching quotes; +# it expands defined symbols as long as they are not between quotes. +# whenever it reaches the end of the string it reads a new line and extends +# its input if possible; if it can't it returns errors if in a macro +# argument or in a quoted string. +sub expand { + local($in,$FH) = @_; + local($i,$st,$qn,$pn) = (0,0,0,0); # used recursively + local($ci,$pi,$t); # not used recursively, but declared anyway + + while (1) { # for 'each' character + if ($i == length($in)) { + if ($FH) { + unless ($pn) { # defer output while reading macro arguments + print $in; + $in = ''; + $i = $ci = 0; + } + + if ($t = <$FH>) { + $in .= $t; + $line++; + next; # process next line + } + + close($FH); + + if (@argv) { + $FH = pop(@FH); + $ARGV = pop(@argv); + $line = pop(@line); + $in .= pop(@in); + $ccp && printf ("#line %s \"%s\"\n", $line, $ARGV); + next; + } + } + $st == 1 && die "missing close quote\n"; + $st == 2 && die "missing close comment\n"; + $pn && die "missing close parenthesis\n"; + last; + } + +## substr($in, $i) =~ $skip && ($i += length($&)) == length($in) && next; + substr($in, $i) =~ /^[ \t0-9]+/ && + ($i += length($&)) == length($in) && next; + + if ($st == 1) { # if in a quoted string + if (substr($in, $i, length($rq)) eq $rq) { + if (--$qn) { + $i += length($rq); + } else { + substr($in, $i, length($rq)) = ''; + $st = 0; + } + next; + } + if (substr($in, $i, length($lq)) eq $lq) { + ++$qn; + $i += length($lq); + next; + } + ++$i; + next; + } + elsif ($st == 2) { # if in a comment + if (($i = index($in, $rcom, $i)) == -1) { # extends past eol + $i = length($in); + next; + } + + $i += length($rcom); + if ($pn) { # if in parens + substr($in, $ci, $i-$ci) = ''; + $i = $ci; + $rcom eq "\n" && (substr($in, $i++, 0) = "\n"); + } + $st = 0; + next; + } + elsif ($st == 3) { # if starting an argument + substr($in, $pi, $i-$pi+1) =~ s/^(\s*)(\S)/$2/ && + ($i -= length($1), $st = 0); + } + + if (substr($in, $i, length($lq)) eq $lq && $lq) { + substr($in, $i, length($lq)) = ''; + $st = $qn = 1; + next; + } + + if (substr($in, $i, length($lcom)) eq $lcom && $lcom) { + $i += length($lcom); + $ci = $i; + $st = 2; + next; + } + + if ($pn) { + $t = substr($in, $i, 1); + if ($t eq '(') { + ++$pn; + ++$i; + next; + } + elsif ($t eq ',') { + if ($pn == 1) { + push(@args, substr($in, $pi, $i-$pi)); + $pi = $i+1; + $st = 3; + } + ++$i; + next; + } + elsif ($t eq ')') { + if (--$pn == 0) { + push(@args, substr($in, $pi, $i-$pi)); + ++$i; + &callm; + $pi = pop(@pi); + $pn = pop(@pn); + next; + } + ++$i; + next; + } + } + + substr($in, $i) =~ /^([a-z_]\w*)(\()?/i || (++$i, next); + defined($D{$1}) || ($i += length($1), next); + + push(@ab, $ab); + push(@args, $1); + $ab = $#args; + push(@mi, $mi); + $mi = $i; + $i += length($&); + + if ($2) { + push(@pi, $pi); + push(@pn, $pn); + $pi = $i; + $pn = 1; + $st = 3; + next; + } + + &callm; + } + $in; +} + +sub callm { + + if (($t = $D{$args[$ab]}) =~ s/^\000//) { + $t = &$t; # may recurse here + } else { + $t =~ s/\$(\#|\*|\@|\d)/$1 eq '#' ? $#args-$ab : + $1 eq '*' ? join(',', @args[$ab+1..$#args]) : + $1 eq '@' ? join(',', "elist(@args[$ab+1..$#args])) : + $args[$ab+$1]/ge; + } + + $ccp && + (substr($in, $mi, $i-$mi) =~ tr/\n/\n/) != ($t =~ tr/\n/\n/) && + ($t =~ s/\n$//, + $t .= sprintf("\n#line %s \"%s\"\n", $line, $ARGV)); + substr($in, $mi, $i-$mi) = $t; + + $i = $mi; # rescan + $#args = $ab-1; + $mi = pop(@mi); + $ab = pop(@ab); +} + +sub quotelist { + local(@T); + for (@_) { + push(@T, $lq . $_ . $rq); + } + @T; +} + +sub setskip { + ($skip = "$lcom$rcom$lq$rq(,)") =~ s/(\W)/\\$1/g; + $skip = "^[^a-zA-Z_$skip]+"; +} + +# m5 functions: + +sub changecom { + $lcom = $args[$ab+1]; + $rcom = $args[$ab+2] || "\n"; + &setskip; + ""; +} + +sub changequote { + $lq = $args[$ab+1]; + $rq = $args[$ab+2] || $lq; + if ($#args <= $ab) { # if no arguments at all + $lq = "\`"; + $rq = "\'"; + } + &setskip; + ""; +} + +sub decr { + $t = $args[$ab+1] - 1; + "$t"; # quotes required for perl bug +} + +sub define { + $args[$ab+1] =~ /^[a-z_]\w*$/i || die "bad macro name: '$args[$ab+1]'\n"; + $D{$args[$ab+1]} = $args[$ab+2]; + ""; +} + +sub defn { + $t = ''; + for (@args[$ab+1..$#args]) { + $t .= $lq . $D{$_} . $rq; + } + $t; +} + +sub dnl { + substr($in, $i) =~ s/[^\n]*\n?//; + ""; +} + +sub dumpdef { + for (sort(keys %D)) { + if (($t = $D{$_}) =~ s/^\000//) { + printf STDERR ("%s:\t<%s>\n", $_, $t); + } else { + printf STDERR ("%s:\t%s%s%s\n", $_, $lq, $t, $rq); + } + } + ""; +} + +sub errprint { + print STDERR $args[$ab+1], "\n"; + ""; +} + +sub eval { + local($r) = int($args[$ab+2]); + package m5; + $main't = eval $main'args[$main'ab+1]; #']; + package main; + $@ && die "eval($args[$ab+1]) failed: $@\n"; + if ($r > 1 && $t =~ s/^(-)?(\d+)$//) { # if a radix is specified + local($d) = $2; + do { + $t = ('0'..'9','A'..'Z')[$d % $r] . $t; + $d = int($d / $r); + } while $d; + + $d = $args[$ab+3] - length($t); + $d > 0 && ($t = ('0' x $d) . $t); + $t = $1 . $t; + } + "$t"; # quotes required for perl bug +} + +sub ifdef { + defined($D{$args[$ab+1]}) ? $args[$ab+2] : $args[$ab+3]; +} + +sub ifelse { + for ($t = $ab+1; $t < $#args; $t += 3) { + $args[$t] eq $args[$t+1] && return "$args[$t+2]"; + } + return "$args[$t]"; # quotes required for perl bug +} + +sub include { + for (@inc) { # search -I list + $t = "$_$args[$ab+1]"; + if (-f $t) { + push(@FH, $FH); + push(@argv, $ARGV); + push(@line, $line); + push(@in, substr($in, $i)); + substr($in, $i) = ''; + &openf($t); + return ""; + } + } + die "Can't find include file $args[$ab+1]"; +} + +sub incr { + $t = $args[$ab+1] + 1; + "$t"; # quotes required for perl bug +} + +sub index { + $t = index($args[$ab+1], $args[$ab+2]); + "$t"; # quotes required for perl bug +} + +sub len { + $t = length($args[$ab+1]); + "$t"; # quotes required for perl bug +} + +sub maketemp { + ($t = $args[$ab+1]) =~ s/X{1,6}$/a$$/; # via experiments + "$t"; # quotes required for perl bug +} + +sub m4exit { + exit($args[$ab+1]); +} + +sub m4wrap { + $m4wrap = $args[$ab+1]; + ""; +} + +sub popdef { + eval "\$D{$args[$ab+1]} = pop(@M5'$args[$ab+1])"; + ""; +} + +sub pushdef { + eval "push(@M5'$args[$ab+1], \$D{$args[$ab+1]})"; + $D{$args[$ab+1]} = $args[$ab+2]; + ""; +} + +sub repeat { # repeat(#, expr); evals expr # times; $0 = 0..#-1 + local($t); + for ($args[$ab] = 0; $args[$ab] < $args[$ab+1]; $args[$ab]++) { + $t .= &expand($args[$ab+2], ''); + } + $t; +} + +sub shift { + join(',', "elist(@args[$ab+2..$#args])); +} + +sub substr { + $t = substr($args[$ab+1], $args[$ab+2], $args[$ab+3] || 1000000000); + "$t"; # quotes required for perl bug +} + +sub syscmd { + $m5'sysval = system($args[$ab+1]); #' this is wrong, but close + ""; +} + +sub undefine { + delete $D{$args[$ab+1]}; + ""; +} + +- ---------------------- end ---------------------- + diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdependC.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdependC.prl new file mode 100644 index 0000000000..edffc6b7ba --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdependC.prl @@ -0,0 +1,186 @@ +# *** MSUB does some substitutions here *** +# *** grep for $( *** +# +# tries to work like mkdependC +# +# ToDo: strip out all the .h junk +# +($Pgm = $0) =~ s/.*\/([^\/]+)$/\1/; +$Usage = "usage: $Pgm: not done yet\n"; + +$Status = 0; # just used for exit() status +$Verbose = ''; +$Dashdashes_seen = 0; + +$Begin_magic_str = "# DO NOT DELETE: Beginning of C dependencies\n"; +$End_magic_str = "# DO NOT DELETE: End of C dependencies\n"; +$Obj_suffix = '.o'; +@Defines = (); +$Include_dirs = ''; +$Col_width = 78; # ignored +$Makefile = ''; +@Src_files = (); + +&mangle_command_line_args(); + +if ( ! $Makefile && -f 'makefile' ) { + $Makefile = 'makefile'; +} elsif ( ! $Makefile && -f 'Makefile') { + $Makefile = 'Makefile'; +} else { + die "$Pgm: no makefile or Makefile found\n"; +} + +@Depend_lines = (); +%Depend_seen = (); + +print STDERR "CPP defines=@Defines\n" if $Verbose; +print STDERR "Include_dirs=$Include_dirs\n" if $Verbose; + +foreach $sf (@Src_files) { + # just like lit-inputter + # except it puts each file through CPP and + # a de-commenter (not implemented); + # builds up @Depend_lines + print STDERR "Here we go for source file: $sf\n" if $Verbose; + ($of = $sf) =~ s/\.(c|hc)$/$Obj_suffix/; + + &slurp_file($sf, 'fh00'); +} + +# OK, mangle the Makefile +unlink("$Makefile.bak"); +rename($Makefile,"$Makefile.bak"); +# now copy Makefile.bak into Makefile, rm'ing old dependencies +# and adding the new +open(OMKF,"< $Makefile.bak") || die "$Pgm: can't open $Makefile.bak: $!\n"; +open(NMKF,"> $Makefile") || die "$Pgm: can't open $Makefile: $!\n"; +select(NMKF); +$_ = ; +while ($_ && $_ ne $Begin_magic_str) { # copy through, 'til Begin_magic_str + print $_; + $_ = ; +} +while ($_ && $_ ne $End_magic_str) { # delete 'til End_magic_str + $_ = ; +} +# insert dependencies +print $Begin_magic_str; +print @Depend_lines; +print $End_magic_str; +while () { # copy the rest through + print $_; +} +close(NMKF); +close(OMKF); +chmod 0444, 'Makefile'; +exit 0; + +sub mangle_command_line_args { + while($_ = $ARGV[0]) { + shift(@ARGV); + + if ( /^--$/ ) { + $Dashdashes_seen++; + + } elsif ( /^-D(.*)/ ) { # recognized wherever they occur + push(@Defines, $_); + } elsif ( /^-I/ ) { + $Include_dirs .= " $_"; + + } elsif ($Dashdashes_seen != 1) { # not between -- ... -- + if ( /^-v$/ ) { + $Verbose = '-v'; + } elsif ( /^-f/ ) { + $Makefile = &grab_arg_arg($_); + } elsif ( /^-o/ ) { + $Obj_suffix = &grab_arg_arg($_); + } elsif ( /^-bs/ ) { + $Begin_magic_str = &grab_arg_arg($_) . "\n"; + } elsif ( /^-es/ ) { + $End_magic_str = &grab_arg_arg($_) . "\n"; + } elsif ( /^-w/ ) { + $Width = &grab_arg_arg($_); + } elsif ( /^-/ ) { + print STDERR "$Pgm: unknown option ignored: $_\n"; + } else { + push(@Src_files, $_); + } + + } elsif ($Dashdashes_seen == 1) { # where we ignore unknown options + push(@Src_files,$_) if ! /^-/; + } + } +} + +sub grab_arg_arg { + local($option) = @_; + local($rest_of_arg); + + ($rest_of_arg = $option) =~ s/^-.//; + + if ($rest_of_arg) { + return($rest_of_arg); + } elsif ($#ARGV >= 0) { + local($temp) = $ARGV[0]; shift(@ARGV); + return($temp); + } else { + die "$Pgm: no argument following $option option\n"; + } +} + +sub slurp_file { # follows an example in the `open' item in perl man page + local($fname,$fhandle) = @_; + local($depend); # tmp + $fhandle++; # a string increment + + $fname = &tidy_dir_names($fname); + + unless (open($fhandle, "$(CPP) $Include_dirs @Defines $fname |")) { + die "$Pgm: Can't open $fname: $!\n"; + } + line: while (<$fhandle>) { + next line if ! /^#/; + next line if /^#(ident|pragma)/; + chop; # rm trailing newline + + $_ = &tidy_dir_names($_); + + # strip junk off the front and back + $_ =~ s/^#\s+\d+\s+//; + $_ =~ s/[ 0-9]*$//; + + # a little bit of ad-hoc fiddling now: + # don't bother w/ dependencies on /usr/include stuff + # don't bother if it looks like a GCC built-in hdr file + # don't bother with "literate" .h files (.lh); we'll just + # depend on the de-litified versions (which have better info) + # don't let a file depend on itself + next line if /^\/usr\/include/; + next line if /\/gcc-lib\/[^\/\n]+\/[\.0-9]+\/include\//; + next line if /\.lh$/; + next line if $_ eq $fname; + + print STDERR "$fname :: $_\n" if $Verbose; + + # ToDo: some sanity checks that we still have something reasonable? + + $depend = "$of : $_\n"; + next line if $Depend_seen{$depend}; # already seen this one... + + # OK, it's a new one. + push (@Depend_lines, $depend); + $Depend_seen{$depend} = 1; + } + close($fhandle); +} + +sub tidy_dir_names { # rm various pernicious dir-name combinations... + local($str) = @_; + + $str =~ s|/[^/.][^/]*/\.\.||g; # nuke: //.. + $str =~ s|/\.[^.][^/]*/\.\.||g; # nuke: /./.. (and others) + $str =~ s|"||g; + $str =~ s| \./| |; + $str; +} diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.man b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.man new file mode 100644 index 0000000000..999fa12822 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.man @@ -0,0 +1,15 @@ +.TH MKDIRHIER 1 "Release 4" "X Version 11" +.SH NAME +mkdirhier \- makes a directory hierarchy +.SH SYNOPSIS +.B mkdirhier +directory ... +.SH DESCRIPTION +The +.I mkdirhier +command creates the specified directories. Unlike +.I mkdir +if any of the parent directories of the specified directory +do not exist, it creates them as well. +.SH "SEE ALSO" +mkdir(1) diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.sh b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.sh new file mode 100644 index 0000000000..739535e118 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkdirhier.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# +# create a heirarchy of directories +# + +for f in $*; do + parts=`echo $f | sed 's,\(.\)/\(.\),\1 \2,g' | sed 's,/$,,'`; + path=""; + for p in $parts; do + if [ x"$path" = x ]; then + dir=$p; + else + dir=$path/$p; + fi; + if [ ! -d $dir ]; then + echo mkdir $dir; + mkdir $dir; + chmod a+rx $dir; + fi; + path=$dir; + done; +done + diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkshadowfile.sh b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkshadowfile.sh new file mode 100644 index 0000000000..a00ede08e0 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/mkshadowfile.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# +# create a heirarchy of directories (mkdir that makes everything) +# + +USAGE="Usage: $0 master-src-dir-root shadow-src-dir-root filename-from-master-root" + +for f in $*; do + parts=`echo $f | sed 's,\(.\)/\(.\),\1 \2,g' | sed 's,/$,,'`; + path=""; + for p in $parts; do + if [ x"$path" = x ]; then + dir=$p; + else + dir=$path/$p; + fi; + if [ ! -d $dir ]; then + echo mkdir $dir; + mkdir $dir; + chmod a+rx $dir; + fi; + path=$dir; + done; +done +exit 0 diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/moan-if-old.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/moan-if-old.prl new file mode 100644 index 0000000000..9b7c0b98bc --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/moan-if-old.prl @@ -0,0 +1,49 @@ +# "moan" if files in this directory tree appear to be out-of-date +# with respect to a given "master directory". +# +# a utility to use with link trees! +# +# usage: +# % moan-if-old /src/ghc-master-copy + +$Verbose = 1; +$Usage = "usage: moan-if-old master-dir\n"; + +if ($#ARGV != 0) { + die $Usage; +} else { + $Master_dir = $ARGV[0]; + die "no such dir: $Master_dir\n$Usage" if ! -d $Master_dir; +} + +open(F,"find . -type f -print |") || die "Cannot open find ($!)"; +while () { + chop; + + if (! -f "$Master_dir/$_" && ! &junk_file($_) ) { + print STDERR "$_ : not in master directory\n"; + + } elsif (-f "$Master_dir/$_") { + + $f1 = "$Master_dir/$_"; + $f2 = $_; + + @m_dope = stat($f1); + @s_dope = stat($f2); + if ($m_dope[9] > $s_dope[9]) { # those are modification times... + print STDERR "$f1 ($m_dope[9]) > $f2 ($s_dope[9])\n" if $Verbose; + print STDERR "$_ : older\n"; + } + } +} +close(F); + +sub junk_file { + local($_) = @_; + + if ( /~$/ || /\.bak$/ || /-(PREV|OLD|SAVE|NEW)$/ ) { + return(1); + } else { + return(0); + } +} diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/perltags.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/perltags.prl new file mode 100644 index 0000000000..d7bf6129cb --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/perltags.prl @@ -0,0 +1,69 @@ +# perl tags, in perl. +# @(#)ptags 1.2 4/11/91, no copyright. Bugfixes to lm@eng.sun.com. + +#In the hack-of-the-hour catagory, a tags file generator for perl. Differences +#from ctags: +# +# 1) Puts a tag in for the filename +# 2) Puts in multiple tags for the same symbol (I have a hacked version +# of vi that groks this). + +# tag file +# catch /u/lm/tmp/eintr.c /^catch() {}$/ + +if ($#ARGV == -1) { + unshift(@ARGV, "-"); +} +open(STDOUT, ">> TAGS") || die "can't create TAGS"; # partain: NB: APPEND +while ($_ = shift) { + next unless -f $_; + print STDERR "$_\n" if $v; + do file($_); +} +exit; + +sub file +{ + local($name) = $_[0]; + + open(F, $name) || return; + $entries = ''; + $lcnt = 1; + $ccnt = 0; + + while () { + # skip the word sub in comments + next unless /^[^#]*\bsub\b/; + # skip the word sub in a string (one line only, I'm lazy) + next if /"[^"]*sub/; +# print "$name: $. $_" if $d; + # demand that "sub" is first on the line (partain) + # (the initial > is for some literate perl scripts...) + next if ! /^>?\s*sub\s+/; + chop; + # rm comments + s/#.*$//; + # and here's the entry... + $entries .= "$_\x7f$lcnt,$ccnt\n"; + $lcnt++; + $ccnt += length($_); + } + # print tag for filename + print "\f\n$name,",length($entries),"\n"; + print $entries; +} + +###I've always used this. Don't recall whom I got it from... +## +##--tom +## +###!/usr/local/bin/perl +#open(OUTPUT, "| sort >> TAGS"); +#while (<>) { +# if (/\bsub\s+(\w+')?(\S+)/) { +# $func = $2; +# chop; +# s,[\\\[\]/.*],\\$&,g; +# print OUTPUT "$func\t", $ARGV, "\t/^$_\$/\n"; +# } +#} diff --git a/web/glasgow/lit2x-0.16/grasp-utils/scripts/runstdtest.prl b/web/glasgow/lit2x-0.16/grasp-utils/scripts/runstdtest.prl new file mode 100644 index 0000000000..48e6cc28a8 --- /dev/null +++ b/web/glasgow/lit2x-0.16/grasp-utils/scripts/runstdtest.prl @@ -0,0 +1,184 @@ +#! /usr/local/bin/perl +# +# Given: +# * a program to run (1st arg) +# * some "command-line opts" ( -O -O ... ) +# [default: anything on the cmd line this script doesn't recognise ] +# the first opt not starting w/ "-" is taken to be an input +# file and (if it exists) is grepped for "what's going on here" +# comments (^--!!!). +# * a file to feed to stdin ( -i ) [default: /dev/null ] +# * a "time" command to use (-t ). +# +# * alternatively, a "-script