home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 357_01 / cstar1.exe / UTL.C < prev    next >
C/C++ Source or Header  |  1991-06-18  |  12KB  |  676 lines

  1. /*
  2.     C* preprocessor -- utility routines.
  3.  
  4.     Source:  utl.c
  5.     Started: October 7, 1985
  6.     Version:
  7.         February 20, 1987
  8.         March 7, 1989
  9.  
  10.     PUBLIC DOMAIN SOFTWARE
  11.  
  12.     The CSTAR program was placed in    the public domain on June 15, 1991,
  13.     by its author and sole owner,
  14.  
  15.         Edward K. Ream
  16.         1617 Monroe Street
  17.         Madison, WI 53711
  18.         (608) 257-0802
  19.  
  20.     CSTAR may be used for any commercial or non-commercial purpose.
  21.  
  22.     See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
  23. */
  24. #include "cstar.h"
  25.  
  26. /*
  27.     Externally visible routines:
  28. */
  29. int    char_val    (register char *s);
  30. void    conv2s        (int a, char *s);
  31. void    convl2s     (long a, char *s);
  32. void    conul2sc    (unsigned long n, char *s, int c);
  33. void    conl2h        (unsigned long n, char *s, int c);
  34. void    fatal        (char * message);
  35. void    revcpy        (char *s1, char *s2);
  36. void    scan_number    (int base);
  37. void    skip_bl        (void);
  38. bool    skip_crlf    (void);
  39. void    skip_1line    (void);
  40. void    skip_past    (void);
  41. void    skip_pp        (void);
  42. void    skip_ws        (void);
  43. void    t_error        (char * message);
  44. void    t_2error    (char * mess1, char *mess2);
  45. void    t_3serr        (struct node *p, char * mess1, char *mess2, char *mess3);
  46. void    t_warning    (char * message);
  47. void    t_2warning    (char * mess1, char *mess2);
  48. void    t_help        (char * message);
  49. void    t_2help        (char * mess1, char *mess2);
  50. void    g_error        (struct node * p, char * message);
  51. void    g_help        (struct node *p, char * message);
  52. unsigned int str_val    (unsigned char *d);
  53.  
  54. /*
  55.     Internal routines:
  56. */
  57. static bool    is_base_digit    (int base);
  58.  
  59. /*
  60.     Return the value of a character constant.
  61. */
  62. int
  63. char_val(register char *s)
  64. {
  65.     int val;
  66.  
  67.     TRACEPB("char_val", printf("(%s)\n", s));
  68.  
  69.     if (*s != '\\') {
  70.         RETURN_INT("char_val", (int) *s);
  71.     }
  72.     s++;
  73.     switch (*s) {
  74.     case 'b':    RETURN_INT("char_val", '\b');
  75.     case 'f':    RETURN_INT("char_val", '\f');
  76.     case 'n':    RETURN_INT("char_val", '\n');
  77.     case 'r':    RETURN_INT("char_val", '\r');
  78.     case 't':    RETURN_INT("char_val", '\t');
  79.     case '\'':    RETURN_INT("char_val", '\'');
  80.     case '\\':    RETURN_INT("char_val", '\\');
  81.  
  82.     default:
  83.         if (*s < '0' || *s > '7') {
  84.             RETURN_INT("char_val", (int)*s);
  85.         }
  86.         val = 0;
  87.         while (*s >= '0' && *s <= '7') {
  88.             val = val * 8 + (int)*s - '0';
  89.             s++;
  90.         }
  91.         RETURN_INT("char_val", val);
  92.     }
  93. }
  94.  
  95. /*
  96.     Convert a signed integer n to a string s[].
  97.     The length of s must be large enough to hold the result.
  98. */
  99. void
  100. conv2s(int a, register char *s)
  101. {
  102.     register char *d, *ss;
  103.     register int sn;
  104.     register unsigned long n;
  105.     char temp [INT_DIGITS];
  106.  
  107.     SL_DISABLE();
  108.  
  109.     /* Do the sign and handle 0x8000 correctly */
  110.     if (a >= 0) {
  111.         sn = 0;
  112.         /* these casts ARE NOT redundant: DO NOT fix them! */
  113.         /* see note in lint.doc about unsigned extending casts */
  114.         n = (unsigned long) (long) a;
  115.     }
  116.     else {
  117.         sn = 1;
  118.         n = (unsigned long) (long) (-a);
  119.     }
  120.  
  121.     /* put digits in reverse order into temp */
  122.     d = &temp[0];
  123.     *d++ = 0;
  124.     if (n) while (n) {
  125.         /* NOTE: in assembly, we would divide once */
  126.         *d++ = (char)(n % 10) + '0';
  127.         n = n / 10;
  128.     }
  129.     else {
  130.         *d++ = '0';
  131.     }
  132.  
  133.     /* insert the sign */
  134.     if (sn) {
  135.         *d++ = '-';
  136.     }
  137.  
  138.     /* Reverse temp into s. */
  139.     ss = s;
  140.  
  141.     /* -----
  142.     while(*ss++ = *--d) {};
  143.     ----- */
  144.  
  145.     do {
  146.         *ss++ = *--d;
  147.     }
  148.     while (*d);
  149.     
  150.  
  151.     TRACEP("conv2s", printf("converts %d to <%s>\n", a, s));
  152. }
  153.  
  154. /*
  155.     Convert a long n to a string s[].
  156.     The length of s must be large enough to hold the result.
  157. */
  158. void
  159. convl2s(long a, register char *s)
  160. {
  161.     register char *d, *ss;
  162.     register int sn;
  163.     register unsigned long n;
  164.     char temp [LONG_DIGITS];
  165.  
  166.     SL_DISABLE();
  167.  
  168.     /* Do the sign and handle 0x80000000 correctly */
  169.     if (a >= 0) {
  170.         sn = 0;
  171.         n = (unsigned long) a;
  172.     }
  173.     else {
  174.         sn = 1;
  175.         n = (unsigned long) (-a);
  176.     }
  177.  
  178.     /* put digits in reverse order into temp */
  179.     d = &temp[0];
  180.     *d++ = 0;
  181.     if (n) while (n) {
  182.         /* NOTE: in assembly, we would divide once */
  183.         *d++ = (char)(n % 10) + '0';
  184.         n = n / 10;
  185.     }
  186.     else {
  187.         *d++ = '0';
  188.     }
  189.  
  190.     /* insert the sign */
  191.     if (sn) {
  192.         *d++ = '-';
  193.     }
  194.  
  195.     /* Reverse temp into s. */
  196.     ss = s;
  197.  
  198.     /* -----
  199.     while(*ss++ = *--d) {};
  200.     ----- */
  201.  
  202.     do {
  203.         *ss++ = *--d;
  204.     }
  205.     while (*d);
  206.  
  207.     TRACEP("convl2s", printf("converts %ld to <%s>\n", a, s));
  208. }
  209.  
  210. /*
  211.     Convert a long n to a string s[], minimum digit count c.
  212.     The length of s must be large enough to hold any result.
  213. */
  214. void
  215. conul2sc(register unsigned long n, register char *s, register int c)
  216. {
  217.     register char *d, *ss;
  218.     char temp [LONG_DIGITS];
  219.  
  220.     SL_DISABLE();
  221.  
  222.     /* put digits in reverse order into temp */
  223.     d = &temp[0];
  224.     *d++ = 0;
  225.     while (n) {
  226.         /* NOTE: in assembly, we would divide once */
  227.         *d++ = (char)(n % 10) + '0';
  228.         n /= 10;
  229.         if (c > 0) {
  230.             c--;
  231.         }
  232.     }
  233.     while (c > 0) {
  234.         c--;
  235.         *d++ = '0';
  236.     }
  237.  
  238.     /* Reverse temp into s. */
  239.     ss = s;
  240.  
  241.     /* -----
  242.     while(*ss++ = *--d) {};
  243.     ----- */
  244.  
  245.     do {
  246.         *ss++ = *--d;
  247.     }
  248.     while (*d);
  249.  
  250.     TRACEP("conul2sc", printf("converts %lu, count %d to <%s>\n", n, c, s));
  251. }
  252.  
  253. /*
  254.     Convert a long n to a hex string s[], minimum digit count c.
  255.     The length of s must be large enough to hold any result.
  256. */
  257. void
  258. conl2h(register unsigned long n, register char *s, register int c)
  259. {
  260.     register char *d, *ss;
  261.     char temp [LONG_DIGITS];
  262.  
  263.     SL_DISABLE();
  264.  
  265.     /* put digits in reverse order into temp */
  266.     d = &temp[0];
  267.     *d++ = 0;
  268.     while (n) {
  269.         *d = ((char)n & 15) + '0';
  270.         if (*d > '9') {
  271.             *d += 7;
  272.         }
  273.         d++;
  274.         n >>= 4;
  275.         if (c > 0) {
  276.             c--;
  277.         }
  278.     }
  279.     while (c > 0) {
  280.         c--;
  281.         *d++ = '0';
  282.     }
  283.  
  284.     /* Reverse temp into s. */
  285.     ss = s;
  286.  
  287.     /* -----
  288.     while(*ss++ = *--d) {};
  289.     ----- */
  290.  
  291.     do {
  292.         *ss++ = *--d;
  293.     }
  294.     while (*d);
  295.  
  296.     TRACEP("conl2h", printf("converts %lu, count %d to <%s>\n", n, c, s));
  297. }
  298.  
  299. /*
  300.     Give an error message and exit.
  301. */
  302. void
  303. fatal(char * message)
  304. {
  305.     SL_DISABLE();
  306.  
  307.     printf("fatal error: ");
  308.     t_error(message);
  309.     sysabort();
  310.     
  311. }
  312.  
  313. /*
  314.     Return true if the global ch is a digit in the indicated base.
  315.  
  316.     Return the value of the digit in digit_val;
  317. */
  318. static unsigned char digit_val;
  319.  
  320. static bool
  321. is_base_digit(register int base)
  322. {
  323.     TRACEPB("is_base_digit", printf("(%d)\n", base));
  324.  
  325.     if (ch >= '0' && ch <= '9') {
  326.         digit_val = ch - '0';
  327.         RETURN_BOOL("is_base_digit", TRUE);
  328.     }
  329.     else if (base != 16) {
  330.         RETURN_BOOL("is_base_digit", FALSE);
  331.     }
  332.     else if (ch >= 'a' && ch <= 'f') {
  333.         digit_val = ch - 'a' + 10;
  334.         RETURN_BOOL("is_base_digit", TRUE);
  335.     }
  336.     else {
  337.         digit_val = ch - 'A' + 10;
  338.         RETURN_BOOL("is_base_digit", ch >= 'A' && ch <= 'F');
  339.     }
  340. }
  341.  
  342. /*
  343.     Copy string s2 to string s1 in reverse order.
  344. */
  345. void
  346. revcpy(char *s1, char *s2)
  347. {
  348.     int length;
  349.  
  350.     SL_DISABLE();
  351.  
  352.     length = str_len(s2);
  353.     s2     = s2 + length - 1;
  354.  
  355.     for (; length; length--) {
  356.         *s1++ = *s2--;
  357.     }
  358.     *s1 = '\0';
  359.  
  360.     TRACEP("revcpy", printf("revcpy copy returns s1 = <%s>\n", s1));
  361. }
  362.  
  363. /*
  364.     Get value of a string of digits into t_value.
  365.     Continue until a non base digit is found.
  366. */
  367. void
  368. scan_number(register int base)
  369. {
  370.     SL_DISABLE();
  371.  
  372.     t_value = 0;
  373.     while (is_base_digit(base)) {
  374.         t_value = ((long)base * t_value) + (long)digit_val;
  375.         sysnext();
  376.     }
  377.  
  378.     TRACEP("scan_number",
  379.         printf("scan_number sets t_value: %ld\n", t_value));
  380. }
  381.  
  382. /*
  383.     Skip blanks and tabs,  but not newlines.
  384. */
  385. void
  386. skip_bl(void)
  387. {
  388.     STAT("skip_bl");
  389.  
  390.     while (ch == ' ' || ch == '\t') {
  391.         sysnext();
  392.     }
  393. }
  394.  
  395. /*
  396.     Skip a newline, optionally preceeded or followed by '\r'.
  397.     Return TRUE if seen.
  398. */
  399. bool
  400. skip_crlf(void)
  401. {
  402.     STAT("skip_crlf");
  403.  
  404.     if (ch == '\r') {
  405.         sysnext();
  406.         if (ch == '\n') {
  407.             sysnext();
  408.             return TRUE;
  409.         }
  410.         else {
  411.             return FALSE;
  412.         }
  413.     }
  414.     else if (ch == '\n') {
  415.         sysnext();
  416.         if (ch == '\r') {
  417.             sysnext();
  418.         }
  419.         return TRUE;
  420.     }
  421.     else {
  422.         return FALSE;
  423.     }
  424. }
  425.  
  426. /*
  427.     Skip characters up to but NOT including a newline.
  428. */
  429. void
  430. skip_1line(void)
  431. {
  432.     STAT("skip_1line");
  433.  
  434.     while (ch != END_FILE && ch != '\n') {
  435.         sysnext();
  436.     }
  437. }
  438.  
  439. /*
  440.     Skip characters up to and including a newline.
  441. */
  442. void
  443. skip_past(void)
  444. {
  445.     STAT("skip_past");
  446.  
  447.     while (ch != END_FILE && ch != '\n') {
  448.         sysnext();
  449.     }
  450.  
  451.     if (ch == '\n') {
  452.         sysnext();
  453.         do_nl();
  454.     }
  455. }
  456.  
  457. /*
  458.     Skip to the end of the current preprocessor directive.
  459.     Do NOT skip past the final newline.
  460.  
  461.     Note that directives may contain comments (!!) and may be continued
  462.     from line to line.
  463. */
  464. void
  465. skip_pp(void)
  466. {
  467.     STAT("skip_pp");
  468.  
  469.     for (;;) {
  470.         skip_ws();
  471.         if (ch == '\\') {
  472.             sysnext();
  473.             if (!skip_crlf()) {
  474.                 /* Skip the escaped character. */
  475.                 sysnext();
  476.             }
  477.         }
  478.         else if (ch == END_FILE || ch == '\n') {
  479.             return;
  480.         }
  481.         else {
  482.             sysnext();
  483.         }
  484.     }
  485. }
  486.  
  487. /*
  488.     Skip blanks, tabs and comments.
  489. */
  490. void
  491. skip_ws(void)
  492. {
  493.     STAT("skip_ws");
  494.  
  495.     for(;;) {
  496.  
  497.         switch(ch) {
  498.  
  499.         case ' ':
  500.         case '\t':
  501.             sysnext();
  502.             continue;
  503.  
  504.         case '/':
  505.             sysnext();
  506.             if (ch == '*') {
  507.                 sysnext();
  508.                 t_comment();
  509.                 continue;
  510.             }
  511.             else {
  512.                 syspush(ch);
  513.                 ch = '/';
  514.                 return;
  515.             }
  516.  
  517.         default:
  518.             return;
  519.         }
  520.     }
  521. }
  522.  
  523. /*
  524.     Process a non-fatal error messages.
  525. */
  526. void
  527. t_error(char * message)
  528. {
  529.     SL_DISABLE();
  530.  
  531.     (void) syscsts();
  532.     t_errcount++;
  533.     printf("line %3d, %s: %s\n", t_line, t_file, message);
  534. }
  535.  
  536. void
  537. t_2error(char * mess1, char *mess2)
  538. {
  539.     SL_DISABLE();
  540.  
  541.     (void) syscsts();
  542.     t_errcount++;
  543.     printf("line %3d, %s: %s%s\n", t_line, t_file, mess1, mess2);
  544. }
  545.  
  546. void
  547. t_3serr(struct node *p, char * mess1, char *mess2, char *mess3)
  548. {
  549.     SL_DISABLE();
  550.  
  551.     t_errcount++;
  552.     (void) syscsts();
  553.     printf("line %3d, %s: %s%s%s", t_line, t_file, mess1, mess2, mess3);
  554.     if (p) {
  555.         printf(" (see line %d)\n", p -> n_linno);
  556.     }
  557.     else {
  558.         printf("\n");
  559.     }
  560. }
  561.  
  562. /*
  563.     Process a warning message.
  564. */
  565. void
  566. t_warning(char * message)
  567. {
  568.     SL_DISABLE();
  569.     printf("line %3d, %s (warning): %s\n", t_line, t_file, message);
  570. }
  571.  
  572. void
  573. t_2warning(char * mess1, char *mess2)
  574. {
  575.     SL_DISABLE();
  576.     printf("line %3d, %s (warning): %s%s\n", t_line, t_file, mess1, mess2);
  577. }
  578.  
  579. /*
  580.     Process a less-important warning message.
  581. */
  582. void
  583. t_help(char * message)
  584. {
  585.     SL_DISABLE();
  586.     printf("line %3d, %s (note): %s\n", t_line, t_file, message);
  587. }
  588.  
  589. void
  590. t_2help(char * mess1, char *mess2)
  591. {
  592.     SL_DISABLE();
  593.     printf("line %3d, %s (note): %s%s\n", t_line, t_file, mess1, mess2);
  594. }
  595.  
  596. /*
  597.     Code generation errors
  598. */
  599. void
  600. g_error(struct node * p, char * message)
  601. {
  602.     SL_DISABLE();
  603.     if (p != NULL) {
  604.         printf("g_error/line %d file %s: %s\n",
  605.             p -> n_linno, "??", message);
  606.     }
  607.     else {
  608.         printf("g_error/line ?? file ??: %s\n", message);
  609.     }
  610. }
  611.  
  612. /*
  613.     Process a less-important warning message.
  614. */
  615. void
  616. g_help(struct node *p, char * message)
  617. {
  618.     SL_DISABLE();
  619.     if (p != NULL) {
  620.         printf("g_help/line %3d file %s (note): %s\n",
  621.                  p -> n_linno, "??", message);
  622.     }
  623.     else {
  624.         printf("g_help/line ?? file ??: %s\n", message);
  625.     }
  626. }
  627.  
  628. /*
  629.     Re-evaluate a string constant; this may shorten it
  630.  
  631.     Return its length; it may contain imbedded zeroes once processed
  632.  
  633.     CAUTION: if the string is transformed, it is always shortened.  Callers
  634.     of this routine may count on that fact.
  635. */
  636. unsigned int
  637. str_val(register unsigned char *d)
  638. {
  639.     register unsigned char val, *dd, *s;
  640.  
  641.     TRACEPB("str_val", printf("(%s)\n", d));
  642.  
  643.     /* outer loop to scan the string */
  644.     s = dd = d;
  645.     while (*s) {
  646.         if (*s != '\\') {
  647.             *d++ = *s++;
  648.             continue;
  649.         }
  650.         ++s;
  651.         switch (*s) {
  652.         case 'b':    *d++ = '\b'; ++s; break;
  653.         case 'f':    *d++ = '\f'; ++s; break;
  654.         case 'n':    *d++ = '\n'; ++s; break;
  655.         case 'r':    *d++ = '\r'; ++s; break;
  656.         case 't':    *d++ = '\t'; ++s; break;
  657.         case '\'':    *d++ = '\''; ++s; break;
  658.         case '\\':    *d++ = '\\'; ++s; break;
  659.  
  660.         default:
  661.             if (*s < '0' || *s > '7') {
  662.                 continue;
  663.             }
  664.             val = 0;
  665.             while (*s >= '0' && *s <= '7') {
  666.                 val = val * 8 + *s - '0';
  667.                 s++;
  668.             }
  669.             *d++ = val;
  670.         }
  671.     }
  672.     *d++ = '\0';
  673.  
  674.     RETURN_UINT("str_val", (unsigned int)(d - dd));
  675. }
  676.