rsalz@pineapple.bbn.com (02/06/88)
Comp.sources.misc: Volume 2, Issue 45 Submitted-By: "Rich $alz" <rsalz@pineapple.BBN.COM> Archive-Name: lint-c-front Comp.sources.misc: Volume 2, Issue 45 Submitted-By: "Rich $alz" <rsalz@pineapple.BBN.COM> Archive-Name: lint-c-front A couple of jobs ago I worked on SysV UniSoft machines, and shell scripts were painfully slow. To make sure I knew pipe/fork/exec/wait semantics, I rewrote the lint script into C code. The games with exit and _exit helped shrink program size; a colleague printf/sprinf library that didn't use standard I/O, so this whole program was under 8K. As a minimum, some folks might find the transliteration of (/lib/cpp $O $A | $L/lint1 $X -H$H $A >>$T) 2>&1 useful, amusing, or maybe even buggy. I know it worked back then... Enjoy, /r$ #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g. PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'lint.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'lint.c'\" else echo shar: Extracting \"'lint.c'\" \(6486 characters\) sed "s/^X//" >'lint.c' <<'END_OF_FILE' X/* X** If only for hack value, a C version of the old-fashioned lint script. X*/ X#include <stdio.h> X#include <fcntl.h> X#include <sys/types.h> X#include <sys/stat.h> X#include <signal.h> X X/* Fundamental constants of the universe. */ X#define ARG_CNT 30 X#define TRUE 1 X#define FALSE 0 X X/* Argument lists. */ Xchar *Lint1[ARG_CNT] = { X "/usr/lib/lint/lint1" X}; Xint Lint1C = 1; X Xchar *Lint2[ARG_CNT] = { X "/usr/lib/lint/lint2" X}; Xint Lint2C = 1; X Xchar *Cpp[ARG_CNT] = { X "/lib/cpp", X "-DLINT", X "-Dlint", X "-C" X}; Xint CppC = 4; X X/* Other global variables. */ Xchar Htemp[] = "/tmp/lintHXXXXXX"; Xchar Ttemp[] = "/tmp/lintTXXXXXX"; Xint Libstat; Xint Tfid; X X/* Linked in later. */ Xextern int errno; Xextern char *calloc(); Xextern char *mktemp(); Xextern char *strcpy(); Xextern char *strchr(); Xextern char *strrchr(); X/*+GETOPT ROUTINE X * X * A hacked-over version of the one in the standard library. X */ X Xint optind = 1; Xchar *optarg; X Xint Xgetopt(ac, av, opts) X int ac; X char **av; X char *opts; X{ X static int sp = 1; X register int c; X register char *cp; X X if (sp == 1) X if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0') X return('\0'); X else if (strcmp(av[optind], "--") == 0) X { X optind++; X return('\0'); X } X X c = av[optind][sp]; X if (c == ':' || (cp = strchr(opts, c)) == NULL) X yelp("illegal option \"%c\"", c); X if (*++cp == ':') X { X if (av[optind][sp + 1] != '\0') X optarg = &av[optind++][sp + 1]; X else if (++optind >= ac) X yelp("option \"%c\" requires an argument", c); X else X optarg = av[optind++]; X sp = 1; X } X else X { X if (av[optind][++sp] == '\0') X { X sp = 1; X optind++; X } X optarg = NULL; X } X return(c); X} X/*+SIGNAL CATCHERS AND EXITS X */ X X X#ifdef LINT Xextern void exit(); X#else Xexit(X) int X; { _exit(X); } X#endif LINT X X X/* VARARGS1 */ Xyelp(A, B) X char *A; X char *B; X{ X int E; X X E = errno; X printf(A, B); X printf(" (errno = %d).\n", E); X exit(1); X} X X XRupt() X{ X (void)unlink(Htemp); X (void)unlink(Ttemp); X yelp("\r\nInterrupted!\r\n"); X /* NOTREACHED */ X} X/*+UTILITY ROUTINES X */ X X X/* X * This routine appends a lint library to the T file. X */ XLib(N, Flag) X char *N; X int Flag; X{ X register int F; X register int i; X char Buff[BUFSIZ]; X X if (Flag) X sprintf(Buff, "/usr/lib/lint/llib-l%s.ln", N); X else X (void)strcpy(Buff, N); X X if ((F = open(Buff, O_RDONLY)) < 0) X printf("cannot open \"%s\" lint library (errno=%d)", Buff, errno); X else X { X while ((i = read(F, Buff, sizeof Buff)) > 0) X (void)write(Tfid, Buff, (unsigned int)i); X (void)close(F); X } X} X X X/* X * This routine concats an argument to an arglist, perhaps preceeding X * it with a minus sign and a letter. X */ XAdd(C, Alist, Arg, Simple) X int C; X char **Alist; X char *Arg; X char Simple; X{ X int L; X register char *p; X X if (C >= ARG_CNT - 2) X yelp("too many arguments"); X /* NOTREACHED */ X X L = strlen(Arg) + 1; X if (Simple) X L += 2; X p = Alist[C] = calloc((unsigned int)L, 1); X if (Simple) X { X *p++ = '-'; X *p++ = Simple; X } X (void)strcpy(p, Arg); X} X/*!*/ X/* X * This routine is implements this line from the script: X * (/lib/cpp $O $A | $L/lint1 $X -H$H $A >>$T) 2>&1 X */ XDo(N) X char *N; X{ X int P[2]; X X if (fork() == 0) X { X /* The kids run "... 2>&1" */ X (void)close(2); X (void)dup(1); X (void)pipe(P); X X Cpp[CppC] = N; X Lint1[Lint1C] = N; X X if (fork() == 0) X { X /* Younger child runs "cpp | ..." */ X (void)close(1); X (void)dup(P[1]); X (void)close(P[1]); X (void)close(P[0]); X (void)close(Tfid); X (void)execv(Cpp[0], Cpp); X yelp("No cpp?"); X /* NOTREACHED */ X } X else X { X /* Older child runs "... | lint >> Tfid" */ X (void)close(0); X (void)dup(P[0]); X (void)close(P[0]); X (void)close(P[1]); X (void)close(1); X (void)dup(Tfid); X (void)close(Tfid); X (void)execv(Lint1[0], Lint1); X yelp("No lint1?"); X /* NOTREACHED */ X } X } X else X (void)wait((int *)0); X} X/*+MAIN ROUTINE X */ X X Xmain(ac, av) X register int ac; X register char *av[]; X{ X register char *p; X register int c; X struct stat Sb; X X (void)mktemp(Htemp); X (void)mktemp(Ttemp); X Tfid = open(Ttemp, O_RDWR | O_CREAT | O_APPEND, 0666); X Add(Lint2C++, Lint2, Ttemp, 'T'); X X /* Parse JCL. */ X while (c = getopt(ac, av, "abhuvxI:D:U:Nnpl:o:")) X switch (c) X { X /* [abhuvx] -- standard lint flags. */ X case 'a': case 'b': case 'h': case 'u': case 'v': case 'x': X Add(Lint1C++, Lint1, "", c); X Add(Lint2C++, Lint2, "", c); X break; X /* [DIU] -- standard cpp flags. */ X case 'D': case 'I': case 'U': X Add(CppC++, Cpp, optarg, c); X break; X /* p -- portable library. */ X case 'p': X Add(Lint1C++, Lint1, "", c); X Add(Lint2C++, Lint1, "", c); X /* [Nn] -- net or no library. */ X case 'N': case 'n': X Libstat = c; X break; X /* l -- lint library. */ X case 'l': X Lib(optarg, TRUE); X break; X /* o -- output file (redirection without meta chars). */ X case 'o': X (void)close(1); X (void)open(optarg, O_WRONLY | O_CREAT | O_TRUNC, 0666); X break; X } X X Add(Lint1C++, Lint1, Htemp, 'H'); X Add(Lint2C++, Lint2, Htemp, 'H'); X if (signal(SIGINT, SIG_IGN) != SIG_IGN) X (void)signal(SIGINT, Rupt); X X /* Did flags; do filenames and libraries. */ X for (; optind < ac; optind++) X { X /* Check for -l.. argument. */ X if (*(p = av[optind]) == '-' && *++p == 'l') X { X Lib(++p, TRUE); X continue; X } X X /* Check for *.c for *.ln arguments. */ X if (p = strrchr(av[optind], '.')) X { X if (*++p == 'c' && p[1] == '\0') X { X Do(av[optind]); X continue; X } X if (p[0] == 'l' && p[1] == 'n' && p[2] == '\0') X { X Lib(av[optind], FALSE); X continue; X } X } X printf("Not grokked -- \"%s\" -- ignored\n", av[optind]); X } X X /* Any standard C library? */ X switch (Libstat) X { X case '\0': Lib("c", TRUE); break; X case 'N': Lib("netc", TRUE); X Lib("net", TRUE); break; X case 'p': Lib("port", TRUE); break; X } X X (void)close(Tfid); X X /* If lint1 created anything, run lint2. */ X if (stat(Htemp, &Sb) >= 0 && Sb.st_size >= 0) X { X Add(Lint2C, Lint2, Htemp, 'H'); X if (fork() == 0) X { X (void)execv(Lint2[0], Lint2); X yelp("No lint2?"); X /* NOTREACHED */ X } X (void)wait((int *)0); X } X X /* That's all she wrote. */ X (void)unlink(Htemp); X (void)unlink(Ttemp); X exit(0); X} END_OF_FILE if test 6486 -ne `wc -c <'lint.c'`; then echo shar: \"'lint.c'\" unpacked with wrong size! fi # end of 'lint.c' fi echo shar: End of shell archive. exit 0