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
Wrap
C/C++ Source or Header
|
1990-06-18
|
11KB
|
668 lines
/*
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);
}
}