home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_300 / 319_02 / utl.c < prev   
C/C++ Source or Header  |  1990-06-18  |  11KB  |  668 lines

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