home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume2 / lint-c-front / lint.c
Encoding:
C/C++ Source or Header  |  1991-08-07  |  6.3 KB  |  349 lines

  1. /*
  2. **  If only for hack value, a C version of the old-fashioned lint script.
  3. */
  4. #include <stdio.h>
  5. #include <fcntl.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <signal.h>
  9.  
  10. /* Fundamental constants of the universe. */
  11. #define ARG_CNT        30
  12. #define TRUE        1
  13. #define FALSE        0
  14.  
  15. /* Argument lists. */
  16. char    *Lint1[ARG_CNT]    = {
  17.     "/usr/lib/lint/lint1"
  18. };
  19. int     Lint1C        = 1;
  20.  
  21. char    *Lint2[ARG_CNT]    = {
  22.     "/usr/lib/lint/lint2"
  23. };
  24. int     Lint2C        = 1;
  25.  
  26. char    *Cpp[ARG_CNT]    = {
  27.     "/lib/cpp",
  28.     "-DLINT",
  29.     "-Dlint",
  30.     "-C"
  31. };
  32. int     CppC        = 4;
  33.  
  34. /* Other global variables. */
  35. char     Htemp[]    = "/tmp/lintHXXXXXX";
  36. char     Ttemp[]    = "/tmp/lintTXXXXXX";
  37. int     Libstat;
  38. int     Tfid;
  39.  
  40. /* Linked in later. */
  41. extern int     errno;
  42. extern char    *calloc();
  43. extern char    *mktemp();
  44. extern char    *strcpy();
  45. extern char    *strchr();
  46. extern char    *strrchr();
  47. /*+GETOPT ROUTINE
  48.  *
  49.  * A hacked-over version of the one in the standard library.
  50.  */
  51.  
  52. int     optind = 1;
  53. char    *optarg;
  54.  
  55. int
  56. getopt(ac, av, opts)
  57.     int              ac;
  58.     char        **av;
  59.     char         *opts;
  60. {
  61.     static int          sp = 1;
  62.     register int      c;
  63.     register char     *cp;
  64.  
  65.     if (sp == 1)
  66.     if (optind >= ac || av[optind][0] != '-' || av[optind][1] == '\0')
  67.         return('\0');
  68.     else if (strcmp(av[optind], "--") == 0)
  69.     {
  70.         optind++;
  71.         return('\0');
  72.     }
  73.  
  74.     c = av[optind][sp];
  75.     if (c == ':' || (cp = strchr(opts, c)) == NULL)
  76.     yelp("illegal option \"%c\"", c);
  77.     if (*++cp == ':')
  78.     {
  79.     if (av[optind][sp + 1] != '\0')
  80.         optarg = &av[optind++][sp + 1];
  81.     else if (++optind >= ac)
  82.         yelp("option \"%c\" requires an argument", c);
  83.     else
  84.         optarg = av[optind++];
  85.     sp = 1;
  86.     }
  87.     else
  88.     {
  89.     if (av[optind][++sp] == '\0')
  90.     {
  91.         sp = 1;
  92.         optind++;
  93.     }
  94.     optarg = NULL;
  95.     }
  96.     return(c);
  97. }
  98. /*+SIGNAL CATCHERS AND EXITS
  99.  */
  100.  
  101.  
  102. #ifdef    LINT
  103. extern void     exit();
  104. #else
  105. exit(X)    int X;     { _exit(X); }
  106. #endif    LINT
  107.  
  108.  
  109. /* VARARGS1 */
  110. yelp(A, B)
  111.     char    *A;
  112.     char    *B;
  113. {
  114.     int         E;
  115.  
  116.     E = errno;
  117.     printf(A, B);
  118.     printf(" (errno = %d).\n", E);
  119.     exit(1);
  120. }
  121.  
  122.  
  123. Rupt()
  124. {
  125.     (void)unlink(Htemp);
  126.     (void)unlink(Ttemp);
  127.     yelp("\r\nInterrupted!\r\n");
  128.     /* NOTREACHED */
  129. }
  130. /*+UTILITY ROUTINES
  131.  */
  132.  
  133.  
  134. /*
  135.  * This routine appends a lint library to the T file.
  136.  */
  137. Lib(N, Flag)
  138.     char        *N;
  139.     int             Flag;
  140. {
  141.     register int     F;
  142.     register int     i;
  143.     char         Buff[BUFSIZ];
  144.  
  145.     if (Flag)
  146.     sprintf(Buff, "/usr/lib/lint/llib-l%s.ln", N);
  147.     else
  148.     (void)strcpy(Buff, N);
  149.  
  150.     if ((F = open(Buff, O_RDONLY)) < 0)
  151.     printf("cannot open \"%s\" lint library (errno=%d)", Buff, errno);
  152.     else
  153.     {
  154.     while ((i = read(F, Buff, sizeof Buff)) > 0)
  155.         (void)write(Tfid, Buff, (unsigned int)i);
  156.     (void)close(F);
  157.     }
  158. }
  159.  
  160.  
  161. /*
  162.  * This routine concats an argument to an arglist, perhaps preceeding
  163.  * it with a minus sign and a letter.
  164.  */
  165. Add(C, Alist, Arg, Simple)
  166.     int          C;
  167.     char    **Alist;
  168.     char     *Arg;
  169.     char      Simple;
  170. {
  171.     int              L;
  172.     register char     *p;
  173.  
  174.     if (C >= ARG_CNT - 2)
  175.     yelp("too many arguments");
  176.     /* NOTREACHED */
  177.  
  178.     L = strlen(Arg) + 1;
  179.     if (Simple)
  180.     L += 2;
  181.     p = Alist[C] = calloc((unsigned int)L, 1);
  182.     if (Simple)
  183.     {
  184.     *p++ = '-';
  185.     *p++ = Simple;
  186.     }
  187.     (void)strcpy(p, Arg);
  188. }
  189. /*!*/
  190. /*
  191.  *  This routine is implements this line from the script:
  192.  *    (/lib/cpp $O $A | $L/lint1 $X -H$H $A >>$T) 2>&1
  193.  */
  194. Do(N)
  195.     char    *N;
  196. {
  197.     int         P[2];
  198.  
  199.     if (fork() == 0)
  200.     {
  201.     /* The kids run "... 2>&1" */
  202.     (void)close(2);
  203.     (void)dup(1);
  204.     (void)pipe(P);
  205.  
  206.     Cpp[CppC]    = N;
  207.     Lint1[Lint1C]    = N;
  208.  
  209.     if (fork() == 0)
  210.     {
  211.         /* Younger child runs "cpp | ..." */
  212.         (void)close(1);
  213.         (void)dup(P[1]);
  214.         (void)close(P[1]);
  215.         (void)close(P[0]);
  216.         (void)close(Tfid);
  217.         (void)execv(Cpp[0], Cpp);
  218.         yelp("No cpp?");
  219.         /* NOTREACHED */
  220.     }
  221.     else
  222.     {
  223.         /* Older child runs "... | lint >> Tfid" */
  224.         (void)close(0);
  225.         (void)dup(P[0]);
  226.         (void)close(P[0]);
  227.         (void)close(P[1]);
  228.         (void)close(1);
  229.         (void)dup(Tfid);
  230.         (void)close(Tfid);
  231.         (void)execv(Lint1[0], Lint1);
  232.         yelp("No lint1?");
  233.         /* NOTREACHED */
  234.     }
  235.     }
  236.     else
  237.     (void)wait((int *)0);
  238. }
  239. /*+MAIN ROUTINE
  240.  */
  241.  
  242.  
  243. main(ac, av)
  244.     register int     ac;
  245.     register char    *av[];
  246. {
  247.     register char    *p;
  248.     register int     c;
  249.     struct stat         Sb;
  250.  
  251.     (void)mktemp(Htemp);
  252.     (void)mktemp(Ttemp);
  253.     Tfid = open(Ttemp, O_RDWR | O_CREAT | O_APPEND, 0666);
  254.     Add(Lint2C++, Lint2, Ttemp, 'T');
  255.  
  256.     /* Parse JCL. */
  257.     while (c = getopt(ac, av, "abhuvxI:D:U:Nnpl:o:"))
  258.     switch (c)
  259.     {
  260.         /* [abhuvx] -- standard lint flags. */
  261.         case 'a': case 'b': case 'h': case 'u': case 'v': case 'x':
  262.         Add(Lint1C++, Lint1, "", c);
  263.         Add(Lint2C++, Lint2, "", c);
  264.         break;
  265.         /* [DIU] -- standard cpp flags. */
  266.         case 'D': case 'I': case 'U':
  267.         Add(CppC++, Cpp, optarg, c);
  268.         break;
  269.         /* p -- portable library. */
  270.         case 'p':
  271.         Add(Lint1C++, Lint1, "", c);
  272.         Add(Lint2C++, Lint1, "", c);
  273.         /* [Nn] -- net or no library. */
  274.         case 'N': case 'n':
  275.         Libstat = c;
  276.         break;
  277.         /* l -- lint library. */
  278.         case 'l':
  279.         Lib(optarg, TRUE);
  280.         break;
  281.         /* o -- output file (redirection without meta chars). */
  282.         case 'o':
  283.         (void)close(1);
  284.         (void)open(optarg, O_WRONLY | O_CREAT | O_TRUNC, 0666);
  285.         break;
  286.     }
  287.  
  288.     Add(Lint1C++, Lint1, Htemp, 'H');
  289.     Add(Lint2C++, Lint2, Htemp, 'H');
  290.     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
  291.     (void)signal(SIGINT, Rupt);
  292.  
  293.     /* Did flags; do filenames and libraries. */
  294.     for (; optind < ac; optind++)
  295.     {
  296.     /* Check for -l.. argument. */
  297.     if (*(p = av[optind]) == '-' && *++p == 'l')
  298.     {
  299.         Lib(++p, TRUE);
  300.         continue;
  301.     }
  302.  
  303.     /* Check for *.c for *.ln arguments. */
  304.     if (p = strrchr(av[optind], '.'))
  305.     {
  306.         if (*++p == 'c' && p[1] == '\0')
  307.         {
  308.         Do(av[optind]);
  309.         continue;
  310.         }
  311.         if (p[0] == 'l' && p[1] == 'n' && p[2] == '\0')
  312.         {
  313.         Lib(av[optind], FALSE);
  314.         continue;
  315.         }
  316.     }
  317.     printf("Not grokked -- \"%s\" -- ignored\n", av[optind]);
  318.     }
  319.  
  320.     /* Any standard C library? */
  321.     switch (Libstat)
  322.     {
  323.     case '\0':    Lib("c", TRUE);        break;
  324.     case 'N':    Lib("netc", TRUE);
  325.             Lib("net", TRUE);    break;
  326.     case 'p':    Lib("port", TRUE);    break;
  327.     }
  328.  
  329.     (void)close(Tfid);
  330.  
  331.     /* If lint1 created anything, run lint2. */
  332.     if (stat(Htemp, &Sb) >= 0 && Sb.st_size >= 0)
  333.     {
  334.     Add(Lint2C, Lint2, Htemp, 'H');
  335.     if (fork() == 0)
  336.     {
  337.         (void)execv(Lint2[0], Lint2);
  338.         yelp("No lint2?");
  339.         /* NOTREACHED */
  340.     }
  341.     (void)wait((int *)0);
  342.     }
  343.  
  344.     /* That's all she wrote. */
  345.     (void)unlink(Htemp);
  346.     (void)unlink(Ttemp);
  347.     exit(0);
  348. }
  349.