home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The C Users' Group Library 1994 August
/
wc-cdrom-cusersgrouplibrary-1994-08.iso
/
vol_200
/
204_01
/
getsym.c
< prev
next >
Wrap
Text File
|
1979-12-31
|
18KB
|
555 lines
#include <stdio.h>
#include "c.h"
#include "expr.h"
#include "gen.h"
#include "cglbdec.h"
/*
* 68000 C compiler
*
* Copyright 1984, 1985, 1986 Matthew Brandt.
* all commercial rights reserved.
*
* This compiler is intended as an instructive tool for personal use. Any
* use for profit without the written consent of the author is prohibited.
*
* This compiler may be distributed freely for non-commercial use as long
* as this notice stays intact. Please forward any enhancements or questions
* to:
*
* Matthew Brandt
* Box 920337
* Norcross, Ga 30092
*/
static int errno[80];
static int numerrs;
static char inline[132];
int total_errors = 0;
char *lptr; /* shared with preproc */
FILE *inclfile[10]; /* shared with preproc */
int inclline[10]; /* shared with preproc */
int incldepth; /* shared with preproc */
char *linstack[20]; /* stack for substitutions */
char chstack[20]; /* place to save lastch */
int lstackptr = 0; /* substitution stack pointer */
int isalnum(c)
char c;
{ return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9');
}
int isidch(c)
char c;
{ return isalnum(c) || c == '_' || c == '$';
}
int isspace(c)
char c;
{ return c == ' ' || c == '\t' || c == '\n';
}
int isdigit(c)
char c;
{ return (c >= '0' && c <= '9');
}
initsym()
{ lptr = inline;
inline[0] = 0;
numerrs = 0;
total_errors = 0;
lineno = 0;
}
int getline(listflag)
int listflag;
{ int rv;
if( lineno > 0 && listflag) {
fprintf(list,"%6d\t%s",lineno,inline);
while(numerrs--)
fprintf(list," *** error %d\n",errno[numerrs]);
numerrs = 0;
}
++lineno;
rv = (fgets(inline,131,input) == NULL);
if( rv && incldepth > 0 ) {
fclose(input);
input = inclfile[--incldepth];
lineno = inclline[incldepth];
return getline(0);
}
if( rv )
return 1;
lptr = inline;
if(inline[0] == '#')
return preprocess();
return 0;
}
/*
* getch - basic get character routine.
*/
int getch()
{ while( (lastch = *lptr++) == '\0') {
if( lstackptr > 0 ) {
lptr = linstack[--lstackptr];
lastch = chstack[lstackptr];
return lastch;
}
if(getline(incldepth == 0))
return lastch = -1;
}
return lastch;
}
/*
* error - print error information
*/
error(n)
int n;
{ errno[numerrs++] = n;
++total_errors;
}
/*
* getid - get an identifier.
*
* identifiers are any isidch conglomerate
* that doesn't start with a numeric character.
* this set INCLUDES keywords.
*/
int getid()
{ register int i;
i = 0;
while(isidch(lastch)) {
if(i < 19)
lastid[i++] = lastch;
getch();
}
lastid[i] = '\0';
lastst = id;
}
/*
* getsch - get a character in a quoted string.
*
* this routine handles all of the escape mechanisms
* for characters in strings and character constants.
*/
int getsch() /* return an in-quote character */
{ register int i, j;
if(lastch == '\n')
return -1;
if(lastch != '\\') {
i = lastch;
getch();
return i;
}
getch(); /* get an escaped character */
if(isdigit(lastch)) {
i = 0;
for(i = 0;j < 3;++j) {
if(lastch <= '7' && lastch >= '0')
i = (i << 3) + lastch - '0';
else
break;
getch();
}
return i;
}
i = lastch;
getch();
switch(i) {
case '\n':
getch();
return getsch();
case 'b':
return '\b';
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
default:
return i;
}
}
int radix36(c)
char c;
{ if(isdigit(c))
return c - '0';
if(c >= 'a' && c <= 'z')
return c - 'a' + 10;
if(c >= 'A' && c <= 'Z')
return c - 'A' + 10;
return -1;
}
/*
* getbase - get an integer in any base.
*/
getbase(b)
{ register int i, j;
i = 0;
while(isalnum(lastch)) {
if((j = radix36(lastch)) < b) {
i = i * b + j;
getch();
}
else break;
}
ival = i;
lastst = iconst;
}
/*
* getfrac - get fraction part of a floating number.
*/
getfrac()
{ double frmul;
frmul = 0.1;
while(isdigit(lastch)) {
rval += frmul * (lastch - '0');
getch();
frmul *= 0.1;
}
}
/*
* getexp - get exponent part of floating number.
*
* this algorithm is primative but usefull. Floating
* exponents are limited to +/-255 but most hardware
* won't support more anyway.
*/
getexp()
{ double expo, exmul;
expo = 1.0;
if(lastst != rconst)
rval = ival;
if(lastch = '-') {
exmul = 0.1;
getch();
}
else
exmul = 10.0;
getbase(10);
if(ival > 255)
error(ERR_FPCON);
else
while(ival--)
expo *= exmul;
rval *= expo;
}
/*
* getnum - get a number from input.
*
* getnum handles all of the numeric input. it accepts
* decimal, octal, hexidecimal, and floating point numbers.
*/
getnum()
{ register int i, j, k;
i = 0;
if(lastch == '0') {
getch();
if(lastch == 'x' || lastch == 'X') {
getch();
getbase(16);
}
else getbase(8);
}
else {
getbase(10);
if(lastch == '.') {
getch();
rval = ival; /* float the integer part */
getfrac(); /* add the fractional part */
lastst = rconst;
}
if(lastch == 'e' || lastch == 'E') {
getch();
getexp(); /* get the exponent */
}
}
}
/*
* getsym - get next symbol from input stream.
*
* getsym is the basic lexical analyzer. It builds
* basic tokens out of the characters on the input
* stream and sets the following global variables:
*
* lastch: A look behind buffer.
* lastst: type of last symbol read.
* laststr: last string constant read.
* lastid: last identifier read.
* ival: last integer constant read.
* rval: last real constant read.
*
* getsym should be called for all your input needs...
*/
int getsym()
{ register int i, j, k;
SYM *sp;
restart: /* we come back here after comments */
while(isspace(lastch))
getch();
if( lastch == -1)
lastst = eof;
else if(isdigit(lastch))
getnum();
else if(isidch(lastch)) {
getid();
if( (sp = search(lastid,defsyms.head)) != 0 ) {
linstack[lstackptr] = lptr;
chstack[lstackptr++] = lastch;
lptr = sp->value.s;
getch();
goto restart;
}
}
else switch(lastch) {
case '+':
getch();
if(lastch == '+') {
getch();
lastst = autoinc;
}
else if(lastch == '=') {
getch();
lastst = asplus;
}
else lastst = plus;
break;
case '-':
getch();
if(lastch == '-') {
getch();
lastst = autodec;
}
else if(lastch == '=') {
getch();
lastst = asminus;
}
else if(lastch == '>') {
getch();
lastst = pointsto;
}
else lastst = minus;
break;
case '*':
getch();
if(lastch == '=') {
getch();
lastst = astimes;
}
else lastst = star;
break;
case '/':
getch();
if(lastch == '=') {
getch();
lastst = asdivide;
}
else if(lastch == '*') {
getch();
for(;;) {
if(lastch == '*') {
getch();
if(lastch == '/') {
getch();
goto restart;
}
}
else
getch();
}
}
else lastst = divide;
break;
case '^':
getch();
lastst = uparrow;
break;
case ';':
getch();
lastst = semicolon;
break;
case ':':
getch();
lastst = colon;
break;
case '=':
getch();
if(lastch == '=') {
getch();
lastst = eq;
}
else lastst = assign;
break;
case '>':
getch();
if(lastch == '=') {
getch();
lastst = geq;
}
else if(lastch == '>') {
getch();
if(lastch == '=') {
getch();
lastst = asrshift;
}
else lastst = rshift;
}
else lastst = gt;
break;
case '<':
getch();
if(lastch == '=') {
getch();
lastst = leq;
}
else if(lastch == '<') {
getch();
if(lastch == '=') {
getch();
lastst = aslshift;
}
else lastst = lshift;
}
else lastst = lt;
break;
case '\'':
getch();
ival = getsch(); /* get a string char */
if(lastch != '\'')
error(ERR_SYNTAX);
else
getch();
lastst = iconst;
break;
case '\"':
getch();
for(i = 0;i < MAX_STRLEN;++i) {
if(lastch == '\"')
break;
if((j = getsch()) == -1)
break;
else
laststr[i] = j;
}
laststr[i] = 0;
lastst = sconst;
if(lastch != '\"')
error(ERR_SYNTAX);
else
getch();
break;
case '!':
getch();
if(lastch == '=') {
getch();
lastst = neq;
}
else lastst = not;
break;
case '%':
getch();
if(lastch == '=') {
getch();
lastst = asmodop;
}
else lastst = modop;
break;
case '~':
getch();
lastst = compl;
break;
case '.':
getch();
lastst = dot;
break;
case ',':
getch();
lastst = comma;
break;
case '&':
getch();
if( lastch == '&') {
lastst = land;
getch();
}
else if( lastch == '=') {
lastst = asand;
getch();
}
else
lastst = and;
break;
case '|':
getch();
if(lastch == '|') {
lastst = lor;
getch();
}
else if( lastch == '=') {
lastst = asor;
getch();
}
else
lastst = or;
break;
case '(':
getch();
lastst = openpa;
break;
case ')':
getch();
lastst = closepa;
break;
case '[':
getch();
lastst = openbr;
break;
case ']':
getch();
lastst = closebr;
break;
case '{':
getch();
lastst = begin;
break;
case '}':
getch();
lastst = end;
break;
case '?':
getch();
lastst = hook;
break;
default:
getch();
error(ERR_ILLCHAR);
goto restart; /* get a real token */
}
if(lastst == id)
searchkw();
}
needpunc(p)
enum e_sym p;
{ if( lastst == p)
getsym();
else
error(ERR_PUNCT);
}