A C version of the lint driver script
rsalz at pineapple.bbn.com
rsalz at pineapple.bbn.com
Sat Feb 6 11:24:31 AEST 1988
Comp.sources.misc: Volume 2, Issue 45
Submitted-By: "Rich $alz" <rsalz at pineapple.BBN.COM>
Archive-Name: lint-c-front
Comp.sources.misc: Volume 2, Issue 45
Submitted-By: "Rich $alz" <rsalz at 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
More information about the Comp.sources.misc
mailing list