home *** CD-ROM | disk | FTP | other *** search
- /*
- CPP V5 -- utilities.
-
- Source: utl.c
- Started: October 7, 1985
- Version:
- July 21, 1988
- March 3, 1989
- bug fix to skip_ws() and copy_ws().
- August 1, 1989
- Support for C++ style single-line comments added to
- skip_pp(), skip_ws() and copy_ws().
-
- Written by Edward K. Ream.
- This software is in the public domain.
-
- See the read.me file for disclaimer and other information.
- */
-
- #include "cpp.h"
-
- /*
- Return the value of a character constant.
- */
- int
- char_val(s)
- register char *s;
- {
- int val;
-
- if (*s != '\\') {
- return (int) *s;
- }
- s++;
- switch (*s) {
- case 'b': return '\b';
- case 'f': return '\f';
- case 'n': return '\n';
- case 'r': return '\r';
- case 't': return '\t';
- case '\'': return '\'';
- case '\\': return '\\';
-
- default:
- if (*s < '0' || *s > '7') {
- return (int)*s;
- }
- val = 0;
- while (*s >= '0' && *s <= '7') {
- val = val * 8 + (int)*s - '0';
- s++;
- }
- return val;
- }
- }
-
- /*
- Re-evaluate a string constant; this may shorten it
-
- Return its length; it may contain imbedded zeroes once processed
-
- CAUTION: if the string is transformed, it is always shortened. Callers
- of this routine may count on that fact.
- */
- unsigned int
- str_val(d)
- register unsigned char *d;
- {
- register unsigned char val, *dd, *s;
- TICK("str_val");
-
- /* outer loop to scan the string */
- s = dd = d;
- while (*s) {
- if (*s != '\\') {
- *d++ = *s++;
- continue;
- }
- ++s;
- switch (*s) {
- case 'b': *d++ = '\b'; ++s; break;
- case 'f': *d++ = '\f'; ++s; break;
- case 'n': *d++ = '\n'; ++s; break;
- case 'r': *d++ = '\r'; ++s; break;
- case 't': *d++ = '\t'; ++s; break;
- case '\'': *d++ = '\''; ++s; break;
- case '\\': *d++ = '\\'; ++s; break;
-
- default:
- if (*s < '0' || *s > '7') {
- continue;
- }
- val = 0;
- while (*s >= '0' && *s <= '7') {
- val = val * 8 + *s - '0';
- s++;
- }
- *d++ = val;
- }
- }
- *d++ = '\0';
- TRACEP("str_val", printf("returns length %d\n", (int)(d - dd)));
- return (unsigned int)(d - dd);
- }
-
- /*
- Return the value of a string of digits in a given radix.
- */
- int
- conv2i(string, radix)
- char *string;
- int radix;
- {
- register int value;
- register int digit;
-
- TICK("conv2i");
-
- value = 0;
- while (digit = *string++) {
- if (digit >= 'a' && digit <= 'z') {
- digit = digit - 'a' + 10;
- }
- else if (digit >= 'A' && digit <= 'Z') {
- digit = digit - 'A' + 10;
- }
- else {
- digit = digit - '0';
- }
- value = (value * radix) + digit;
- }
- return value;
- }
-
- /*
- Convert a signed integer n to a string s[].
- The length of s must be large enough to hold the result.
- */
- void
- conv2s (a, s)
- int a;
- register char *s;
- {
- register char *d, *ss;
- register int sn;
- register unsigned long n;
- char temp [INT_DIGITS];
-
- TICK("conv2s");
-
- /* Do the sign and handle 0x8000 correctly */
- if (a >= 0) {
- sn = 0;
- /* these casts ARE NOT redundant: DO NOT fix them! */
- /* see note in lint.doc about unsigned extending casts */
- n = (unsigned long) (long) a;
- }
- else {
- sn = 1;
- n = (unsigned long) (long) (-a);
- }
-
- /* put digits in reverse order into temp */
- d = &temp[0];
- *d++ = 0;
- if (n) while (n) {
- /* NOTE: in assembly, we would divide once */
- *d++ = (char)(n % 10) + '0';
- n = n / 10;
- }
- else {
- *d++ = '0';
- }
-
- /* insert the sign */
- if (sn) {
- *d++ = '-';
- }
-
- /* Reverse temp into s. */
- ss = s;
- while(*ss++ = *--d) {};
-
- TRACE("conv2s", printf("conv2s returns: %s\n", s));
- }
-
- /*
- Convert a long n to a string s[].
- The length of s must be large enough to hold the result.
- */
- void
- convl2s (a, s)
- long a;
- register char *s;
- {
- register char *d, *ss;
- register int sn;
- register unsigned long n;
- char temp [LONG_DIGITS];
-
- TICK("convl2s");
-
- /* Do the sign and handle 0x80000000 correctly */
- if (a >= 0) {
- sn = 0;
- n = (unsigned long) a;
- }
- else {
- sn = 1;
- n = (unsigned long) (-a);
- }
-
- /* put digits in reverse order into temp */
- d = &temp[0];
- *d++ = 0;
- if (n) while (n) {
- /* NOTE: in assembly, we would divide once */
- *d++ = (char)(n % 10) + '0';
- n = n / 10;
- }
- else {
- *d++ = '0';
- }
-
- /* insert the sign */
- if (sn) {
- *d++ = '-';
- }
-
- /* Reverse temp into s. */
- ss = s;
- while(*ss++ = *--d) {};
-
- TRACE("convl2s", printf("convl2s (%ld): %s\n", a, s));
- }
-
- /*
- Convert a long n to a string s[], minimum digit count c.
- The length of s must be large enough to hold any result.
- */
- void
- conul2sc(n, s, c)
- register unsigned long n;
- register char *s;
- register int c;
- {
- register char *d, *ss;
- char temp [LONG_DIGITS];
-
- TICK("conul2sc");
-
- /* put digits in reverse order into temp */
- d = &temp[0];
- *d++ = 0;
- while (n) {
- /* NOTE: in assembly, we would divide once */
- *d++ = (char)(n % 10) + '0';
- n /= 10;
- if (c > 0) {
- c--;
- }
- }
- while (c > 0) {
- c--;
- *d++ = '0';
- }
-
- /* Reverse temp into s. */
- ss = s;
- while(*ss++ = *--d) {};
-
- TRACE("conul2sc", printf("conul2sc returns: %s\n", s));
- }
-
- /*
- Convert a long n to a hex string s[], minimum digit count c.
- The length of s must be large enough to hold any result.
- */
- void
- conl2h(n, s, c)
- register unsigned long n;
- register char *s;
- register int c;
- {
- register char *d, *ss;
- char temp [LONG_DIGITS];
-
- TICK("conl2h");
-
- /* put digits in reverse order into temp */
- d = &temp[0];
- *d++ = 0;
- while (n) {
- *d = ((char)n & 15) + '0';
- if (*d > '9') {
- *d += 7;
- }
- d++;
- n >>= 4;
- if (c > 0) {
- c--;
- }
- }
- while (c > 0) {
- c--;
- *d++ = '0';
- }
-
- /* Reverse temp into s. */
- ss = s;
- while(*ss++ = *--d) {};
-
- TRACE("conl2h", printf("conl2h returns: %s\n", s));
- }
-
- /*
- Skip blanks and tabs, but not newlines.
- */
- void
- skip_bl()
- {
- TICKB("skip_bl");
-
- while (ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f') {
- sysnext();
- }
-
- RETURN_VOID("skip_bl");
- }
-
- /*
- Skip characters up to but NOT including a newline.
- */
- void
- skip_1line()
- {
- TICKB("skip_1line");
-
- while (ch != END_FILE && ch != '\n') {
- sysnext();
- }
-
- RETURN_VOID("skip_1line");
- }
-
- /*
- Skip characters up to and including a newline.
- */
- void
- skip_past()
- {
- TICKB("skip_past");
-
- while (ch != END_FILE && ch != '\n') {
- sysnext();
- }
-
- if (ch == '\n') {
- sysnext();
- if (com_flag) {
- sysnlput();
- }
- bump_line();
- }
-
- RETURN_VOID("skip_past");
- }
-
- /*
- Skip to the end of the current preprocessor directive.
- I.e., skip to the first newline not contained in a comment.
- */
- void
- skip_pp()
- {
- TICKB("skip_pp");
-
- while (ch != '\n' && ch != END_FILE) {
- if (ch == '/') {
- /* Possible comment. */
- sysnext();
- if (ch == '*') {
- sysnext();
- skip_comment();
- }
- else if (slc_flag && ch == '/') {
- /* 8/1/89 Single-line comment */
- while (ch != END_FILE && ch != '\n') {
- sysnext();
- }
- RETURN_VOID("skip_pp");
- }
- else {
- syspushback(ch);
- ch = '/';
- RETURN_VOID("skip_pp");
- }
- }
- else {
- sysnext();
- }
- }
- RETURN_VOID("skip_pp");
- }
-
- /*
- Skip blanks, tabs, and comments.
- Also skip newlines if nl_flag is TRUE;
- */
- void
- skip_ws(nl_flag)
- bool nl_flag;
- {
- TRACEPB("skip_ws", printf("(%s)\n", pr_bool(nl_flag)));
-
- for(;;) {
-
- switch(ch) {
-
- case ' ':
- case '\t':
- case '\f':
- case '\v':
- sysnext();
- continue;
-
- case '\n':
- if (nl_flag) {
- bump_line();
- sysnext();
- continue;
- }
- else {
- /* 3/3/89 */
- goto done;
- }
-
- case '/':
- sysnext();
- if (ch == '*') {
- sysnext();
- skip_comment();
- continue;
- }
- else if (slc_flag && ch == '/') {
- /* 8/1/89 Single-line comment */
- while (ch != END_FILE && ch != '\n') {
- sysnext();
- }
- continue;
- }
- else {
- syspushback(ch);
- ch = '/';
- goto done;
- }
-
- default:
- goto done;
- }
- }
- done:
- RETURN_VOID("skip_ws");
- }
-
- /*
- Copy blanks, tabs and comments to the output.
- Also copy newlines if nl_flag is TRUE;
- */
- void
- copy_ws(nl_flag)
- bool nl_flag;
- {
- TRACEPB("copy_ws", printf("(%s)\n", pr_bool(nl_flag)));
-
- for(;;) {
-
- switch(ch) {
-
- case ' ':
- case '\t':
- case '\f':
- case '\v':
- syscput(ch);
- sysnext();
- continue;
-
- case '\n':
- if (nl_flag) {
- bump_line();
- sysnlput();
- sysnext();
- continue;
- }
- else {
- /* 3/3/89 */
- goto done;
- }
-
- case '/':
- sysnext();
- if (ch == '*') {
- sysnext();
- syscput('/');
- syscput('*');
- copy_comment();
- continue;
- }
- else if (slc_flag && ch == '/') {
- /* 8/1/89 Single-line comment */
- sysnext();
- syscput('/');
- syscput('/');
- while (ch != END_FILE && ch != '\n') {
- syscput(ch);
- sysnext();
- }
- continue;
- }
- else {
- syspushback(ch);
- ch = '/';
- goto done;
- }
-
- default:
- goto done;
- }
- }
- done:
- RETURN_VOID("copy_ws");
- }
-
- /*
- Process a non-fatal error messages.
- */
- void
- error(message)
- char *message;
- {
- TICK("error");
- syscsts();
- t_errcount++;
- if (t_inlevel == 0) {
- printf("line %3d: %s\n", t_line, message);
- }
- else {
- printf("line %3d, %s: %s\n", t_line, t_file, message);
- }
- }
-
- void
- err2(mess1, mess2)
- char *mess1;
- char *mess2;
- {
- TICK("err2");
- syscsts();
- t_errcount++;
- if (t_inlevel == 0) {
- printf("line %3d: %s%s\n", t_line, mess1, mess2);
- }
- else {
- printf("line %3d, %s: %s%s\n", t_line, t_file, mess1, mess2);
- }
- }
-
- void
- err3(mess1, mess2, mess3)
- char *mess1;
- char *mess2;
- char *mess3;
- {
- TICK("err3");
- syscsts();
- t_errcount++;
- if (t_inlevel == 0) {
- printf("line %3d: %s%s%s\n", t_line, mess1, mess2, mess3);
- }
- else {
- printf("line %3d, %s: %s%s%s\n",
- t_line, t_file, mess1, mess2, mess3);
- }
- }
-
- /*
- Give an error message and exit.
- */
- void
- fatal(message)
- char * message;
- {
- printf("\nOh dear. I can't go on like this...\n\n");
- printf("line %3d, %s: %s\n", t_line, t_file, message);
-
- TRACE("dump", m_stat());
- TRACE("dump", sl_dump());
- sysabort();
-
- }
-
- /*
- Internal error.
- */
- void
- syserr(message)
- char *message;
- {
- printf("\nOh dear. There is something wrong with me...\n\n");
- printf("line %3d, %s: %s\n", t_line, t_file, message);
-
- TRACE("dump", m_stat());
- TRACE("dump", sl_dump());
- sysabort();
- }
-
- /*
- Process a non-fatal warning message.
- */
- void
- warning(message)
- char *message;
- {
- TICK("warning");
- syscsts();
- if (t_inlevel == 0) {
- printf("line %3d: (Warning) %s\n", t_line, message);
- }
- else {
- printf("line %3d, %s: (Warning) %s\n",
- t_line, t_file, message);
- }
- }
-
- void
- warn2(mess1, mess2)
- char *mess1;
- char *mess2;
- {
- TICK("warn2");
- syscsts();
- if (t_inlevel == 0) {
- printf("line %3d: (Warning) %s%s\n", t_line, mess1, mess2);
- }
- else {
- printf("line %3d, %s: (Warning) %s%s\n",
- t_line, t_file, mess1, mess2);
- }
- }
-
- void
- warn3(mess1, mess2, mess3)
- char *mess1;
- char *mess2;
- char *mess3;
- {
- TICK("warn3");
- syscsts();
- if (t_inlevel == 0) {
- printf("line %3d: (Warning) %s%s%s\n",
- t_line, mess1, mess2, mess3);
- }
- else {
- printf("line %3d, %s: (Warning) %s%s%s\n",
- t_line, t_file, mess1, mess2, mess3);
- }
- }
-