home *** CD-ROM | disk | FTP | other *** search
/ Aminet 10 / aminetcdnumber101996.iso / Aminet / dev / c / mkid.lha / src / scan-c.c < prev    next >
C/C++ Source or Header  |  1995-12-03  |  8KB  |  475 lines

  1. /* Copyright (c) 1986, Greg McGary */
  2. static char sccsid[] = "@(#)scan-c.c    1.1 86/10/09";
  3.  
  4. #include    "bool.h"
  5. #include    <stdio.h>
  6. #include    "string.h"
  7. #include    "id.h"
  8.  
  9. char *getCId();
  10. void setCArgs();
  11.  
  12. static void clrCtype();
  13. static void setCtype();
  14.  
  15. #define    I1    0x0001    /* 1st char of an identifier [a-zA-Z_] */
  16. #define    DG    0x0002    /* decimal digit [0-9] */
  17. #define    NM    0x0004    /* extra chars in a hex or long number [a-fA-FxXlL] */
  18. #define    C1    0x0008    /* C comment introduction char: / */
  19. #define    C2    0x0010    /* C comment termination  char: * */
  20. #define    Q1    0x0020    /* single quote: ' */
  21. #define    Q2    0x0040    /* double quote: " */
  22. #define    ES    0x0080    /* escape char: \ */
  23. #define    NL    0x0100    /* newline: \n */
  24. #define    EF    0x0200    /* EOF */
  25. #define    SK    0x0400    /* Make these chars valid for names within strings */
  26.  
  27. /*
  28.     character class membership macros:
  29. */
  30. #define    ISDIGIT(c)    ((rct)[c]&(DG))        /* digit */
  31. #define    ISNUMBER(c)    ((rct)[c]&(DG|NM))    /* legal in a number */
  32. #define    ISEOF(c)    ((rct)[c]&(EF))        /* EOF */
  33. #define    ISID1ST(c)    ((rct)[c]&(I1))        /* 1st char of an identifier */
  34. #define    ISIDREST(c)    ((rct)[c]&(I1|DG))    /* rest of an identifier */
  35. #define    ISSTRKEEP(c)    ((rct)[c]&(I1|DG|SK))    /* keep contents of string */
  36. /*
  37.     The `BORING' classes should be skipped over
  38.     until something interesting comes along...
  39. */
  40. #define    ISBORING(c)    (!((rct)[c]&(EF|NL|I1|DG|Q1|Q2|C1)))    /* fluff */
  41. #define    ISCBORING(c)    (!((rct)[c]&(EF|C2)))    /* comment fluff */
  42. #define    ISQ1BORING(c)    (!((rct)[c]&(EF|NL|Q1|ES)))    /* char const fluff */
  43. #define    ISQ2BORING(c)    (!((rct)[c]&(EF|NL|Q2|ES)))    /* quoted str fluff */
  44.  
  45. static short idctype[] = {
  46.  
  47.     EF,
  48.  
  49.     /*      0       1       2       3       4       5       6       7   */
  50.     /*    -----   -----   -----   -----   -----   -----   -----   ----- */
  51.  
  52.     /*000*/    0,    0,    0,    0,    0,    0,    0,    0,
  53.     /*010*/    0,    0,    NL,    0,    0,    0,    0,    0,
  54.     /*020*/    0,    0,    0,    0,    0,    0,    0,    0,
  55.     /*030*/    0,    0,    0,    0,    0,    0,    0,    0,
  56.     /*040*/    0,    0,    Q2,    0,    0,    0,    0,    Q1,
  57.     /*050*/    0,    0,    C2,    0,    0,    0,    0,    C1,
  58.     /*060*/    DG,    DG,    DG,    DG,    DG,    DG,    DG,    DG,
  59.     /*070*/    DG,    DG,    0,    0,    0,    0,    0,    0,
  60.     /*100*/    0,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1,
  61.     /*110*/    I1,    I1,    I1,    I1,    I1|NM,    I1,    I1,    I1,
  62.     /*120*/    I1,    I1,    I1,    I1,    I1,    I1,    I1,    I1,
  63.     /*130*/    I1|NM,    I1,    I1,    0,    ES,    0,    0,    I1,
  64.     /*140*/    0,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1|NM,    I1,
  65.     /*150*/    I1,    I1,    I1,    I1,    I1|NM,    I1,    I1,    I1,
  66.     /*160*/    I1,    I1,    I1,    I1,    I1,    I1,    I1,    I1,
  67.     /*170*/    I1|NM,    I1,    I1,    0,    0,    0,    0,    0,
  68.  
  69.     /*200*/    0,    0,    0,    0,    0,    0,    0,    0,
  70.     /*210*/    0,    0,    0,    0,    0,    0,    0,    0,
  71.     /*220*/    0,    0,    0,    0,    0,    0,    0,    0,
  72.     /*230*/    0,    0,    0,    0,    0,    0,    0,    0,
  73.     /*240*/    0,    0,    0,    0,    0,    0,    0,    0,
  74.     /*250*/    0,    0,    0,    0,    0,    0,    0,    0,
  75.     /*260*/    0,    0,    0,    0,    0,    0,    0,    0,
  76.     /*270*/    0,    0,    0,    0,    0,    0,    0,    0,
  77.     /*300*/    0,    0,    0,    0,    0,    0,    0,    0,
  78.     /*310*/    0,    0,    0,    0,    0,    0,    0,    0,
  79.     /*320*/    0,    0,    0,    0,    0,    0,    0,    0,
  80.     /*330*/    0,    0,    0,    0,    0,    0,    0,    0,
  81.     /*340*/    0,    0,    0,    0,    0,    0,    0,    0,
  82.     /*350*/    0,    0,    0,    0,    0,    0,    0,    0,
  83.     /*360*/    0,    0,    0,    0,    0,    0,    0,    0,
  84.     /*370*/    0,    0,    0,    0,    0,    0,    0,    0,
  85.  
  86. };
  87.  
  88. static bool eatUnder = TRUE;
  89.  
  90. /*
  91.     Grab the next identifier the C source
  92.     file opened with the handle `inFILE'.
  93.     This state machine is built for speed, not elegance.
  94. */
  95. char *
  96. getCId(inFILE, flagP)
  97.     FILE        *inFILE;
  98.     int        *flagP;
  99. {
  100.     static char    idBuf[BUFSIZ];
  101.     static bool    newLine = TRUE;
  102.     register short    *rct = &idctype[1];
  103.     register int    c;
  104.     register char    *id = idBuf;
  105.  
  106. top:
  107.     c = getc(inFILE);
  108.  
  109.     if (ISEOF(c))
  110.     {
  111.         newLine = TRUE;
  112.         return NULL;
  113.     }
  114.  
  115.     if (newLine) {
  116.         newLine = FALSE;
  117.         if (c != '#')
  118.             goto next;
  119.         while (ISBORING(c))
  120.         {
  121.             c = getc(inFILE);
  122.  
  123.             if (ISEOF(c))
  124.             {
  125.                 newLine = TRUE;
  126.                 return NULL;
  127.             }
  128.         }
  129.  
  130.         if (!ISID1ST(c))
  131.             goto next;
  132.         id = idBuf;
  133.         *id++ = c;
  134.         while (ISIDREST(c = getc(inFILE)))
  135.             *id++ = c;
  136.         if (ISEOF(c))
  137.         {
  138.             newLine = TRUE;
  139.             return NULL;
  140.         }
  141.         *id = '\0';
  142.         if (strcmp(idBuf, "include") == 0) {
  143.             while (c != '"' && c != '<')
  144.             {
  145.                 c = getc(inFILE);
  146.  
  147.                 if (ISEOF(c))
  148.                 {
  149.                     newLine = TRUE;
  150.                     return NULL;
  151.                 }
  152.             }
  153.  
  154.             id = idBuf;
  155.             *id++ = c = getc(inFILE);
  156.  
  157.             if (ISEOF(c))
  158.             {
  159.                 newLine = TRUE;
  160.                 return NULL;
  161.             }
  162.  
  163.             while ((c = getc(inFILE)) != '"' && c != '>')
  164.             {
  165.                 if (ISEOF(c))
  166.                 {
  167.                     newLine = TRUE;
  168.                     return NULL;
  169.                 }
  170.  
  171.                 *id++ = c;
  172.             }
  173.  
  174.             *id = '\0';
  175.             *flagP = IDN_STRING;
  176.             return idBuf;
  177.         }
  178.         if (strncmp(idBuf, "if", 2) == 0
  179.         || strcmp(idBuf, "define")  == 0
  180.         || strcmp(idBuf, "undef")   == 0)
  181.             goto next;
  182.         while (c != '\n')
  183.         {
  184.             c = getc(inFILE);
  185.  
  186.             if (ISEOF(c))
  187.             {
  188.                 newLine = TRUE;
  189.                 return NULL;
  190.             }
  191.         }
  192.         newLine = TRUE;
  193.         goto top;
  194.     }
  195.  
  196. next:
  197.     while (ISBORING(c))
  198.     {
  199.         c = getc(inFILE);
  200.  
  201.         if (ISEOF(c))
  202.         {
  203.             newLine = TRUE;
  204.             return NULL;
  205.         }
  206.     }
  207.  
  208.     switch (c)
  209.     {
  210.     case '"':
  211.         id = idBuf;
  212.         *id++ = c = getc(inFILE);
  213.  
  214.         if (ISEOF(c))
  215.         {
  216.             newLine = TRUE;
  217.             return NULL;
  218.         }
  219.  
  220.         for (;;) {
  221.             while (ISQ2BORING(c))
  222.             {
  223.                 *id++ = c = getc(inFILE);
  224.  
  225.                 if (ISEOF(c))
  226.                 {
  227.                     newLine = TRUE;
  228.                     return NULL;
  229.                 }
  230.             }
  231.  
  232.             if (c == '\\') {
  233.                 *id++ = c = getc(inFILE);
  234.  
  235.                 if (ISEOF(c))
  236.                 {
  237.                     newLine = TRUE;
  238.                     return NULL;
  239.                 }
  240.  
  241.                 continue;
  242.             } else if (c != '"')
  243.                 goto next;
  244.             break;
  245.         }
  246.         *--id = '\0';
  247.         id = idBuf;
  248.         while (ISSTRKEEP(*id))
  249.             id++;
  250.         if (*id || id == idBuf) {
  251.             c = getc(inFILE);
  252.  
  253.             if (ISEOF(c))
  254.             {
  255.                 newLine = TRUE;
  256.                 return NULL;
  257.             }
  258.  
  259.             goto next;
  260.         }
  261.         *flagP = IDN_STRING;
  262.         if (eatUnder && idBuf[0] == '_' && idBuf[1])
  263.             return &idBuf[1];
  264.         else
  265.             return idBuf;
  266.  
  267.     case '\'':
  268.         c = getc(inFILE);
  269.  
  270.         if (ISEOF(c))
  271.         {
  272.             newLine = TRUE;
  273.             return NULL;
  274.         }
  275.         for (;;) {
  276.             while (ISQ1BORING(c))
  277.             {
  278.                 c = getc(inFILE);
  279.  
  280.                 if (ISEOF(c))
  281.                 {
  282.                     newLine = TRUE;
  283.                     return NULL;
  284.                 }
  285.             }
  286.             if (c == '\\') {
  287.                 c = getc(inFILE);
  288.  
  289.                 if (ISEOF(c))
  290.                 {
  291.                     newLine = TRUE;
  292.                     return NULL;
  293.                 }
  294.  
  295.                 continue;
  296.             } else if (c == '\'') {
  297.                 c = getc(inFILE);
  298.  
  299.                 if (ISEOF(c))
  300.                 {
  301.                     newLine = TRUE;
  302.                     return NULL;
  303.                 }
  304.             }
  305.             goto next;
  306.         }
  307.  
  308.     case '/':
  309.         c = getc(inFILE);
  310.  
  311.         if (ISEOF(c))
  312.         {
  313.             newLine = TRUE;
  314.             return NULL;
  315.         }
  316.  
  317.         if (c == '/')    /* Introduces a C++ style comment. */
  318.         {
  319.             for(;;)
  320.             {
  321.                 c = getc(inFILE);
  322.  
  323.                 if(ISEOF(c))
  324.                 {
  325.                     newLine = TRUE;
  326.                     return NULL;
  327.                 }
  328.                 else
  329.                 {
  330.                     if(c == '\n')
  331.                     {
  332.                         newLine = TRUE;
  333.                         goto top;
  334.                     }
  335.                 }
  336.             }
  337.         }
  338. /*
  339.         if ((c = getc(inFILE)) != '*')
  340.             goto next;
  341. */
  342.         if (c != '*')
  343.             goto next;
  344.         c = getc(inFILE);
  345.  
  346.         if (ISEOF(c))
  347.         {
  348.             newLine = TRUE;
  349.             return NULL;
  350.         }
  351.  
  352.         for (;;) {
  353.             while (ISCBORING(c))
  354.             {
  355.                 c = getc(inFILE);
  356.  
  357.                 if (ISEOF(c))
  358.                 {
  359.                     newLine = TRUE;
  360.                     return NULL;
  361.                 }
  362.             }
  363.  
  364.             if ((c = getc(inFILE)) == '/') {
  365.                 c = getc(inFILE);
  366.  
  367.                 if (ISEOF(c))
  368.                 {
  369.                     newLine = TRUE;
  370.                     return NULL;
  371.                 }
  372.  
  373.                 goto next;
  374.             } else if (ISEOF(c)) {
  375.                 newLine = TRUE;
  376.                 return NULL;
  377.             }
  378.         }
  379.  
  380.     case '\n':
  381.         newLine = TRUE;
  382.         goto top;
  383.  
  384.     default:
  385.         if (ISEOF(c)) {
  386.             newLine = TRUE;
  387.             return NULL;
  388.         }
  389.     name:
  390.         id = idBuf;
  391.         *id++ = c;
  392.         if (ISID1ST(c)) {
  393.             *flagP = IDN_NAME;
  394.             while (ISIDREST(c = getc(inFILE)))
  395.                 *id++ = c;
  396.         } else if (ISDIGIT(c)) {
  397.             *flagP = IDN_NUMBER;
  398.             while (ISNUMBER(c = getc(inFILE)))
  399.                 *id++ = c;
  400.         } else
  401.             fprintf(stderr, "junk: `\\%3o'", c);
  402.         if (ISEOF(c))
  403.         {
  404.             newLine = TRUE;
  405.             return NULL;
  406.         }
  407.         ungetc(c, inFILE);
  408.         *id = '\0';
  409.         *flagP |= IDN_LITERAL;
  410.         return idBuf;
  411.     }
  412. }
  413.  
  414. static void
  415. setCtype(chars, type)
  416.     char        *chars;
  417.     int        type;
  418. {
  419.     short        *rct = &idctype[1];
  420.  
  421.     while (*chars)
  422.         rct[*chars++] |= type;
  423. }
  424. static void
  425. clrCtype(chars, type)
  426.     char        *chars;
  427.     int        type;
  428. {
  429.     short        *rct = &idctype[1];
  430.  
  431.     while (*chars)
  432.         rct[*chars++] &= ~type;
  433. }
  434.  
  435. extern char    *MyName;
  436. static void
  437. usage(lang)
  438.     char        *lang;
  439. {
  440.     fprintf(stderr, "Usage: %s does not accept %s scanner arguments\n", MyName, lang);
  441.     exit(1);
  442. }
  443. static char *cDocument[] =
  444. {
  445. "The C scanner arguments take the form -Sc<arg>, where <arg>",
  446. "is one of the following: (<cc> denotes one or more characters)",
  447. "  (+|-)u . . . . (Do|Don't) strip a leading `_' from ids in strings.",
  448. "  -s<cc> . . . . Allow <cc> in string ids.",
  449. NULL
  450. };
  451. void
  452. setCArgs(lang, op, arg)
  453.     char        *lang;
  454.     int        op;
  455.     char        *arg;
  456. {
  457.     if (op == '?') {
  458.         document(cDocument);
  459.         return;
  460.     }
  461.     switch (*arg++)
  462.     {
  463.     case 'u':
  464.         eatUnder = (op == '+');
  465.         break;
  466.     case 's':
  467.         setCtype(arg, SK);
  468.         break;
  469.     default:
  470.         if (lang)
  471.             usage(lang);
  472.         break;
  473.     }
  474. }
  475.