home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / program / d / elvis / Source / c / cgrind < prev    next >
Encoding:
Text File  |  1989-12-31  |  5.5 KB  |  304 lines

  1. /* cgrind.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    16820 SW Tallac Way
  6.  *    Beaverton, OR 97006
  7.  *    kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
  8.  */
  9.  
  10.  
  11. /* This file contains the complete source-code for the cgrind program. */
  12.  
  13. /* Cgrind underlines C's reserved words, and emboldens function names.
  14.  * It does this by inserting "\fB", "\fU", and "\fR" into the file.
  15.  *    usage: cgrind [file.c]... >file
  16.  */
  17.  
  18. #include <stdio.h>
  19. #include <ctype.h>
  20.  
  21. /* These store the fonts that are used for various parts of the source */
  22. char    font_reserved = 'U';
  23. char    font_function = 'B';
  24. char    font_comment = '\0';
  25. char    font_string = '\0';
  26.  
  27. /* This array contains all C reserved words.  The words are segregated
  28.  * according to their first letter, to speed lookups
  29.  */
  30. char *reserved[26][5] =
  31. {
  32.     {"auto"},
  33.     {"break"},
  34.     {"case", "char", "continue"},
  35.     {"default", "do", "double"},
  36.     {"else", "enum", "extern"},
  37.     {"far", "float", "for"},
  38.     {"goto"},
  39.     {(char *)0},
  40.     {"if", "int"},
  41.     {(char *)0},
  42.     {(char *)0},
  43.     {"long"},
  44.     {(char *)0},
  45.     {"near"},
  46.     {(char *)0},
  47.     {(char *)0},
  48.     {(char *)0},
  49.     {"register", "return"},
  50.     {"short", "sizeof", "static", "struct", "switch"},
  51.     {"typedef"},
  52.     {"union", "unsigned"},
  53.     {"void", "volatile"},
  54.     {"while"},
  55.     {(char *)0},
  56.     {(char *)0},
  57.     {(char *)0},
  58. };
  59.  
  60. /* the program name, for diagnostics */
  61. char    *progname;
  62.  
  63. main(argc, argv)
  64.     int    argc;    /* number of command-line args */
  65.     char    **argv;    /* values of the command line args */
  66. {
  67.     FILE    *fp;
  68.     int    i;
  69.  
  70.     progname = argv[0];
  71.  
  72.     /* parse the flags */
  73.     for (i = 1; i < argc && *argv[i] == '-'; i++)
  74.     {
  75.         switch (argv[i][1])
  76.         {
  77.           case 'r':
  78.             font_reserved = argv[i][2];
  79.             break;
  80.  
  81.           case 'f':
  82.             font_function = argv[i][2];
  83.             break;
  84.  
  85.           case 'c':
  86.             font_comment = argv[i][2];
  87.             break;
  88.  
  89.           case 's':
  90.             font_string = argv[i][2];
  91.             break;
  92.  
  93.           default:
  94.             fputs(progname, stderr);
  95.             fputs(": invalid flag (valid ones are -rC -fC -cC -sC)\n", stderr);
  96.             exit(2);
  97.         }
  98.     }
  99.  
  100.     if (i == argc)
  101.     {
  102.         /* probably shouldn't read from keyboard */
  103.         if (isatty(fileno(stdin)))
  104.         {
  105.             fputs("usage: ", stderr);
  106.             fputs(progname, stderr);
  107.             fputs(" [-rC] [-fC] [-cC] [-sC] [filename.c]...\n", stderr);
  108.             exit(3);
  109.         }
  110.  
  111.         /* no files named, so use stdin */
  112.         cgrind(stdin);
  113.     }
  114.     else
  115.     {
  116.         for (; i < argc; i++)
  117.         {
  118.             fp = fopen(argv[i], "r");
  119.             if (!fp)
  120.             {
  121.                 perror(argv[i]);
  122.             }
  123.             else
  124.             {
  125.                 cgrind(fp);
  126.                 if (i < argc - 1)
  127.                 {
  128.                     putchar('\f');
  129.                 }
  130.                 fclose(fp);
  131.             }
  132.         }
  133.     }
  134. }
  135.  
  136.  
  137. /* This function does the cgrind thing to a single file */
  138. cgrind(fp)
  139.     FILE    *fp;
  140. {
  141.     char    linebuf[1025];
  142.     char    *fgets();
  143.     char    *ptr;
  144.     int    newfont;
  145.  
  146.     /* for each line ... */
  147.     while (fgets(linebuf, sizeof linebuf, fp))
  148.     {
  149.         /* for each char of the line... */
  150.         for (ptr = linebuf; *ptr; ptr++)
  151.         {
  152.             /* output a font string, if needed */
  153.             newfont = grindchar(ptr);
  154.             if (newfont)
  155.             {
  156.                 putchar('\\');
  157.                 putchar('f');
  158.                 putchar(newfont);
  159.             }
  160.  
  161.             /* output this character */
  162.             putchar(*ptr);
  163.         }
  164.     }
  165. }
  166.  
  167.  
  168. /* This function detects when the font should change.  It should be called
  169.  * for each position in the line of text, including the '\n' or '\0' that
  170.  * marks its end.  This function returns '\0' normally, or one of 'B', 'U',
  171.  * or 'R' to change the font.
  172.  */
  173. grindchar(ptr)
  174.     char    *ptr;    /* pointer to the char to process */
  175. {
  176.     static    font = 'R';    /* start in regular font */
  177.     static    context = '\0';    /* not in string, not in comment */
  178.     static    afternl = 0;    /* after a newline in funny context? */
  179.     static    delay = 0;    /* delay the emission of font? */
  180.     int    i, j, k;
  181.  
  182.     /* if we're in a funny context & get a '\n' or '\0', then make sure we
  183.      * go out of its font during the newline and then go back into it
  184.      */
  185.     if ((*ptr == '\n' || *ptr == '\0') && context)
  186.     {
  187.         afternl = 1;
  188.         delay = 0;
  189.         if (font && font != 'R')
  190.             return 'R';
  191.         return '\0';
  192.     }
  193.     if (afternl && context)
  194.     {
  195.         afternl = 0;
  196.         delay = 0;
  197.         return font;
  198.     }
  199.  
  200.     /* strings */
  201.     if (!context && *ptr == '"')
  202.     {
  203.         context = '"';
  204.         font = font_string;
  205.         delay = 1;
  206.         return '\0';
  207.     }
  208.     if (context == '"' && *ptr == '"')
  209.     {
  210.         context = '\0';
  211.         font = 'R';
  212.         delay = 0;
  213.         return font_string ? 'R' : '\0';
  214.     }
  215.  
  216.     /* comments */
  217.     if (!context && *ptr == '/' && ptr[1] == '*')
  218.     {
  219.         context = '*';
  220.         font = font_comment;
  221.         delay = 0;
  222.         return font;
  223.     }
  224.     if (context == '*' && *ptr == '*' && ptr[1] == '/')
  225.     {
  226.         context = '\0';
  227.         font = 'R';
  228.         if (font_comment)
  229.             delay = 2;
  230.         return '\0';
  231.     }
  232.  
  233.     /* handle delayed output */
  234.     if (delay > 0)
  235.     {
  236.         delay--;
  237.         if (delay == 0)
  238.             return font;
  239.     }
  240.  
  241.     /* within funny contexts, don't look for reserved words or functions */
  242.     if (context)
  243.     {
  244.         return '\0';
  245.     }
  246.  
  247.     /* if this isn't alphanumeric, and font != 'R', then change to 'R' */
  248.     if (!isalnum(*ptr) && *ptr != '_')
  249.     {
  250.         if (font != 'R')
  251.         {
  252.             font = 'R';
  253.             return 'R';
  254.         }
  255.         return '\0';
  256.     }
  257.  
  258.     /* if this *is* alphanumeric, and font != 'R', then it stays the same */
  259.     if ((isalnum(*ptr) || *ptr == '_') && font != 'R')
  260.     {
  261.         return '\0';
  262.     }
  263.  
  264.     /* if neither functions nor reserved words are used, skip! */
  265.     if (!font_function && !font_reserved)
  266.     {
  267.         return '\0';
  268.     }
  269.  
  270.     /* is this a reserved word? */
  271.     if (islower(*ptr))
  272.     {
  273.         i = *ptr - 'a';
  274.         for (j = 0; j < 5 && reserved[i][j]; j++)
  275.         {
  276.             k = strlen(reserved[i][j]);
  277.             if (!strncmp(ptr, reserved[i][j], k) && !islower(ptr[k]))
  278.             {
  279.                 if (font_reserved)
  280.                     font = font_reserved;
  281.                 return font_reserved;
  282.             }
  283.         }
  284.     }
  285.  
  286.     /* is this word followed by a '(' ? */
  287.     do
  288.     {
  289.         ptr++;
  290.     } while (isalnum(*ptr) || *ptr == '_');
  291.     while (*ptr == ' ')
  292.     {
  293.         ptr++;
  294.     }
  295.     if (*ptr == '(')
  296.     {
  297.         if (font_function)
  298.             font = font_function;
  299.         return font_function;
  300.     }
  301.  
  302.     return '\0';
  303. }
  304.