lots and lots of changes & improvements

This commit is contained in:
eck 1989-09-19 16:13:23 +00:00
parent 18439ffa3f
commit fa4e6eecb4
59 changed files with 1826 additions and 1571 deletions

View file

@ -57,11 +57,9 @@
#define SZ_WORD (arith)4
#define SZ_INT (arith)4
#define SZ_LONG (arith)4
#ifndef NOFLOAT
#define SZ_FLOAT (arith)4
#define SZ_DOUBLE (arith)8
#define SZ_LNGDBL (arith)8 /* for now */
#endif NOFLOAT
#define SZ_POINTER (arith)4
/* target machine alignment requirements */
@ -70,11 +68,9 @@
#define AL_WORD SZ_WORD
#define AL_INT SZ_WORD
#define AL_LONG SZ_WORD
#ifndef NOFLOAT
#define AL_FLOAT SZ_WORD
#define AL_DOUBLE SZ_WORD
#define AL_LNGDBL SZ_WORD
#endif NOFLOAT
#define AL_POINTER SZ_WORD
#define AL_STRUCT 1
#define AL_UNION 1
@ -134,14 +130,6 @@
#define GSTATIC /* for large global "static" arrays */
!File: nofloat.h
#undef NOFLOAT 1 /* if NOT defined, floats are implemented */
!File: noRoption.h
#undef NOROPTION 1 /* if NOT defined, R option is implemented */
!File: nocross.h
#undef NOCROSS 1 /* if NOT defined, cross compiler */

View file

@ -7,7 +7,6 @@
#include "lint.h"
#include <alloc.h>
#include "nofloat.h"
#include "idfsize.h"
#include "numsize.h"
#include "debug.h"
@ -32,6 +31,7 @@ int ReplaceMacros = 1; /* replacing macros */
int AccDefined = 0; /* accept "defined(...)" */
int UnknownIdIsZero = 0; /* interpret unknown id as integer 0 */
int Unstacked = 0; /* an unstack is done */
extern int InputLevel;
#endif
int AccFileSpecifier = 0; /* return filespecifier <...> */
int EoiForNewline = 0; /* return EOI upon encountering newline */
@ -39,6 +39,11 @@ int File_Inserted = 0; /* a file has just been inserted */
int LexSave = 0; /* last character read by GetChar */
#define MAX_LL_DEPTH 2
#define FLG_ESEEN 0x01 /* possibly a floating point number */
#define FLG_DOTSEEN 0x02 /* certainly a floating point number */
extern arith full_mask[];
extern arith max_int;
static struct token LexStack[MAX_LL_DEPTH];
static LexSP = 0;
@ -49,7 +54,7 @@ static LexSP = 0;
*/
PushLex()
{
ASSERT(LexSP < 2);
ASSERT(LexSP < MAX_LL_DEPTH);
ASSERT(ASIDE == 0); /* ASIDE = 0; */
GetToken(&ahead);
LexStack[LexSP++] = dot;
@ -95,12 +100,11 @@ LLlex()
char *string_token();
arith char_constant();
int
GetToken(ptok)
register struct token *ptok;
{
/* LexToken() is the actual token recognizer. It calls the
/* GetToken() is the actual token recognizer. It calls the
control line interpreter if it encounters a "\n{w}*#"
combination. Macro replacement is also performed if it is
needed.
@ -117,7 +121,9 @@ again: /* rescan the input after an error or replacement */
ch = GetChar();
go_on: /* rescan, the following character has been read */
if ((ch & 0200) && ch != EOI) /* stop on non-ascii character */
{
fatal("non-ascii '\\%03o' read", ch & 0377);
}
/* keep track of the place of the token in the file */
ptok->tk_file = FileName;
ptok->tk_line = LineNumber;
@ -152,23 +158,13 @@ firstline:
case STSKIP: /* just skip the skip characters */
goto again;
case STGARB: /* garbage character */
garbage:
if (040 < ch && ch < 0177)
lexerror("garbage char %c", ch);
else
lexerror("garbage char \\%03o", ch);
goto again;
case STSIMP: /* a simple character, no part of compound token*/
if (ch == '/') { /* probably the start of comment */
ch = GetChar();
if (ch == '*') { /* start of comment */
skipcomment();
goto again;
}
else {
UnGetChar();
ch = '/'; /* restore ch */
}
}
return ptok->tk_symb = ch;
case STCOMP: /* maybe the start of a compound token */
nch = GetChar(); /* character lookahead */
@ -181,18 +177,24 @@ firstline:
case '&':
if (nch == '&')
return ptok->tk_symb = AND;
else if (nch == '=')
return ptok->tk_symb = ANDAB;
UnGetChar();
return ptok->tk_symb = ch;
case '+':
if (nch == '+')
return ptok->tk_symb = PLUSPLUS;
else if (nch == '=')
return ptok->tk_symb = PLUSAB;
UnGetChar();
return ptok->tk_symb = ch;
case '-':
if (nch == '-')
return ptok->tk_symb = MINMIN;
if (nch == '>')
else if (nch == '>')
return ptok->tk_symb = ARROW;
else if (nch == '=')
return ptok->tk_symb = MINAB;
UnGetChar();
return ptok->tk_symb = ch;
case '<':
@ -202,8 +204,12 @@ firstline:
'>', &(ptok->tk_len));
return ptok->tk_symb = FILESPECIFIER;
}
if (nch == '<')
if (nch == '<') {
if ((nch = GetChar()) == '=')
return ptok->tk_symb = LEFTAB;
UnGetChar();
return ptok->tk_symb = LEFT;
}
if (nch == '=')
return ptok->tk_symb = LESSEQ;
UnGetChar();
@ -211,64 +217,53 @@ firstline:
case '=':
if (nch == '=')
return ptok->tk_symb = EQUAL;
/* The following piece of code tries to recognise
old-fashioned assignment operators `=op'
Note however, that these are removed from the
ANSI C standard.
*/
switch (nch) {
case '+':
ptok->tk_symb = PLUSAB;
goto warn;
case '-':
ptok->tk_symb = MINAB;
goto warn;
case '*':
ptok->tk_symb = TIMESAB;
goto warn;
case '/':
ptok->tk_symb = DIVAB;
goto warn;
case '%':
ptok->tk_symb = MODAB;
goto warn;
case '>':
case '<':
GetChar(ch);
if (ch != nch) {
UnGetChar();
lexerror("illegal combination '=%c'",
nch);
}
ptok->tk_symb = nch == '<' ? LEFTAB : RIGHTAB;
goto warn;
case '&':
ptok->tk_symb = ANDAB;
goto warn;
case '^':
ptok->tk_symb = XORAB;
goto warn;
case '|':
ptok->tk_symb = ORAB;
warn:
warning("Old-fashioned assignment operator");
return ptok->tk_symb;
}
UnGetChar();
return ptok->tk_symb = ch;
case '>':
if (nch == '=')
return ptok->tk_symb = GREATEREQ;
if (nch == '>')
if (nch == '>') {
if ((nch = GetChar()) == '=')
return ptok->tk_symb = RIGHTAB;
UnGetChar();
return ptok->tk_symb = RIGHT;
}
UnGetChar();
return ptok->tk_symb = ch;
case '|':
if (nch == '|')
return ptok->tk_symb = OR;
else if (nch == '=')
return ptok->tk_symb = ORAB;
UnGetChar();
return ptok->tk_symb = ch;
case '%':
if (nch == '=')
return ptok->tk_symb = MODAB;
UnGetChar();
return ptok->tk_symb = ch;
case '*':
if (nch == '=')
return ptok->tk_symb = TIMESAB;
UnGetChar();
return ptok->tk_symb = ch;
case '^':
if (nch == '=')
return ptok->tk_symb = XORAB;
UnGetChar();
return ptok->tk_symb = ch;
case '/':
if (nch == '*' && !InputLevel) {
skipcomment();
goto again;
}
else if (nch == '=')
return ptok->tk_symb = DIVAB;
UnGetChar();
return ptok->tk_symb = ch;
default:
crash("bad class for char 0%o", ch);
/* NOTREACHED */
}
case STCHAR: /* character constant */
ptok->tk_ival = char_constant("character");
@ -291,6 +286,7 @@ firstline:
return ptok->tk_symb = INTEGER;
}
UnGetChar();
/* fallthrough */
case STIDF:
{
register char *tg = &buf[0];
@ -298,7 +294,15 @@ firstline:
register int hash;
register struct idf *idef;
extern int idfsize; /* ??? */
#ifndef NOPP
int NoExpandNext = 0;
if (Unstacked) EnableMacros(); /* unstack macro's when allowed. */
if (ch == NOEXPM) {
NoExpandNext = 1;
ch = GetChar();
}
#endif
hash = STARTHASH();
do { /* read the identifier */
if (++pos < idfsize) {
@ -316,12 +320,16 @@ firstline:
idef->id_file = ptok->tk_file;
idef->id_line = ptok->tk_line;
#ifndef NOPP
if (idef->id_macro && ReplaceMacros) {
if (idef->id_macro && ReplaceMacros && !NoExpandNext) {
#if 0
if (idef->id_macro->mc_count > 0)
idef->id_macro->mc_count--;
else if (replace(idef))
goto again;
else
#endif /* 0 */
if (replace(idef))
goto again;
}
NoExpandNext = 0;
if (UnknownIdIsZero && idef->id_reserved != SIZEOF) {
ptok->tk_ival = (arith)0;
ptok->tk_fund = INT;
@ -338,171 +346,85 @@ firstline:
}
case STNUM: /* a numeric constant */
{
register char *np = &buf[1];
register int base = 10;
register int vch;
register arith val = 0;
register int siz_left = NUMSIZE - 1;
register char *np = &buf[0];
int flags = 0;
#define store(ch) if (--siz_left >= 0) \
*np++ = ch;
if (ch == '.') {
#ifndef NOFLOAT
/* A very embarrasing ambiguity. We have either a
floating point number or field operator or
ELLIPSIS.
/* An embarrasing ambiguity. We have either a
pp-number, a field operator, an ELLIPSIS or
an error (..).
*/
vch = GetChar();
if (!is_dig(vch)) { /* . or ... */
if (vch == '.') {
if ((vch = GetChar()) == '.')
ch = GetChar();
if (!is_dig(ch)) { /* . or ... */
if (ch == '.') {
if ((ch = GetChar()) == '.')
return ptok->tk_symb = ELLIPSIS;
/* This is funny: we can't push the
second dot back. But then again
..<ch> is already an error in C,
so why bother ?
*/
UnGetChar();
lexerror("illegal combination '..'");
}
UnGetChar();
UnGetChar(); /* not '.' */
ChPushBack('.'); /* sigh ... */
} else
UnGetChar(); /* not '.' */
return ptok->tk_symb = '.';
}
*np++ = '0';
UnGetChar();
#else
if ((vch = GetChar()) == '.') {
if ((vch = GetChar()) == '.')
return ptok->tk_symb = ELLIPSIS;
UnGetChar();
lexerror("illegal combination '..'");
}
UnGetChar();
return ptok->tk_symb = '.';
#endif
}
if (ch == '0') {
*np++ = ch;
ch = GetChar();
if (ch == 'x' || ch == 'X') {
base = 16;
ch = '.';
flags |= FLG_DOTSEEN;
}
store(ch);
ch = GetChar();
while(in_idf(ch) || ch == '.') {
store(ch);
if (ch == '.') flags |= FLG_DOTSEEN;
if (ch == 'e' || ch == 'E') {
flags |= FLG_ESEEN;
ch = GetChar();
}
else
base = 8;
}
while (vch = val_in_base(ch, base), vch >= 0) {
val = val*base + vch;
if (np < &buf[NUMSIZE])
*np++ = ch;
ch = GetChar();
}
if (is_suf(ch)) {
register int suf_long = 0;
register int suf_unsigned = 0;
/* The type of the integal constant is
based on its suffix.
*/
do {
switch (ch) {
case 'l':
case 'L':
suf_long++;
break;
case 'u':
case 'U':
suf_unsigned++;
break;
if (ch == '+' || ch == '-') {
flags |= FLG_DOTSEEN; /* trick */
store(ch);
ch = GetChar();
}
ch = GetChar();
} while (is_suf(ch));
UnGetChar();
} else ch = GetChar();
}
store('\0');
UnGetChar();
if (suf_long > 1)
lexerror("only one long suffix allowed");
if (suf_unsigned > 1)
lexerror("only one unsigned suffix allowed");
ptok->tk_fund = (suf_long && suf_unsigned) ? ULONG :
(suf_long) ? LONG : UNSIGNED;
ptok->tk_ival = val;
return ptok->tk_symb = INTEGER;
}
#ifndef NOFLOAT
if (base == 16 || !(ch == '.' || ch == 'e' || ch == 'E'))
#endif NOFLOAT
{
UnGetChar();
ptok->tk_ival = val;
/* The semantic analyser must know if the
integral constant is given in octal/hexa-
decimal form, in which case its type is
UNSIGNED, or in decimal form, in which case
its type is signed, indicated by
the fund INTEGER.
*/
ptok->tk_fund =
(base == 10 || (base == 8 && val == (arith)0))
? INTEGER : UNSIGNED;
return ptok->tk_symb = INTEGER;
}
/* where's the test for the length of the integral ??? */
#ifndef NOFLOAT
if (ch == '.'){
if (np < &buf[NUMSIZE])
*np++ = ch;
ch = GetChar();
}
while (is_dig(ch)){
if (np < &buf[NUMSIZE])
*np++ = ch;
ch = GetChar();
}
if (ch == 'e' || ch == 'E') {
if (np < &buf[NUMSIZE])
*np++ = ch;
ch = GetChar();
if (ch == '+' || ch == '-') {
if (np < &buf[NUMSIZE])
*np++ = ch;
ch = GetChar();
}
if (!is_dig(ch)) {
lexerror("malformed floating constant");
if (np < &buf[NUMSIZE])
*np++ = ch;
}
while (is_dig(ch)) {
if (np < &buf[NUMSIZE])
*np++ = ch;
ch = GetChar();
np = &buf[0];
ch = *np++;
if (siz_left < 0) {
lexerror("number too long");
if ((flags & FLG_DOTSEEN)
|| (flags & FLG_ESEEN
&& !(ch == '0'
&& (*np == 'x' || *np == 'X')))) {
ptok->tk_fval = Salloc("0.0", (unsigned) 4);
ptok->tk_fund = DOUBLE;
return ptok->tk_symb = FLOATING;
}
ptok->tk_ival = 1;
ptok->tk_fund = ULONG;
ptok->tk_symb = INTEGER;
}
/* The type of an integral floating point
constant may be given by the float (f)
or long double (l) suffix.
*/
if (ch == 'f' || ch == 'F')
ptok->tk_fund = FLOAT;
else if (ch == 'l' || ch == 'L')
ptok->tk_fund = LNGDBL;
else {
ptok->tk_fund = DOUBLE;
UnGetChar();
/* Now, the pp-number must be converted into a token */
if ((flags & FLG_DOTSEEN)
|| (flags & FLG_ESEEN
&& !(ch == '0' && (*np == 'x' || *np == 'X')))) {
strflt2tok(&buf[0], ptok);
return ptok->tk_symb = FLOATING;
}
*np++ = '\0';
buf[0] = '-'; /* good heavens... */
if (np == &buf[NUMSIZE+1]) {
lexerror("floating constant too long");
ptok->tk_fval = Salloc("0.0",(unsigned) 5) + 1;
}
else
ptok->tk_fval = Salloc(buf,(unsigned) (np - buf)) + 1;
return ptok->tk_symb = FLOATING;
#endif NOFLOAT
strint2tok(&buf[0], ptok);
return ptok->tk_symb = INTEGER;
}
case STEOI: /* end of text on source file */
return ptok->tk_symb = EOI;
#ifndef NOPP
case STMSPEC:
if (!InputLevel) goto garbage;
if (ch == TOKSEP) goto again;
/* fallthrough shouldn't happen */
#endif
default: /* this cannot happen */
crash("bad class for char 0%o", ch);
}
@ -533,16 +455,13 @@ skipcomment()
while (c != '*') {
if (class(c) == STNL) {
++LineNumber;
} else
if (c == EOI) {
} else if (c == EOI) {
NoUnstack--;
#ifdef LINT
lint_end_comment();
#endif LINT
return;
}
if (c == '/' && (c = GetChar()) == '*')
strict("extra comment delimiter found");
c = GetChar();
#ifdef LINT
lint_comment_char(c);
@ -580,7 +499,8 @@ char_constant(nm)
if (ch == '\\')
ch = quoted(GetChar());
if (ch >= 128) ch -= 256;
val = val*256 + ch;
if (size < (int)int_size)
val |= ch << 8 * size;
size++;
ch = GetChar();
}
@ -612,7 +532,7 @@ string_token(nm, stop_char, plen)
lexerror("end-of-file inside %s", nm);
break;
}
if (ch == '\\')
if (ch == '\\' && !AccFileSpecifier)
ch = quoted(GetChar());
str[pos++] = ch;
if (pos == str_size)
@ -776,3 +696,134 @@ trigraph()
PushBack();
return('?');
}
/* strflt2tok only checks the syntax of the floating-point number and
* selects the right type for the number.
*/
strflt2tok(fltbuf, ptok)
char fltbuf[];
struct token *ptok;
{
register char *cp = fltbuf;
int malformed = 0;
while (is_dig(*cp)) cp++;
if (*cp == '.') {
cp++;
while (is_dig(*cp)) cp++;
}
if (*cp == 'e' || *cp == 'E') {
cp++;
if (*cp == '+' || *cp == '-')
cp++;
if (!is_dig(*cp)) malformed++;
while (is_dig(*cp)) cp++;
}
if (*cp == 'f' || *cp == 'F') {
if (*(cp + 1)) malformed++;
*cp = '\0';
ptok->tk_fund = FLOAT;
} else if (*cp == 'l' || *cp == 'L') {
if (*(cp + 1)) malformed++;
*cp = '\0';
ptok->tk_fund = LNGDBL;
} else {
ptok->tk_fund = DOUBLE;
}
if (*cp) malformed++;
if (malformed) {
lexerror("malformed floating constant");
ptok->tk_fval = Salloc("0.0", (unsigned) 4);
} else {
ptok->tk_fval = Salloc(fltbuf, (unsigned) (cp - fltbuf + 1));
}
}
strint2tok(intbuf, ptok)
char intbuf[];
struct token *ptok;
{
register char *cp = intbuf;
int base = 10;
arith val = 0, dig, ubound;
int uns_flg = 0, lng_flg = 0, malformed = 0, ovfl = 0;
int fund;
ASSERT(*cp != '-');
if (*cp == '0') {
cp++;
if (*cp == 'x' || *cp == 'X') {
cp++;
base = 16;
} else base = 8;
}
/* The upperbound will be the same as when computed with
* max_unsigned_arith / base (since base is even). The problem here
* is that unsigned arith is not accepted by all compilers.
*/
ubound = max_arith / (base / 2);
while (is_hex(*cp)) {
dig = is_dig(*cp) ? *cp - '0'
: (( *cp >= 'A' && *cp <= 'F' ? *cp - 'A'
: *cp - 'a')
+ 10) ;
if (dig >= base) {
malformed++; /* ignore */
}
else {
if (val < 0 || val > ubound) ovfl++;
val *= base;
if (val < 0 && val + dig >= 0) ovfl++;
val += dig;
}
cp++;
}
while (*cp) {
if (*cp == 'l' || *cp == 'L') lng_flg++;
else if (*cp == 'u' || *cp == 'U') uns_flg++;
else break;
cp++;
}
if (*cp) {
malformed++;
}
if (malformed) {
lexerror("malformed %s integer constant",
(base == 10 ? "decimal"
: (base == 8 ? "octal"
: "hexadecimal")));
} else {
if (lng_flg > 1)
lexerror("only one long suffix allowed");
if (uns_flg > 1)
lexerror("only one unsigned suffix allowed");
}
if (ovfl) {
lexwarning("overflow in constant");
fund = ULONG;
} else if ((val & full_mask[(int)int_size]) == val) {
if (val >= 0 && val <= max_int) fund = INT;
else fund = (base == 10 ? LONG : UNSIGNED);
} else if((val & full_mask[(int)long_size]) == val) {
if (val > 0) fund = LONG;
else fund = ULONG;
} else { /* sizeof(arith) is greater than long_size */
ASSERT(arith_size > long_size);
lexwarning("constant too large for target machine");
/* cut the size to prevent further complaints */
val &= full_mask[(int)long_size];
fund = ULONG;
}
if (lng_flg) {
if (fund == INT) fund = LONG;
else if (fund == UNSIGNED) fund = ULONG;
}
if (uns_flg) {
if (fund == INT) fund = UNSIGNED;
else if (fund == LONG) fund = ULONG;
}
ptok->tk_fund = fund;
ptok->tk_ival = val;
}

View file

@ -10,7 +10,6 @@
to it.
*/
#include "nofloat.h"
#include "file_info.h"
#include "nopp.h"
@ -27,9 +26,7 @@ struct token {
int tok_len; /* length of row of bytes */
} tok_string;
arith tok_ival; /* for INTEGER */
#ifndef NOFLOAT
char *tok_fval; /* for FLOATING */
#endif NOFLOAT
} tok_data;
};
@ -41,9 +38,7 @@ struct token {
#define tk_bts tok_data.tok_string.tok_bts
#define tk_len tok_data.tok_string.tok_len
#define tk_ival tok_data.tok_ival
#ifndef NOFLOAT
#define tk_fval tok_data.tok_fval
#endif NOFLOAT
extern struct token dot, ahead, aside;

View file

@ -6,7 +6,6 @@
/* PARSER ERROR ADMINISTRATION */
#include <alloc.h>
#include "nofloat.h"
#include "idf.h"
#include "arith.h"
#include "LLlex.h"
@ -50,10 +49,8 @@ insert_token(tk)
dot.tk_fund = INT;
dot.tk_ival = 1;
break;
#ifndef NOFLOAT
case FLOATING:
dot.tk_fval = Salloc("0.0", 4);
break;
#endif NOFLOAT
}
}

View file

@ -52,10 +52,8 @@
#define SZ_WORD (arith)4
#define SZ_INT (arith)4
#define SZ_LONG (arith)4
#ifndef NOFLOAT
#define SZ_FLOAT (arith)4
#define SZ_DOUBLE (arith)8
#endif NOFLOAT
#define SZ_POINTER (arith)4
/* target machine alignment requirements */
@ -64,10 +62,8 @@
#define AL_WORD SZ_WORD
#define AL_INT SZ_WORD
#define AL_LONG SZ_WORD
#ifndef NOFLOAT
#define AL_FLOAT SZ_WORD
#define AL_DOUBLE SZ_WORD
#endif NOFLOAT
#define AL_POINTER SZ_WORD
#define AL_STRUCT 1
#define AL_UNION 1
@ -127,14 +123,6 @@
#define GSTATIC /* for large global "static" arrays */
!File: nofloat.h
#undef NOFLOAT 1 /* if NOT defined, floats are implemented */
!File: noRoption.h
#undef NOROPTION 1 /* if NOT defined, R option is implemented */
!File: nocross.h
#undef NOCROSS 1 /* if NOT defined, cross compiler */

View file

@ -4,7 +4,7 @@
# Machine and environ dependent definitions
EMHOME = ../../..
CC = cc
CC = /proj/em/Work/bin/fcc.cc
CC = $(EMHOME)/bin/fcc
CFLOW = cflow
MKDEP = $(EMHOME)/bin/mkdep
PRID = $(EMHOME)/bin/prid
@ -17,6 +17,7 @@ EMOLIB = $(EMHOME)/modules/lib/libemopt.a
EMELIB = $(EMHOME)/modules/lib/libeme.a $(EMHOME)/lib/em_data.a
STRLIB = $(EMHOME)/modules/lib/libstring.a
PRTLIB = $(EMHOME)/modules/lib/libprint.a
FLTLIB = $(EMHOME)/modules/lib/libflt.a
EMMESLIB = $(EMHOME)/modules/lib/libem_mes.a
EMMESOLIB = $(EMHOME)/modules/lib/libem_mesO.a
EMMESCELIB = $(EMHOME)/modules/lib/libem_mesCE.a
@ -28,15 +29,15 @@ INPLIB = $(EMHOME)/modules/lib/libinput.a
ALLOCLIB = $(EMHOME)/modules/lib/liballoc.a
MALLOC = $(EMHOME)/modules/lib/malloc.o
LIBS = $(INPLIB) $(EMMESLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) \
$(ALLOCLIB) $(MALLOC) $(SYSLIB)
$(ALLOCLIB) $(MALLOC) $(SYSLIB) $(FLTLIB)
ELIBS = $(INPLIB) $(EMMESLIB) $(EMELIB) $(PRTLIB) $(STRLIB) \
$(ALLOCLIB) $(MALLOC) $(SYSLIB)
$(ALLOCLIB) $(MALLOC) $(SYSLIB) $(FLTLIB)
OLIBS = $(INPLIB) $(EMMESOLIB) $(EMOLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) \
$(ALLOCLIB) $(MALLOC) $(SYSLIB)
$(ALLOCLIB) $(MALLOC) $(SYSLIB) $(FLTLIB)
CELIBS = $(INPLIB) $(EMMESCELIB) $(EMCELIB) $(PRTLIB) $(STRLIB) \
$(ALLOCLIB) $(MALLOC) $(SYSLIB)
$(ALLOCLIB) $(MALLOC) $(SYSLIB) $(FLTLIB)
LLIBS = $(INPLIB) $(EMMESLIB) $(PRTLIB) $(STRLIB) \
$(ALLOCLIB) $(MALLOC) $(SYSLIB)
$(ALLOCLIB) $(MALLOC) $(SYSLIB) $(FLTLIB)
LIB_INCLUDES = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg
EM_INCLUDES = -I$(EMHOME)/h
SYSLLIB = $(EMHOME)/modules/lib/llib-lsystem.ln
@ -70,7 +71,7 @@ LOBJ = tokenfile.o declar.o statement.o expression.o program.o Lpars.o ival.o
# Objects of hand-written C files
CSRC = main.c idf.c declarator.c decspecs.c struct.c \
expr.c ch7.c ch7bin.c cstoper.c arith.c \
expr.c ch7.c ch7bin.c cstoper.c fltcstoper.c arith.c \
code.c dumpidf.c error.c field.c\
tokenname.c LLlex.c LLmessage.c \
input.c domacro.c replace.c init.c options.c \
@ -79,7 +80,7 @@ CSRC = main.c idf.c declarator.c decspecs.c struct.c \
pragma.c blocks.c dataflow.c Version.c \
l_lint.c l_states.c l_misc.c l_ev_ord.c l_outdef.c l_comment.c l_dummy.c
COBJ = main.o idf.o declarator.o decspecs.o struct.o \
expr.o ch7.o ch7bin.o cstoper.o arith.o \
expr.o ch7.o ch7bin.o cstoper.o fltcstoper.o arith.o \
code.o dumpidf.o error.o field.o\
tokenname.o LLlex.o LLmessage.o \
input.o domacro.o replace.o init.o options.o \
@ -106,7 +107,7 @@ GSRC = $(GCSRC) $(GHSTRSRC)
# .h files generated by `make hfiles LLfiles'; PLEASE KEEP THIS UP-TO-DATE!
GHSRC = botch_free.h dataflow.h debug.h density.h errout.h \
idfsize.h ifdepth.h inputtype.h lapbuf.h argbuf.h lint.h \
nobitfield.h nofloat.h nopp.h noRoption.h nocross.h \
nobitfield.h nopp.h nocross.h \
nparams.h numsize.h parbufsize.h pathlength.h Lpars.h \
strsize.h target_sizes.h textsize.h use_tmp.h spec_arith.h static.h \
regcount.h
@ -290,10 +291,8 @@ main.o: input.h
main.o: inputtype.h
main.o: level.h
main.o: lint.h
main.o: noRoption.h
main.o: nobitfield.h
main.o: nocross.h
main.o: nofloat.h
main.o: nopp.h
main.o: proto.h
main.o: sizes.h
@ -319,10 +318,8 @@ idf.o: idfsize.h
idf.o: label.h
idf.o: level.h
idf.o: lint.h
idf.o: noRoption.h
idf.o: nobitfield.h
idf.o: nocross.h
idf.o: nofloat.h
idf.o: nopp.h
idf.o: nparams.h
idf.o: proto.h
@ -346,7 +343,6 @@ declarator.o: level.h
declarator.o: lint.h
declarator.o: nobitfield.h
declarator.o: nocross.h
declarator.o: nofloat.h
declarator.o: nopp.h
declarator.o: proto.h
declarator.o: sizes.h
@ -361,9 +357,7 @@ decspecs.o: decspecs.h
decspecs.o: def.h
decspecs.o: level.h
decspecs.o: lint.h
decspecs.o: noRoption.h
decspecs.o: nobitfield.h
decspecs.o: nofloat.h
decspecs.o: spec_arith.h
decspecs.o: type.h
struct.o: LLlex.h
@ -379,10 +373,8 @@ struct.o: file_info.h
struct.o: idf.h
struct.o: level.h
struct.o: lint.h
struct.o: noRoption.h
struct.o: nobitfield.h
struct.o: nocross.h
struct.o: nofloat.h
struct.o: nopp.h
struct.o: proto.h
struct.o: sizes.h
@ -394,7 +386,9 @@ struct.o: type.h
expr.o: LLlex.h
expr.o: Lpars.h
expr.o: arith.h
expr.o: assert.h
expr.o: botch_free.h
expr.o: debug.h
expr.o: declar.h
expr.o: decspecs.h
expr.o: def.h
@ -404,10 +398,8 @@ expr.o: idf.h
expr.o: label.h
expr.o: level.h
expr.o: lint.h
expr.o: noRoption.h
expr.o: nobitfield.h
expr.o: nocross.h
expr.o: nofloat.h
expr.o: nopp.h
expr.o: sizes.h
expr.o: spec_arith.h
@ -424,7 +416,6 @@ ch7.o: idf.h
ch7.o: label.h
ch7.o: lint.h
ch7.o: nobitfield.h
ch7.o: nofloat.h
ch7.o: nopp.h
ch7.o: proto.h
ch7.o: spec_arith.h
@ -437,9 +428,7 @@ ch7bin.o: expr.h
ch7bin.o: idf.h
ch7bin.o: label.h
ch7bin.o: lint.h
ch7bin.o: noRoption.h
ch7bin.o: nobitfield.h
ch7bin.o: nofloat.h
ch7bin.o: nopp.h
ch7bin.o: spec_arith.h
ch7bin.o: struct.h
@ -453,24 +442,37 @@ cstoper.o: idf.h
cstoper.o: label.h
cstoper.o: nobitfield.h
cstoper.o: nocross.h
cstoper.o: nofloat.h
cstoper.o: nopp.h
cstoper.o: sizes.h
cstoper.o: spec_arith.h
cstoper.o: target_sizes.h
cstoper.o: type.h
fltcstoper.o: Lpars.h
fltcstoper.o: arith.h
fltcstoper.o: assert.h
fltcstoper.o: debug.h
fltcstoper.o: expr.h
fltcstoper.o: idf.h
fltcstoper.o: label.h
fltcstoper.o: nobitfield.h
fltcstoper.o: nocross.h
fltcstoper.o: nopp.h
fltcstoper.o: sizes.h
fltcstoper.o: spec_arith.h
fltcstoper.o: target_sizes.h
fltcstoper.o: type.h
arith.o: Lpars.h
arith.o: arith.h
arith.o: assert.h
arith.o: debug.h
arith.o: expr.h
arith.o: field.h
arith.o: idf.h
arith.o: label.h
arith.o: lint.h
arith.o: mes.h
arith.o: noRoption.h
arith.o: nobitfield.h
arith.o: nocross.h
arith.o: nofloat.h
arith.o: nopp.h
arith.o: proto.h
arith.o: sizes.h
@ -495,10 +497,8 @@ code.o: l_lint.h
code.o: label.h
code.o: level.h
code.o: lint.h
code.o: noRoption.h
code.o: nobitfield.h
code.o: nocross.h
code.o: nofloat.h
code.o: nopp.h
code.o: sizes.h
code.o: spec_arith.h
@ -519,7 +519,6 @@ dumpidf.o: idf.h
dumpidf.o: label.h
dumpidf.o: lint.h
dumpidf.o: nobitfield.h
dumpidf.o: nofloat.h
dumpidf.o: nopp.h
dumpidf.o: proto.h
dumpidf.o: spec_arith.h
@ -536,7 +535,6 @@ error.o: expr.h
error.o: file_info.h
error.o: label.h
error.o: lint.h
error.o: nofloat.h
error.o: nopp.h
error.o: spec_arith.h
error.o: tokenname.h
@ -553,7 +551,6 @@ field.o: label.h
field.o: lint.h
field.o: nobitfield.h
field.o: nocross.h
field.o: nofloat.h
field.o: nopp.h
field.o: sizes.h
field.o: spec_arith.h
@ -564,7 +561,6 @@ tokenname.o: Lpars.h
tokenname.o: arith.h
tokenname.o: file_info.h
tokenname.o: idf.h
tokenname.o: nofloat.h
tokenname.o: nopp.h
tokenname.o: spec_arith.h
tokenname.o: tokenname.h
@ -582,7 +578,6 @@ LLlex.o: input.h
LLlex.o: lint.h
LLlex.o: macro.h
LLlex.o: nocross.h
LLlex.o: nofloat.h
LLlex.o: nopp.h
LLlex.o: numsize.h
LLlex.o: sizes.h
@ -594,7 +589,6 @@ LLmessage.o: Lpars.h
LLmessage.o: arith.h
LLmessage.o: file_info.h
LLmessage.o: idf.h
LLmessage.o: nofloat.h
LLmessage.o: nopp.h
LLmessage.o: spec_arith.h
input.o: file_info.h
@ -614,7 +608,6 @@ domacro.o: idfsize.h
domacro.o: ifdepth.h
domacro.o: input.h
domacro.o: macro.h
domacro.o: nofloat.h
domacro.o: nopp.h
domacro.o: nparams.h
domacro.o: parbufsize.h
@ -632,7 +625,6 @@ replace.o: idfsize.h
replace.o: input.h
replace.o: lapbuf.h
replace.o: macro.h
replace.o: nofloat.h
replace.o: nopp.h
replace.o: nparams.h
replace.o: numsize.h
@ -654,10 +646,8 @@ options.o: idf.h
options.o: idfsize.h
options.o: lint.h
options.o: macro.h
options.o: noRoption.h
options.o: nobitfield.h
options.o: nocross.h
options.o: nofloat.h
options.o: nopp.h
options.o: sizes.h
options.o: spec_arith.h
@ -668,7 +658,6 @@ skip.o: arith.h
skip.o: class.h
skip.o: file_info.h
skip.o: input.h
skip.o: nofloat.h
skip.o: nopp.h
skip.o: spec_arith.h
stack.o: Lpars.h
@ -680,9 +669,7 @@ stack.o: idf.h
stack.o: level.h
stack.o: lint.h
stack.o: mes.h
stack.o: noRoption.h
stack.o: nobitfield.h
stack.o: nofloat.h
stack.o: nopp.h
stack.o: spec_arith.h
stack.o: stack.h
@ -698,7 +685,6 @@ type.o: idf.h
type.o: lint.h
type.o: nobitfield.h
type.o: nocross.h
type.o: nofloat.h
type.o: nopp.h
type.o: proto.h
type.o: sizes.h
@ -714,7 +700,6 @@ ch7mon.o: idf.h
ch7mon.o: label.h
ch7mon.o: lint.h
ch7mon.o: nobitfield.h
ch7mon.o: nofloat.h
ch7mon.o: nopp.h
ch7mon.o: spec_arith.h
ch7mon.o: type.h
@ -725,9 +710,7 @@ label.o: idf.h
label.o: label.h
label.o: level.h
label.o: lint.h
label.o: noRoption.h
label.o: nobitfield.h
label.o: nofloat.h
label.o: nopp.h
label.o: spec_arith.h
label.o: type.h
@ -748,7 +731,6 @@ eval.o: lint.h
eval.o: mes.h
eval.o: nobitfield.h
eval.o: nocross.h
eval.o: nofloat.h
eval.o: nopp.h
eval.o: sizes.h
eval.o: spec_arith.h
@ -766,19 +748,19 @@ switch.o: density.h
switch.o: expr.h
switch.o: idf.h
switch.o: label.h
switch.o: noRoption.h
switch.o: nobitfield.h
switch.o: nofloat.h
switch.o: nocross.h
switch.o: nopp.h
switch.o: sizes.h
switch.o: spec_arith.h
switch.o: switch.h
switch.o: target_sizes.h
switch.o: type.h
conversion.o: Lpars.h
conversion.o: arith.h
conversion.o: lint.h
conversion.o: nobitfield.h
conversion.o: nocross.h
conversion.o: nofloat.h
conversion.o: sizes.h
conversion.o: spec_arith.h
conversion.o: target_sizes.h
@ -788,7 +770,6 @@ util.o: align.h
util.o: def.h
util.o: lint.h
util.o: nocross.h
util.o: nofloat.h
util.o: regcount.h
util.o: sizes.h
util.o: stack.h
@ -812,7 +793,6 @@ proto.o: level.h
proto.o: lint.h
proto.o: nobitfield.h
proto.o: nocross.h
proto.o: nofloat.h
proto.o: nopp.h
proto.o: nparams.h
proto.o: proto.h
@ -834,7 +814,6 @@ pragma.o: idfsize.h
pragma.o: ifdepth.h
pragma.o: input.h
pragma.o: macro.h
pragma.o: nofloat.h
pragma.o: nopp.h
pragma.o: nparams.h
pragma.o: parbufsize.h
@ -847,7 +826,6 @@ blocks.o: atw.h
blocks.o: label.h
blocks.o: lint.h
blocks.o: nocross.h
blocks.o: nofloat.h
blocks.o: sizes.h
blocks.o: spec_arith.h
blocks.o: stack.h
@ -871,7 +849,6 @@ l_lint.o: label.h
l_lint.o: level.h
l_lint.o: lint.h
l_lint.o: nobitfield.h
l_lint.o: nofloat.h
l_lint.o: nopp.h
l_lint.o: spec_arith.h
l_lint.o: stack.h
@ -896,7 +873,6 @@ l_states.o: label.h
l_states.o: level.h
l_states.o: lint.h
l_states.o: nobitfield.h
l_states.o: nofloat.h
l_states.o: nopp.h
l_states.o: spec_arith.h
l_states.o: stack.h
@ -915,7 +891,6 @@ l_misc.o: label.h
l_misc.o: level.h
l_misc.o: lint.h
l_misc.o: nobitfield.h
l_misc.o: nofloat.h
l_misc.o: nopp.h
l_misc.o: spec_arith.h
l_misc.o: stack.h
@ -937,7 +912,6 @@ l_ev_ord.o: label.h
l_ev_ord.o: level.h
l_ev_ord.o: lint.h
l_ev_ord.o: nobitfield.h
l_ev_ord.o: nofloat.h
l_ev_ord.o: nopp.h
l_ev_ord.o: spec_arith.h
l_ev_ord.o: stack.h
@ -962,7 +936,6 @@ l_outdef.o: label.h
l_outdef.o: level.h
l_outdef.o: lint.h
l_outdef.o: nobitfield.h
l_outdef.o: nofloat.h
l_outdef.o: nopp.h
l_outdef.o: spec_arith.h
l_outdef.o: stack.h
@ -998,7 +971,6 @@ declar.o: level.h
declar.o: lint.h
declar.o: nobitfield.h
declar.o: nocross.h
declar.o: nofloat.h
declar.o: nopp.h
declar.o: proto.h
declar.o: sizes.h
@ -1021,7 +993,6 @@ statement.o: l_state.h
statement.o: label.h
statement.o: lint.h
statement.o: nobitfield.h
statement.o: nofloat.h
statement.o: nopp.h
statement.o: spec_arith.h
statement.o: stack.h
@ -1035,9 +1006,7 @@ expression.o: file_info.h
expression.o: idf.h
expression.o: label.h
expression.o: lint.h
expression.o: noRoption.h
expression.o: nobitfield.h
expression.o: nofloat.h
expression.o: nopp.h
expression.o: spec_arith.h
expression.o: type.h
@ -1055,7 +1024,6 @@ program.o: l_state.h
program.o: label.h
program.o: lint.h
program.o: nobitfield.h
program.o: nofloat.h
program.o: nopp.h
program.o: spec_arith.h
program.o: type.h
@ -1075,10 +1043,8 @@ ival.o: l_lint.h
ival.o: label.h
ival.o: level.h
ival.o: lint.h
ival.o: noRoption.h
ival.o: nobitfield.h
ival.o: nocross.h
ival.o: nofloat.h
ival.o: nopp.h
ival.o: proto.h
ival.o: sizes.h

View file

@ -57,11 +57,9 @@
#define SZ_WORD (arith)4
#define SZ_INT (arith)4
#define SZ_LONG (arith)4
#ifndef NOFLOAT
#define SZ_FLOAT (arith)4
#define SZ_DOUBLE (arith)8
#define SZ_LNGDBL (arith)8 /* for now */
#endif NOFLOAT
#define SZ_POINTER (arith)4
/* target machine alignment requirements */
@ -70,11 +68,9 @@
#define AL_WORD SZ_WORD
#define AL_INT SZ_WORD
#define AL_LONG SZ_WORD
#ifndef NOFLOAT
#define AL_FLOAT SZ_WORD
#define AL_DOUBLE SZ_WORD
#define AL_LNGDBL SZ_WORD
#endif NOFLOAT
#define AL_POINTER SZ_WORD
#define AL_STRUCT 1
#define AL_UNION 1
@ -134,14 +130,6 @@
#define GSTATIC /* for large global "static" arrays */
!File: nofloat.h
#undef NOFLOAT 1 /* if NOT defined, floats are implemented */
!File: noRoption.h
#define NOROPTION 1 /* if NOT defined, R option is implemented */
!File: nocross.h
#undef NOCROSS 1 /* if NOT defined, cross compiler */

View file

@ -5,16 +5,13 @@
/* $Header$ */
/* A L I G N M E N T D E F I N I T I O N S */
#include "nofloat.h"
#include "nocross.h"
#include "target_sizes.h"
#ifndef NOCROSS
extern int
short_align, word_align, int_align, long_align,
#ifndef NOFLOAT
float_align, double_align, lngdbl_align,
#endif NOFLOAT
pointer_align,
struct_align, union_align;
#else NOCROSS
@ -22,11 +19,9 @@ extern int
#define word_align ((int)AL_WORD)
#define int_align ((int)AL_INT)
#define long_align ((int)AL_LONG)
#ifndef NOFLOAT
#define float_align ((int)AL_FLOAT)
#define double_align ((int)AL_DOUBLE)
#define lngdbl_align ((int)AL_LNGDBL)
#endif NOFLOAT
#define pointer_align ((int)AL_POINTER)
#define struct_align ((int)AL_STRUCT)
#define union_align ((int)AL_UNION)

View file

@ -13,9 +13,9 @@
#include <alloc.h>
#include "lint.h"
#include "nofloat.h"
#include "nobitfield.h"
#include "idf.h"
#include <flt_arith.h>
#include "arith.h"
#include "sizes.h"
#include "type.h"
@ -25,12 +25,12 @@
#include "Lpars.h"
#include "field.h"
#include "mes.h"
#include "noRoption.h"
#include "assert.h"
extern char *symbol2str();
extern char options[];
arithbalance(e1p, oper, e2p) /* RM 6.6 */
arithbalance(e1p, oper, e2p) /* 3.1.2.5 */
register struct expr **e1p, **e2p;
int oper;
{
@ -38,15 +38,17 @@ arithbalance(e1p, oper, e2p) /* RM 6.6 */
of the arithmetic operator oper.
*/
register int t1, t2, u1, u2;
int shifting = (oper == LEFT || oper == RIGHT
|| oper == LEFTAB || oper == RIGHTAB);
t1 = any2arith(e1p, oper);
t2 = any2arith(e2p, oper);
/* Now t1 and t2 are either INT, LONG, FLOAT, DOUBLE, or LNGDBL */
#ifndef NOFLOAT
/* If any operand has the type long double, the other operand
is converted to long double.
*/
/* ??? t1 == LNGDBL, t2 == DOUBLE */
if (t1 == LNGDBL) {
if (t2 != LNGDBL)
int2float(e2p, lngdbl_type);
@ -82,7 +84,6 @@ arithbalance(e1p, oper, e2p) /* RM 6.6 */
int2float(e1p, float_type);
return;
}
#endif NOFLOAT
/* Now they are INT or LONG */
u1 = (*e1p)->ex_type->tp_unsigned;
@ -93,7 +94,8 @@ arithbalance(e1p, oper, e2p) /* RM 6.6 */
*/
if (t1 == LONG && u1 && (t2 != LONG || !u2))
t2 = int2int(e2p, ulong_type);
else if (t2 == LONG && u2 && (t1 != LONG || !u1))
else if (t2 == LONG && u2 && (t1 != LONG || !u1)
&& !shifting) /* ??? */
t1 = int2int(e1p, ulong_type);
/* If one operand has type long int and the other has type unsigned
@ -104,7 +106,7 @@ arithbalance(e1p, oper, e2p) /* RM 6.6 */
*/
if (t1 == LONG && t2 == INT && u2)
t2 = int2int(e2p, (int_size<long_size)? long_type : ulong_type);
else if (t2 == LONG && t1 == INT && u1)
else if (t2 == LONG && t1 == INT && u1 && !shifting) /* ??? */
t1 = int2int(e1p, (int_size<long_size)? long_type : ulong_type);
if (int_size > long_size) /* sanity check */
crash("size of int exceeds size of long");
@ -115,17 +117,17 @@ arithbalance(e1p, oper, e2p) /* RM 6.6 */
if (t1 == LONG && t2 != LONG)
t2 = int2int(e2p, long_type);
else
if (t2 == LONG && t1 != LONG)
if (t2 == LONG && t1 != LONG && !shifting) /* ??? */
t1 = int2int(e1p, long_type);
/* If either operand has type unsigned int, the other operand
is converted to unsigned int.
Otherwise, both operands have type int.
*/
if (u1 && !u2)
if (u1 && !u2 && !shifting)
t2 = int2int(e2p, (t1 == LONG) ? ulong_type : uint_type);
else
if (!u1 && u2)
if (!u1 && u2 && !shifting)
t1 = int2int(e1p, (t2 == LONG) ? ulong_type : uint_type);
}
@ -168,15 +170,15 @@ ch76pointer(expp, oper, tp)
ch7cast(expp, oper, tp);
}
else
if ( is_integral_type(exp->ex_type)
#ifndef NOROPTION
&&
( !options['R'] /* we don't care */ ||
(oper == EQUAL || oper == NOTEQUAL || oper == ':')
)
#endif NOROPTION
) /* ch 7.7 */
if (is_integral_type(exp->ex_type)) {
if ((oper != EQUAL && oper != NOTEQUAL && oper != ':')
|| !(is_cp_cst(exp) && exp->VL_VALUE == 0)) {
expr_error(exp,"%s on %s and pointer",
symbol2str(oper),
symbol2str(exp->ex_type->tp_fund));
}
ch7cast(expp, CAST, tp);
}
else {
expr_error(exp, "%s on %s and pointer",
symbol2str(oper),
@ -191,8 +193,8 @@ any2arith(expp, oper)
register struct expr **expp;
register int oper;
{
/* Turns any expression into int_type, long_type or
double_type.
/* Turns any expression into int_type, long_type,
float_type, double_type or lngdbl_type.
*/
int fund;
@ -200,41 +202,32 @@ any2arith(expp, oper)
case CHAR:
case SHORT:
case GENERIC:
int2int(expp,
(*expp)->ex_type->tp_unsigned ? uint_type : int_type);
ASSERT((*expp)->ex_type->tp_size <= int_type->tp_size);
if ((*expp)->ex_type->tp_unsigned
&& (*expp)->ex_type->tp_size == int_type->tp_size) {
int2int(expp, uint_type);
} else {
int2int(expp, int_type);
}
break;
case INT:
case LONG:
break;
case ENUM:
/* test the admissibility of the operator */
if ( is_test_op(oper) || oper == '=' || oper == PARCOMMA ||
oper == ',' || oper == ':'
) {
/* allowed by K & R */
}
else
#ifndef NOROPTION
if (!options['R']) {
/* allowed by us */
}
else
expr_warning(*expp, "%s on enum", symbol2str(oper));
#endif NOROPTION
#ifndef LINT
int2int(expp, int_type);
#endif LINT
break;
#ifndef NOFLOAT
case FLOAT:
/*
/* only when it is a parameter and the default promotion should
occur. Hence this code is moved to any2parameter().
float2float(expp, double_type);
break;
*/
case DOUBLE:
case LNGDBL:
break;
#endif NOFLOAT
#ifndef NOBITFIELD
case FIELD:
field2arith(expp);
@ -322,7 +315,6 @@ int2int(expp, tp)
return exp->ex_type->tp_fund;
}
#ifndef NOFLOAT
int2float(expp, tp)
register struct expr **expp;
struct type *tp;
@ -331,18 +323,20 @@ int2float(expp, tp)
converted to the floating type tp.
*/
register struct expr *exp = *expp;
char buf[32];
fp_used = 1;
if (is_cp_cst(exp)) {
*expp = new_expr();
**expp = *exp;
sprint(buf+1, "%ld", (long)(exp->VL_VALUE));
buf[0] = '-';
exp = *expp;
/* sprint(buf+1, "%ld", (long)(exp->VL_VALUE));
/* buf[0] = '-';
*/
exp = *expp; /* ??? */
exp->ex_type = tp;
exp->ex_class = Float;
exp->FL_VALUE = Salloc(buf, (unsigned)strlen(buf)+2) + 1;
exp->FL_VALUE = 0 /* Salloc(buf, (unsigned)strlen(buf)+1) */ ;
flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH));
exp->FL_DATLAB = 0;
}
else *expp = arith2arith(tp, INT2FLOAT, *expp);
@ -376,7 +370,6 @@ float2float(expp, tp)
else
*expp = arith2arith(tp, FLOAT2FLOAT, *expp);
}
#endif NOFLOAT
array2pointer(exp)
register struct expr *exp;
@ -384,8 +377,9 @@ array2pointer(exp)
/* The expression, which must be an array, is converted
to a pointer.
*/
exp->ex_type = construct_type(POINTER, exp->ex_type->tp_up, 0,
(arith)0, NO_PROTO);
exp->ex_type = construct_type(POINTER, exp->ex_type->tp_up
, /* exp->ex_type->tp_typequal */ 0
, (arith)0, NO_PROTO);
}
function2pointer(exp)
@ -454,10 +448,9 @@ opnd2logical(expp, oper)
case LONG:
case ENUM:
case POINTER:
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
#endif NOFLOAT
case LNGDBL:
break;
default:
expr_error(*expp, "%s operand to %s",
@ -503,13 +496,11 @@ any2opnd(expp, oper)
{
if (!*expp)
return;
switch ((*expp)->ex_type->tp_fund) { /* RM 7.1 */
switch ((*expp)->ex_type->tp_fund) {
case CHAR:
case SHORT:
case ENUM:
#ifndef NOFLOAT
case FLOAT:
#endif NOFLOAT
/* case FLOAT: /* not necessary anymore */
any2arith(expp, oper);
break;
case ARRAY:
@ -533,10 +524,8 @@ any2parameter(expp)
/* To handle default argument promotions
*/
any2opnd(expp, '(');
#ifndef NOFLOAT
if ((*expp)->ex_type->tp_fund == FLOAT)
float2float(expp, double_type);
#endif NOFLOAT
}
#ifndef NOBITFIELD
@ -569,19 +558,13 @@ field2arith(expp)
}
#endif NOBITFIELD
#ifndef NOFLOAT
/* switch_sign_fp() negates the given floating constant expression
The lexical analyser has reserved an extra byte of space in front
of the string containing the representation of the floating
constant. This byte contains the '-' character and we have to
take care of the first byte the fl_value pointer points to.
*/
/* switch_sign_fp() negates the given floating constant expression,
* and frees the string representing the old value.
*/
switch_sign_fp(expr)
register struct expr *expr;
{
if (*(expr->FL_VALUE) == '-')
++(expr->FL_VALUE);
else
--(expr->FL_VALUE);
flt_umin(&(expr->FL_ARITH));
if (expr->FL_VALUE) free(expr->FL_VALUE);
expr->FL_VALUE = 0;
}
#endif NOFLOAT

View file

@ -26,3 +26,7 @@
#define arith long /* dummy */
#endif SPECIAL_ARITHMETICS
#define arith_size (sizeof(arith))
#define arith_sign ((arith) 1 << (arith_size * 8 - 1))
#define max_arith (~arith_sign)

View file

@ -3,13 +3,13 @@
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
/* S E M A N T I C A N A L Y S I S -- C H A P T E R 7 RM */
/* S E M A N T I C A N A L Y S I S -- C H A P T E R 3.3 */
#include "lint.h"
#include "nofloat.h"
#include "debug.h"
#include "nobitfield.h"
#include "idf.h"
#include <flt_arith.h>
#include "arith.h"
#include "proto.h"
#include "type.h"
@ -23,6 +23,7 @@
extern char options[];
extern char *symbol2str();
extern struct type *qualifier_type();
/* Most expression-handling routines have a pointer to a
(struct type *) as first parameter. The object under the pointer
@ -52,15 +53,15 @@ ch7sel(expp, oper, idf)
"char c; c->selector"
*/
switch (tp->tp_fund) {
case POINTER:
break;
case INT:
case LONG:
/* Allowed by RM 14.1 */
/* An error is given in idf2sdef() */
ch7cast(expp, CAST, pa_type);
sd = idf2sdef(idf, tp);
tp = sd->sd_stype;
break;
case POINTER:
break;
default:
expr_error(exp, "-> applied to %s",
symbol2str(tp->tp_fund));
@ -69,7 +70,9 @@ ch7sel(expp, oper, idf)
return;
}
}
} /* oper == ARROW */
} else { /* oper == '.' */
/* nothing */
}
exp = *expp;
switch (tp->tp_fund) {
case POINTER: /* for int *p; p->next = ... */
@ -105,8 +108,10 @@ ch7sel(expp, oper, idf)
*/
exp->VL_VALUE += sd->sd_offset;
exp->ex_type = sd->sd_type;
if (exp->ex_type == error_type)
exp->ex_lvalue = exp->ex_type->tp_fund != ARRAY;
if (exp->ex_type == error_type) {
exp->ex_flags |= EX_ERROR;
}
}
else
if (exp->ex_class == Oper) {
@ -116,13 +121,17 @@ ch7sel(expp, oper, idf)
ASSERT(is_cp_cst(op->op_right));
op->op_right->VL_VALUE += sd->sd_offset;
exp->ex_type = sd->sd_type;
if (exp->ex_type == error_type)
exp->ex_lvalue = exp->ex_type->tp_fund != ARRAY;
if (exp->ex_type == error_type) {
exp->ex_flags |= EX_ERROR;
}
}
else {
exp = new_oper(sd->sd_type, exp, '.',
intexpr(sd->sd_offset, INT));
exp->ex_lvalue = exp->OP_LEFT->ex_lvalue;
exp->ex_lvalue = sd->sd_type->tp_fund != ARRAY;
if (!exp->OP_LEFT->ex_lvalue)
exp->ex_flags |= EX_ILVALUE;
}
}
}
@ -130,11 +139,15 @@ ch7sel(expp, oper, idf)
exp = new_oper(sd->sd_type,
exp, oper, intexpr(sd->sd_offset, INT));
exp->ex_lvalue = (sd->sd_type->tp_fund != ARRAY);
exp->ex_flags &= ~EX_ILVALUE;
}
if (sd->sd_type->tp_typequal & TQ_CONST)
exp->ex_flags |= EX_READONLY;
if (sd->sd_type->tp_typequal & TQ_VOLATILE)
exp->ex_flags |= EX_VOLATILE;
if (oper == '.' && exp->ex_flags & EX_READONLY) {
exp->ex_type = qualifier_type(exp->ex_type, TQ_CONST);
}
*expp = exp;
}
@ -191,15 +204,6 @@ ch7cast(expp, oper, tp)
int i = is_integral_type(tp);
if (oldi && i) {
if ( oper != CAST
&& ( tp->tp_fund == ENUM
|| oldtp->tp_fund == ENUM
)
) {
expr_warning(*expp,
"dubious %s on enum",
symbol2str(oper));
}
#ifdef LINT
if (oper == CAST)
(*expp)->ex_type = tp;
@ -209,13 +213,8 @@ ch7cast(expp, oper, tp)
int2int(expp, tp);
#endif LINT
}
#ifndef NOFLOAT
else
if (oldi && !i) {
if (oldtp->tp_fund == ENUM && oper != CAST)
expr_warning(*expp,
"conversion of enum to %s\n",
symbol2str(tp->tp_fund));
#ifdef LINT
if (oper == CAST)
(*expp)->ex_type = tp;
@ -247,12 +246,6 @@ ch7cast(expp, oper, tp)
float2float(expp, tp);
#endif LINT
}
#else NOFLOAT
else {
crash("(ch7cast) floats not implemented\n");
/*NOTREACHED*/
}
#endif NOFLOAT
}
else
if (oldtp->tp_fund == POINTER && tp->tp_fund == POINTER) {
@ -330,6 +323,9 @@ ch7cast(expp, oper, tp)
);
(*expp)->ex_type = tp; /* brute force */
}
if (oper == CAST) {
(*expp)->ex_flags |= EX_ILVALUE;
}
}
/* Determine whether two types are equal.
@ -348,9 +344,10 @@ equal_type(tp, otp)
return 0;
if (tp->tp_align != otp->tp_align)
return 0;
if (tp->tp_fund != ARRAY)
if (tp->tp_fund != ARRAY /* && tp->tp_fund != STRUCT */ ) { /* UNION ??? */
if (tp->tp_size != otp->tp_size)
return 0;
}
switch (tp->tp_fund) {
@ -359,9 +356,13 @@ equal_type(tp, otp)
each parameter in the composite parameter type list
is the composite type of the corresponding paramaters.
*/
if (tp->tp_proto && otp->tp_proto &&
!equal_proto(tp->tp_proto, otp->tp_proto))
return 0;
if (tp->tp_proto && otp->tp_proto) {
if (!equal_proto(tp->tp_proto, otp->tp_proto))
return 0;
} else if (tp->tp_proto || otp->tp_proto) {
if (!legal_mixture(tp, otp))
return 0;
}
return equal_type(tp->tp_up, otp->tp_up);
case ARRAY:
@ -374,6 +375,16 @@ equal_type(tp, otp)
return equal_type(tp->tp_up, otp->tp_up);
case POINTER:
if (equal_type(tp->tp_up, otp->tp_up)) {
if (otp->tp_up->tp_typequal & TQ_CONST) {
if (!(tp->tp_up->tp_typequal & TQ_CONST)) {
strict("illegal use of pointer to const object");
}
}
return 1;
}
else return 0;
case FIELD:
return equal_type(tp->tp_up, otp->tp_up);
@ -387,6 +398,78 @@ equal_type(tp, otp)
}
}
check_pseudoproto(pl, opl)
register struct proto *pl, *opl;
{
int retval = 1;
if (pl->pl_flag & PL_ELLIPSIS) {
error("illegal ellipsis terminator");
return 2;
}
while (pl && opl) {
if (!equal_type(pl->pl_type, opl->pl_type)) {
if (!(pl->pl_flag & PL_ERRGIVEN)
&& !(opl->pl_flag & PL_ERRGIVEN))
error("incorrect type for parameter %s of definition",
opl->pl_idf->id_text);
pl->pl_flag |= PL_ERRGIVEN;
opl->pl_flag |= PL_ERRGIVEN;
retval = 2;
}
pl = pl->next;
opl = opl->next;
}
if (pl || opl) {
error("incorrect number of parameters");
retval = 2;
}
return retval;
}
legal_mixture(tp, otp)
struct type *tp, *otp;
{
register struct proto *pl = tp->tp_proto, *opl = otp->tp_proto;
int retval = 1;
struct proto *prot;
int fund;
ASSERT( (pl != 0) ^ (opl != 0));
if (pl) {
prot = pl;
} else {
prot = opl;
}
if (!opl && otp->tp_pseudoproto) {
return check_pseudoproto(tp->tp_proto, otp->tp_pseudoproto);
}
if (prot->pl_flag & PL_ELLIPSIS) {
if (!(prot->pl_flag & PL_ERRGIVEN)) {
if (pl)
error("illegal ellipsis terminator");
else error("ellipsis terminator in previous (prototype) declaration");
}
prot->pl_flag |= PL_ERRGIVEN;
prot = prot->next;
return 2;
}
while (prot) {
/* if (!(prot->pl_flag & PL_ELLIPSIS)) {} */
fund = prot->pl_type->tp_fund;
if (fund == CHAR || fund == SHORT || fund == FLOAT) {
if (!(prot->pl_flag & PL_ERRGIVEN))
error("illegal %s parameter in %sdeclaration",
symbol2str(fund), (opl ? "previous (prototype) " : "" ));
prot->pl_flag |= PL_ERRGIVEN;
retval = 2;
}
prot = prot->next;
}
return retval;
}
equal_proto(pl, opl)
register struct proto *pl, *opl;
{
@ -397,15 +480,35 @@ equal_proto(pl, opl)
(a function prototype), the composite type is a function
prototype with parameter type list.
*/
if (pl == 0 || opl == 0) return 0;
while ( pl && opl) {
if (pl->pl_flag != opl->pl_flag)
if ((pl->pl_flag & ~PL_ERRGIVEN) != (opl->pl_flag & ~PL_ERRGIVEN))
return 0;
if (!equal_type(pl->pl_type, opl->pl_type))
if (!equal_type(pl->pl_type, opl->pl_type))
return 0;
return equal_proto(pl->next, opl->next);
pl = pl->next;
opl = opl->next;
}
return !(pl || opl);
}
recurconst(tp)
struct type *tp;
{
register struct sdef *sdf;
ASSERT(tp);
if (!tp) return 0;
if (tp->tp_typequal & TQ_CONST) return 1;
sdf = tp->tp_sdef;
while (sdf) {
if (recurconst(sdf->sd_type))
return 1;
sdf = sdf->sd_sdef;
}
return 0;
}
ch7asgn(expp, oper, expr)
@ -431,13 +534,17 @@ ch7asgn(expp, oper, expr)
struct type *tp;
/* We expect an lvalue */
if (!exp->ex_lvalue) {
expr_error(exp, "no lvalue in lhs of %s", symbol2str(oper));
exp->ex_depth = 99; /* no direct store/load at EVAL() */
/* what is 99 ??? DG */
if (!exp->ex_lvalue) {
expr_error(exp, "no lvalue in operand of %s", symbol2str(oper));
} else if (exp->ex_flags & EX_ILVALUE) {
strict("incorrect lvalue in operand of %s", symbol2str(oper));
} else if (exp->ex_flags & EX_READONLY) {
expr_error(exp, "operand of %s is read-only", symbol2str(oper));
} else if (fund == STRUCT || fund == UNION) {
if (recurconst(exp->ex_type))
expr_error(expr,"operand of %s contains a const-qualified member",
symbol2str(oper));
}
if (exp->ex_flags & EX_READONLY)
strict("lhs of assignment is read-only");
/* Preserve volatile markers across the tree.
This is questionable, depending on the way the optimizer
@ -520,11 +627,9 @@ is_arith_type(tp)
case INT:
case LONG:
case ENUM:
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
#endif NOFLOAT
return 1;
#ifndef NOBITFIELD
case FIELD:

View file

@ -3,20 +3,19 @@
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
/* SEMANTIC ANALYSIS (CHAPTER 7RM) -- BINARY OPERATORS */
/* SEMANTIC ANALYSIS (CHAPTER 3.3) -- BINARY OPERATORS */
#include "botch_free.h"
#include <alloc.h>
#include "nofloat.h"
#include "lint.h"
#include "idf.h"
#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "struct.h"
#include "label.h"
#include "expr.h"
#include "Lpars.h"
#include "noRoption.h"
extern char options[];
extern char *symbol2str();
@ -40,8 +39,8 @@ ch7bin(expp, oper, expr)
any2opnd(expp, oper);
any2opnd(&expr, oper);
switch (oper) {
case '[': /* RM 7.1 */
/* RM 14.3 states that indexing follows the commutative laws */
case '[': /* 3.3.2.1 */
/* indexing follows the commutative laws */
switch ((*expp)->ex_type->tp_fund) {
case POINTER:
case ARRAY:
@ -67,14 +66,10 @@ ch7bin(expp, oper, expr)
ch7mon('*', expp);
break;
case '(': /* RM 7.1 */
case '(': /* 3.3.2.2 */
if ( (*expp)->ex_type->tp_fund == POINTER &&
(*expp)->ex_type->tp_up->tp_fund == FUNCTION
) {
#ifndef NOROPTION
if (options['R'])
warning("function pointer called");
#endif NOROPTION
ch7mon('*', expp);
}
if ((*expp)->ex_type->tp_fund != FUNCTION) {
@ -82,6 +77,8 @@ ch7bin(expp, oper, expr)
symbol2str((*expp)->ex_type->tp_fund));
/* leave the expression; it may still serve */
free_expression(expr); /* there go the parameters */
*expp = new_oper(error_type,
*expp, '(', (struct expr *)0);
}
else
*expp = new_oper((*expp)->ex_type->tp_up,
@ -89,7 +86,7 @@ ch7bin(expp, oper, expr)
(*expp)->ex_flags |= EX_SIDEEFFECTS;
break;
case PARCOMMA: /* RM 7.1 */
case PARCOMMA: /* 3.3.2.2 */
if ((*expp)->ex_type->tp_fund == FUNCTION)
function2pointer(*expp);
*expp = new_oper(expr->ex_type, *expp, PARCOMMA, expr);
@ -102,7 +99,7 @@ ch7bin(expp, oper, expr)
case ORAB:
opnd2integral(expp, oper);
opnd2integral(&expr, oper);
/* Fall through */
/* fallthrough */
case '/':
case DIVAB:
case TIMESAB:
@ -115,7 +112,7 @@ ch7bin(expp, oper, expr)
case '|':
opnd2integral(expp, oper);
opnd2integral(&expr, oper);
/* Fall through */
/* fallthrough */
case '*':
arithbalance(expp, oper, &expr);
commutative_binop(expp, oper, expr);
@ -127,7 +124,7 @@ ch7bin(expp, oper, expr)
expr = *expp;
*expp = etmp;
}
/*FALLTHROUGH*/
/* fallthrough */
case PLUSAB:
case POSTINCR:
case PLUSPLUS:
@ -226,8 +223,9 @@ ch7bin(expp, oper, expr)
ch7bin(expp, ',', expr);
}
}
else
else {
*expp = new_oper(int_type, *expp, oper, expr);
}
(*expp)->ex_flags |= EX_LOGICAL;
break;
@ -310,6 +308,8 @@ mk_binop(expp, oper, expr, commutative)
if (is_cp_cst(expr) && is_cp_cst(ex))
cstbin(expp, oper, expr);
else if (is_fp_cst(expr) && is_fp_cst(ex))
fltcstbin(expp, oper, expr);
else {
*expp = (commutative && expr->ex_depth >= ex->ex_depth) ?
new_oper(ex->ex_type, expr, oper, ex) :
@ -320,16 +320,18 @@ mk_binop(expp, oper, expr, commutative)
pointer_arithmetic(expp1, oper, expp2)
register struct expr **expp1, **expp2;
{
int typ;
/* prepares the integral expression expp2 in order to
apply it to the pointer expression expp1
*/
#ifndef NOFLOAT
if (any2arith(expp2, oper) == DOUBLE) {
if ((typ = any2arith(expp2, oper)) == FLOAT
|| typ == DOUBLE
|| typ == LNGDBL) {
expr_error(*expp2,
"illegal combination of float and pointer");
"illegal combination of %s and pointer",
symbol2str(typ));
erroneous2int(expp2);
}
#endif NOFLOAT
ch7bin( expp2, '*',
intexpr(size_of_type((*expp1)->ex_type->tp_up, "object"),
pa_type->tp_fund)

View file

@ -3,13 +3,13 @@
* See the copyright notice in the ACK home directory, in the file "Copyright".
*/
/* $Header$ */
/* SEMANTIC ANALYSIS (CHAPTER 7RM) -- MONADIC OPERATORS */
/* SEMANTIC ANALYSIS (CHAPTER 3.3) -- MONADIC OPERATORS */
#include "botch_free.h"
#include <alloc.h>
#include "nofloat.h"
#include "nobitfield.h"
#include "Lpars.h"
#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "label.h"
@ -18,7 +18,7 @@
#include "def.h"
extern char options[];
extern long full_mask[/*MAXSIZE*/]; /* cstoper.c */
extern arith full_mask[/*MAXSIZE*/]; /* cstoper.c */
char *symbol2str();
ch7mon(oper, expp)
@ -29,16 +29,20 @@ ch7mon(oper, expp)
register struct expr *expr;
switch (oper) {
case '*': /* RM 7.2 */
case '*': /* 3.3.3.2 */
/* no FIELD type allowed */
if ((*expp)->ex_type->tp_fund == ARRAY)
array2pointer(*expp);
if ((*expp)->ex_type->tp_fund != POINTER) {
expr_error(*expp,
"* applied to non-pointer (%s)",
symbol2str((*expp)->ex_type->tp_fund));
}
else {
if ((*expp)->ex_type->tp_fund != POINTER) {
if ((*expp)->ex_type->tp_fund != FUNCTION) {
expr_error(*expp,
"* applied to non-pointer (%s)",
symbol2str((*expp)->ex_type->tp_fund));
} else {
warning("superfluous use of * on function");
/* ignore indirection (yegh) */
}
} else {
expr = *expp;
if (expr->ex_lvalue == 0 && expr->ex_class != String)
/* dereference in administration only */
@ -54,16 +58,17 @@ ch7mon(oper, expp)
(*expp)->ex_flags |= EX_READONLY;
if ((*expp)->ex_type->tp_typequal & TQ_VOLATILE)
(*expp)->ex_flags |= EX_VOLATILE;
(*expp)->ex_flags &= ~EX_ILVALUE;
}
break;
case '&':
if ((*expp)->ex_type->tp_fund == ARRAY) {
warning("& before array ignored");
expr_warning(*expp, "& before array ignored");
array2pointer(*expp);
}
else
if ((*expp)->ex_type->tp_fund == FUNCTION) {
warning("& before function ignored");
expr_warning(*expp, "& before function ignored");
function2pointer(*expp);
}
else
@ -74,6 +79,8 @@ ch7mon(oper, expp)
#endif NOBITFIELD
if (!(*expp)->ex_lvalue)
expr_error(*expp, "& applied to non-lvalue");
else if ((*expp)->ex_flags & EX_ILVALUE)
expr_error(*expp, "& applied to illegal lvalue");
else {
/* assume that enums are already filtered out */
if (ISNAME(*expp)) {
@ -90,28 +97,25 @@ ch7mon(oper, expp)
break; /* break case '&' */
}
}
(*expp)->ex_type = pointer_to((*expp)->ex_type);
(*expp)->ex_type = pointer_to((*expp)->ex_type,
(*expp)->ex_type->tp_typequal);
(*expp)->ex_lvalue = 0;
(*expp)->ex_flags &= ~EX_READONLY;
}
break;
case '~':
#ifndef NOFLOAT
{
int fund = (*expp)->ex_type->tp_fund;
if (fund == FLOAT || fund == DOUBLE) {
expr_error(
*expp,
"~ not allowed on %s operands",
symbol2str(fund)
);
if (fund == FLOAT || fund == DOUBLE || fund == LNGDBL) {
expr_error( *expp,
"~ not allowed on %s operands",
symbol2str(fund));
erroneous2int(expp);
break;
}
/* FALLTHROUGH */
}
#endif NOFLOAT
case '-':
any2arith(expp, oper);
if (is_cp_cst(*expp)) {
@ -124,11 +128,9 @@ ch7mon(oper, expp)
);
}
else
#ifndef NOFLOAT
if (is_fp_cst(*expp))
switch_sign_fp(*expp);
else
#endif NOFLOAT
*expp = new_oper((*expp)->ex_type,
NILEXPR, oper, *expp);
break;
@ -152,7 +154,7 @@ ch7mon(oper, expp)
break;
case SIZEOF:
if (ISNAME(*expp) && (*expp)->VL_IDF->id_def->df_formal_array)
warning("sizeof formal array %s is sizeof pointer!",
expr_warning(*expp, "sizeof formal array %s is sizeof pointer!",
(*expp)->VL_IDF->id_text);
expr = intexpr((*expp)->ex_class == String ?
(arith)((*expp)->SG_LEN) :

View file

@ -10,14 +10,15 @@
%iSTGARB
STSKIP:\r \t\013\f
STNL:\n
STCOMP:-!&+<=>|
STSIMP:%()*,/:;?[]^{}~
STCOMP:-!&+<=>|*%/^
STSIMP:(),:;?[]{}~
STCHAR:'
STIDF:a-zA-KM-Z_
STIDF:a-zA-KM-Z_\003
STELL:L
STNUM:.0-9
STSTR:"
STEOI:\200
STMSPEC:\004
%T/* character classes */
%T#include "class.h"
%Tchar tkclass[] = {
@ -44,7 +45,7 @@ STEOI:\200
% ISHEX
%
%C
1:a-fA-F
1:0-9a-fA-F
%Tchar ishex[] = {
%p
%T};
@ -57,14 +58,6 @@ STEOI:\200
%p
%T};
%
% ISSUF
%
%C
1:lLuU
%Tchar issuf[] = {
%p
%T};
%
% ISWSP
%
%C

View file

@ -13,7 +13,7 @@
#define class(ch) (tkclass[ch])
/* Being the start of a token is, fortunately, a mutual exclusive
property, so, although there are less than 16 classes they can be
property, so, as there are less than 16 classes they can be
packed in 4 bits.
*/
@ -28,6 +28,10 @@
#define STSTR 8 /* the starter of a string */
#define STNUM 9 /* the starter of a numeric constant */
#define STEOI 10 /* End-Of-Information mark */
#define STMSPEC 11 /* special class for token expansion */
#define NOEXPM '\003' /* don't expand the next macro identifier */
#define TOKSEP '\004' /* the token separator */
/* But occurring inside a token is not, so we need 1 bit for each
class. This is implemented as a collection of tables to speed up

View file

@ -11,6 +11,7 @@
#include <alloc.h>
#include "dataflow.h"
#include "use_tmp.h"
#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "idf.h"
@ -28,7 +29,6 @@
#include "specials.h"
#include "atw.h"
#include "assert.h"
#include "noRoption.h"
#include "file_info.h"
#ifdef LINT
#include "l_lint.h"
@ -37,9 +37,8 @@
label lab_count = 1;
label datlab_count = 1;
#ifndef NOFLOAT
int fp_used;
#endif NOFLOAT
extern arith NewLocal(); /* util.c */
/* global function info */
char *func_name;
@ -109,12 +108,10 @@ end_code()
/* end_code() performs the actions to be taken when closing
the output stream.
*/
#ifndef NOFLOAT
if (fp_used) {
/* floating point used */
C_ms_flt();
}
#endif NOFLOAT
def_strings(str_list);
str_list = 0;
C_ms_src((int)(LineNumber - 2), FileName);
@ -204,6 +201,7 @@ begin_proc(ds, idf) /* to be called when entering a procedure */
DfaStartFunction(name);
#endif DATAFLOW
/* set global function info */
func_name = name;
if (def->df_type->tp_fund != FUNCTION) {
@ -368,32 +366,31 @@ code_declaration(idf, expr, lvl, sc)
If there is a storage class indication (EXTERN/STATIC),
code_declaration() will generate an exa or ina.
The sc is the actual storage class, as given in the
declaration. This is to allow:
extern int a;
int a = 5;
while at the same time forbidding
extern int a = 5;
declaration.
*/
register struct def *def = idf->id_def;
register arith size = def->df_type->tp_size;
int fund = def->df_type->tp_fund;
int def_sc = def->df_sc;
if (def_sc == TYPEDEF) /* no code for typedefs */
return;
if (sc == EXTERN && expr && !is_anon_idf(idf))
error("%s is extern; cannot initialize", idf->id_text);
#ifndef PREPEND_SCOPES
if (def->df_type->tp_fund == FUNCTION) {
if (fund == FUNCTION) {
code_scope(idf->id_text, def);
}
#endif PREPEND_SCOPES
if (lvl == L_GLOBAL) { /* global variable */
/* is this an allocating declaration? */
if ( (sc == 0 || sc == STATIC)
&& def->df_type->tp_fund != FUNCTION
&& fund != FUNCTION
&& size >= 0
)
def->df_alloc = ALLOC_SEEN;
if (expr && def_sc == STATIC && sc == EXTERN) {
warning("%s redeclared extern", idf->id_text);
def->df_sc = EXTERN;
}
if (expr) { /* code only if initialized */
#ifndef PREPEND_SCOPES
code_scope(idf->id_text, def);
@ -407,7 +404,7 @@ code_declaration(idf, expr, lvl, sc)
/* STATIC, EXTERN, GLOBAL, IMPLICIT, AUTO or REGISTER */
switch (def_sc) {
case STATIC:
if (def->df_type->tp_fund == FUNCTION) {
if (fund == FUNCTION) {
/* should produce "inp $function" ??? */
break;
}
@ -426,6 +423,9 @@ code_declaration(idf, expr, lvl, sc)
}
break;
case EXTERN:
if (expr && !is_anon_idf(idf) && level != L_GLOBAL)
error("cannot initialize extern in block"
, idf->id_text);
case GLOBAL:
case IMPLICIT:
/* we are sure there is no expression */
@ -437,6 +437,11 @@ code_declaration(idf, expr, lvl, sc)
case REGISTER:
if (expr)
loc_init(expr, idf);
else if ((fund == ARRAY)
&& (def->df_type->tp_size == (arith)-1)) {
error("size for local %s unknown"
, idf->id_text);
}
break;
default:
crash("bad local storage class");
@ -455,27 +460,44 @@ loc_init(expr, id)
*/
register struct expr *e = expr;
register struct type *tp = id->id_def->df_type;
static arith tmpoffset = 0;
static arith unknownsize = 0;
ASSERT(id->id_def->df_sc != STATIC);
switch (tp->tp_fund) {
case ARRAY:
if (id->id_def->df_type->tp_size == (arith) -1)
unknownsize = 1;
case STRUCT:
case UNION:
error("automatic %s cannot be initialized in declaration",
symbol2str(tp->tp_fund));
free_expression(e);
if (!tmpoffset) { /* first time for this variable */
tmpoffset = id->id_def->df_address;
id->id_def->df_address = data_label();
C_df_dlb((label)id->id_def->df_address);
} else {
/* generate a 'loi, sti' sequence. The peephole
* optimizer will optimize this into a 'blm'
* whenever possible.
*/
C_lae_dlb((label)id->id_def->df_address, (arith)0);
C_loi(tp->tp_size);
if (unknownsize) {
/* tmpoffset += tp->tp_size; */
unknownsize = 0;
tmpoffset = NewLocal(tp->tp_size
, tp->tp_align
, regtype(tp)
, id->id_def->df_sc);
}
C_lal(tmpoffset);
C_sti(tp->tp_size);
id->id_def->df_address = tmpoffset;
tmpoffset = 0;
}
return;
}
if (ISCOMMA(e)) { /* embraced: int i = {12}; */
#ifndef NOROPTION
if (options['R']) {
if (ISCOMMA(e->OP_LEFT)) /* int i = {{1}} */
expr_error(e, "extra braces not allowed");
else
if (e->OP_RIGHT != 0) /* int i = {1 , 2} */
expr_error(e, "too many initializers");
}
#endif NOROPTION
while (e) {
loc_init(e->OP_LEFT, id);
e = e->OP_RIGHT;
@ -510,25 +532,17 @@ bss(idf)
#ifndef PREPEND_SCOPES
code_scope(idf->id_text, idf->id_def);
#endif PREPEND_SCOPES
/* Since bss() is only called if df_alloc is non-zero, and
since df_alloc is only non-zero if size >= 0, we have:
*/
/* but we already gave a warning at the declaration of the
array. Besides, the message given here does not apply to
voids
if (options['R'] && size == 0)
warning("actual array of size 0");
*/
C_df_dnam(idf->id_text);
C_bss_cst(ATW(size), (arith)0, 1);
}
formal_cvt(df)
formal_cvt(hasproto,df)
int hasproto;
register struct def *df;
{
/* formal_cvt() converts a formal parameter of type char or
short from int to that type.
short from int to that type. It also converts a formal
parameter of type float from a double to a float.
*/
register struct type *tp = df->df_type;
@ -540,6 +554,12 @@ formal_cvt(df)
No, you can't do this on the stack! (CJ)
*/
StoreLocal(df->df_address, tp->tp_size);
} else if (tp->tp_size != double_size
&& tp->tp_fund == FLOAT
&& !hasproto) {
LoadLocal(df->df_address, double_size);
conversion(double_type, float_type);
StoreLocal(df->df_address, tp->tp_size);
}
}

View file

@ -8,7 +8,6 @@
#include "lint.h"
#ifndef LINT
#include "nofloat.h"
#include <em.h>
#include "arith.h"
#include "type.h"
@ -17,9 +16,7 @@
#define T_SIGNED 1
#define T_UNSIGNED 2
#ifndef NOFLOAT
#define T_FLOATING 3
#endif NOFLOAT
/* conversion() generates the EM code for a conversion between
the types char, short, int, long, float, double and pointer.
@ -52,9 +49,7 @@ conversion(from_type, to_type)
C_cii();
break;
case T_UNSIGNED:
#ifndef NOFLOAT
case T_FLOATING:
#endif NOOFLOAT
if ((int)from_size < (int)word_size) {
C_loc(from_size);
C_loc(word_size);
@ -79,14 +74,11 @@ conversion(from_type, to_type)
case T_UNSIGNED:
C_cuu();
break;
#ifndef NOFLOAT
case T_FLOATING:
C_cuf();
break;
#endif NOFLOAT
}
break;
#ifndef NOFLOAT
case T_FLOATING:
C_loc(from_size);
C_loc(to_size);
@ -102,17 +94,14 @@ conversion(from_type, to_type)
break;
}
break;
#endif NOFLOAT
default:
crash("(conversion) illegal type conversion");
/*NOTREACHED*/
}
if ((int)(to_type->tp_size) < (int)word_size
#ifndef NOFLOAT
&& to_cnvtype != T_FLOATING
#endif NOFLOAT
) {
extern long full_mask[];
extern arith full_mask[];
if (to_cnvtype == T_SIGNED) {
C_loc(to_type->tp_size);
@ -142,12 +131,10 @@ convtype(tp)
case LONG:
case ENUM:
return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
return T_FLOATING;
#endif NOFLOAT
case POINTER:
return T_UNSIGNED;
}

View file

@ -7,6 +7,7 @@
#include "target_sizes.h"
#include "idf.h"
#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "label.h"
@ -15,11 +16,10 @@
#include "Lpars.h"
#include "assert.h"
long mach_long_sign; /* sign bit of the machine long */
int mach_long_size; /* size of long on this machine == sizeof(long) */
long full_mask[MAXSIZE];/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
arith full_mask[MAXSIZE];/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
arith max_int; /* maximum integer on target machine */
arith max_unsigned; /* maximum unsigned on target machine */
extern int ResultKnown;
cstbin(expp, oper, expr)
register struct expr **expp, *expr;
@ -39,35 +39,38 @@ cstbin(expp, oper, expr)
break;
case '/':
if (o2 == 0) {
expr_error(expr, "division by 0");
if (!ResultKnown)
expr_error(expr, "division by 0");
else
expr_warning(expr, "division by 0");
break;
}
if (uns) {
/* this is more of a problem than you might
think on C compilers which do not have
unsigned long.
unsigned arith (== long (probably)).
*/
if (o2 & mach_long_sign) {/* o2 > max_long */
if (o2 & arith_sign) {/* o2 > max_arith */
o1 = ! (o1 >= 0 || o1 < o2);
/* this is the unsigned test
o1 < o2 for o2 > max_long
o1 < o2 for o2 > max_arith
*/
}
else { /* o2 <= max_long */
long half, bit, hdiv, hrem, rem;
else { /* o2 <= max_arith */
arith half, bit, hdiv, hrem, rem;
half = (o1 >> 1) & ~mach_long_sign;
half = (o1 >> 1) & ~arith_sign;
bit = o1 & 01;
/* now o1 == 2 * half + bit
and half <= max_long
and bit <= max_long
and half <= max_arith
and bit <= max_arith
*/
hdiv = half / o2;
hrem = half % o2;
rem = 2 * hrem + bit;
o1 = 2 * hdiv + (rem < 0 || rem >= o2);
/* that is the unsigned compare
rem >= o2 for o2 <= max_long
rem >= o2 for o2 <= max_arith
*/
}
}
@ -76,24 +79,27 @@ cstbin(expp, oper, expr)
break;
case '%':
if (o2 == 0) {
expr_error(expr, "modulo by 0");
if (!ResultKnown)
expr_error(expr, "modulo by 0");
else
expr_warning(expr, "modulo by 0");
break;
}
if (uns) {
if (o2 & mach_long_sign) {/* o2 > max_long */
if (o2 & arith_sign) {/* o2 > max_arith */
o1 = (o1 >= 0 || o1 < o2) ? o1 : o1 - o2;
/* this is the unsigned test
o1 < o2 for o2 > max_long
o1 < o2 for o2 > max_arith
*/
}
else { /* o2 <= max_long */
long half, bit, hrem, rem;
else { /* o2 <= max_arith */
arith half, bit, hrem, rem;
half = (o1 >> 1) & ~mach_long_sign;
half = (o1 >> 1) & ~arith_sign;
bit = o1 & 01;
/* now o1 == 2 * half + bit
and half <= max_long
and bit <= max_long
and half <= max_arith
and bit <= max_arith
*/
hrem = half % o2;
rem = 2 * hrem + bit;
@ -117,7 +123,7 @@ cstbin(expp, oper, expr)
break;
if (uns) {
o1 >>= 1;
o1 &= ~mach_long_sign;
o1 &= ~arith_sign;
o1 >>= (o2-1);
}
else
@ -133,9 +139,9 @@ cstbin(expp, oper, expr)
/* Fall through */
case '>':
if (uns) {
o1 = (o1 & mach_long_sign ?
(o2 & mach_long_sign ? o1 > o2 : 1) :
(o2 & mach_long_sign ? 0 : o1 > o2)
o1 = (o1 & arith_sign ?
(o2 & arith_sign ? o1 > o2 : 1) :
(o2 & arith_sign ? 0 : o1 > o2)
);
}
else
@ -151,9 +157,9 @@ cstbin(expp, oper, expr)
/* Fall through */
case GREATEREQ:
if (uns) {
o1 = (o1 & mach_long_sign ?
(o2 & mach_long_sign ? o1 >= o2 : 1) :
(o2 & mach_long_sign ? 0 : o1 >= o2)
o1 = (o1 & arith_sign ?
(o2 & arith_sign ? o1 >= o2 : 1) :
(o2 & arith_sign ? 0 : o1 >= o2)
);
}
else
@ -201,16 +207,18 @@ cut_size(expr)
}
if (uns) {
if (o1 & ~full_mask[size])
if (!ResultKnown)
expr_warning(expr,
"overflow in unsigned constant expression");
o1 &= full_mask[size];
}
else {
int nbits = (int) (mach_long_size - size) * 8;
long remainder = o1 & ~full_mask[size];
int nbits = (int) (arith_size - size) * 8;
arith remainder = o1 & ~full_mask[size];
if (remainder != 0 && remainder != ~full_mask[size])
expr_warning(expr, "overflow in constant expression");
if (!ResultKnown)
expr_warning(expr,"overflow in constant expression");
o1 <<= nbits; /* ??? */
o1 >>= nbits;
}
@ -228,10 +236,8 @@ init_cst()
fatal("array full_mask too small for this machine");
full_mask[i] = bt;
}
mach_long_size = i;
mach_long_sign = 1L << (mach_long_size * 8 - 1);
if ((int)long_size < mach_long_size)
fatal("sizeof (long) insufficient on this machine");
if ((int)long_size > arith_size)
fatal("sizeof (arith) insufficient on this machine");
max_int = full_mask[(int)int_size] & ~(1L << ((int)int_size * 8 - 1));
max_unsigned = full_mask[(int)int_size];
}

View file

@ -10,6 +10,7 @@
#include <alloc.h>
#include "nobitfield.h"
#include "debug.h"
#include <flt_arith.h>
#include "arith.h"
#include "LLlex.h"
#include "label.h"
@ -32,7 +33,7 @@
#endif LINT
}
/* 8 */
/* 3.5 */
declaration
{struct decspecs Ds;}
:
@ -49,12 +50,12 @@ declaration
empty case has already be dealt with in `external_definition'.
This means that something like:
unsigned extern int short xx;
is perfectly good C.
is perfectly legal C.
On top of that, multiple occurrences of storage_class_specifiers,
unsigned_specifiers and size_specifiers are errors, but a second
type_specifier should end the decl_specifiers and be treated as
the name to be declared (see the thin ice in RM11.1).
the name to be declared.
Such a language is not easily expressed in a grammar; enumeration
of the permutations is unattractive. We solve the problem by
having a regular grammar for the "soft" items, handling the single
@ -86,7 +87,7 @@ decl_specifiers /* non-empty */ (register struct decspecs *ds;)
{do_decspecs(ds);}
;
/* 8.1 */
/* 3.5.1 & 3.5.2 (partially) & 3.5.3 (partially) */
other_specifier(register struct decspecs *ds;)
:
[ AUTO | STATIC | EXTERN | TYPEDEF | REGISTER ]
@ -125,7 +126,7 @@ other_specifier(register struct decspecs *ds;)
}
;
/* 8.2 */
/* 3.5.2 */
type_specifier(struct type **tpp;)
/* Used in struct/union declarations and in casts; only the
type is relevant.
@ -161,7 +162,7 @@ single_type_specifier(register struct decspecs *ds;):
enum_specifier(&ds->ds_type)
;
/* 8.3 */
/* 3.5 */
init_declarator_list(struct decspecs *ds;):
init_declarator(ds)
[ ',' init_declarator(ds) ]*
@ -179,6 +180,7 @@ init_declarator(register struct decspecs *ds;)
declarator(&Dc)
{
reject_params(&Dc);
def_proto(&Dc);
declare_idf(ds, &Dc, level);
#ifdef LINT
lint_declare_idf(Dc.dc_idf, ds->ds_sc);
@ -198,18 +200,26 @@ init_declarator(register struct decspecs *ds;)
}
;
/* 8.6: initializer */
/* 3.5.7: initializer */
initializer(struct idf *idf; int sc;)
{
struct expr *expr = (struct expr *) 0;
int globalflag = level == L_GLOBAL ||
(level >= L_LOCAL && sc == STATIC);
int fund = idf->id_def->df_type->tp_fund;
int autoagg = (level >= L_LOCAL
&& sc != STATIC
&& ( fund == STRUCT
|| fund == UNION
|| fund == ARRAY));
int globalflag = level == L_GLOBAL
|| (level >= L_LOCAL && sc == STATIC);
}
:
{ if (idf->id_def->df_type->tp_fund == FUNCTION) {
error("illegal initialization of function");
idf->id_def->df_type->tp_fund = ERRONEOUS;
}
if (level == L_FORMAL2)
warning("illegal initialization of formal parameter (ignored)");
}
'='
{
@ -220,8 +230,12 @@ initializer(struct idf *idf; int sc;)
struct expr ex;
code_declaration(idf, &ex, level, sc);
}
else if (autoagg)
loc_init((struct expr *) 0, idf);
}
initial_value(globalflag ? &(idf->id_def->df_type) : (struct type **)0,
initial_value((globalflag || autoagg) ?
&(idf->id_def->df_type)
: (struct type **)0,
&expr)
{ if (! globalflag) {
if (idf->id_def->df_type->tp_fund == FUNCTION) {
@ -234,7 +248,9 @@ initializer(struct idf *idf; int sc;)
#ifdef LINT
change_state(idf, SET);
#endif LINT
code_declaration(idf, expr, level, sc);
if (autoagg)
loc_init((struct expr *) 0, idf);
else code_declaration(idf, expr, level, sc);
}
init_idf(idf);
}
@ -247,6 +263,7 @@ initializer(struct idf *idf; int sc;)
we just include the (formal) parameter list in the declarator
description list dc.
*/
/* 3.5.4 */
declarator(register struct declarator *dc;)
{ struct formal *fm = NO_PARAMS;
struct proto *pl = NO_PROTO;
@ -303,7 +320,7 @@ arrayer(arith *sizep;)
formal_list (struct formal **fmp;)
:
formal(fmp) [ ',' formal(fmp) ]*
formal(fmp) [ %persistent ',' formal(fmp) ]*
;
formal(struct formal **fmp;)
@ -404,7 +421,14 @@ struct_or_union_specifier(register struct type **tpp;)
(idf->id_struct->tg_busy)--;
}
|
{apply_struct(fund, idf, tpp);}
{
/* a ';' means an empty declaration (probably)
* this means that we have to declare a new
* structure. (yegh)
*/
if (DOT == ';') declare_struct(fund, idf, tpp);
else apply_struct(fund, idf, tpp);
}
empty
]
]
@ -543,12 +567,13 @@ parameter_type_list(struct proto **plp;)
{ register struct proto *new = new_proto();
new->next = *plp;
new->pl_flag = ELLIPSIS;
new->pl_flag = PL_ELLIPSIS;
*plp = new;
}
]?
{ if (level == L_PROTO)
{ check_for_void(*plp);
if (level == L_PROTO)
level = save_level;
else level++;
}
@ -558,6 +583,7 @@ parameter_decl_list(struct proto **plp;)
:
parameter_decl(plp)
[ %while (AHEAD != ELLIPSIS)
%persistent
',' parameter_decl(plp)
]*
;
@ -615,11 +641,11 @@ parameter_declarator(register struct declarator *dc;)
parameter_type_list(&pl)
|
formal_list(&fm)
|
empty
]
]?
')'
{add_decl_unary(dc, FUNCTION, 0, (arith)0, fm, pl);}
{ add_decl_unary(dc, FUNCTION, 0, (arith)0, fm, pl);
reject_params(dc);
}
|
arrayer(&count)
{add_decl_unary(dc, ARRAY, 0, count, NO_PARAMS, NO_PROTO);}
@ -631,7 +657,8 @@ parameter_declarator(register struct declarator *dc;)
primary_parameter_declarator(register struct declarator *dc;)
:
[%if (AHEAD == ')' || first_of_parameter_type_list(AHEAD))
[%if (AHEAD == ')' || first_of_parameter_type_list(AHEAD)
&& (AHEAD != IDENTIFIER))
empty
|
identifier(&dc->dc_idf)
@ -645,7 +672,6 @@ pointer(int *qual;)
'*' type_qualifier_list(qual)
;
/* Type qualifiers may come in three flavours:
volatile, const, const volatile.
These all have different semantic properties:
@ -663,12 +689,12 @@ pointer(int *qual;)
prior knowledge of the implementation, but may
not be used as a l-value.
*/
/* 3.5.4 */
type_qualifier_list(int *qual;)
:
[
[ VOLATILE | CONST ]
{ *qual = (DOT == VOLATILE) ? TQ_VOLATILE : TQ_CONST; }
[
[ VOLATILE | CONST ]
{ if (DOT == VOLATILE) {
@ -690,9 +716,5 @@ type_qualifier_list(int *qual;)
]
;
empty:
;
/* 8.8 */
/* included in the IDENTIFIER/TYPE_IDENTIFIER mechanism */

View file

@ -7,6 +7,7 @@
#include "botch_free.h"
#include <alloc.h>
#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "proto.h"

View file

@ -5,7 +5,6 @@
/* $Header$ */
/* D E C L A R A T I O N S P E C I F I E R C H E C K I N G */
#include "nofloat.h"
#include "assert.h"
#include "Lpars.h"
#include "decspecs.h"
@ -13,7 +12,6 @@
#include "type.h"
#include "level.h"
#include "def.h"
#include "noRoption.h"
extern char options[];
extern int level;
@ -70,7 +68,7 @@ do_decspecs(ds)
type and will have to be postponed to declare_idf.
*/
/* some adjustments as described in RM 8.2 */
/* some adjustments as described in 3.5.2. */
if (tp == 0) {
ds->ds_notypegiven = 1;
tp = int_type;
@ -86,38 +84,24 @@ do_decspecs(ds)
if (tp == int_type)
tp = long_type;
else
#ifndef NOFLOAT
if (tp == double_type)
tp = lngdbl_type;
else
#endif NOFLOAT
error("long with illegal type");
break;
}
if (ds->ds_unsigned == UNSIGNED) {
switch (tp->tp_fund) {
case CHAR:
#ifndef NOROPTION
if (options['R'])
warning("unsigned char not allowed");
#endif
tp = uchar_type;
break;
case SHORT:
#ifndef NOROPTION
if (options['R'])
warning("unsigned short not allowed");
#endif
tp = ushort_type;
break;
case INT:
tp = uint_type;
break;
case LONG:
#ifndef NOROPTION
if (options['R'])
warning("unsigned long not allowed");
#endif
tp = ulong_type;
break;
default:
@ -128,7 +112,7 @@ do_decspecs(ds)
if (ds->ds_unsigned == SIGNED) {
switch (tp->tp_fund) {
case CHAR:
tp = char_type;
tp = schar_type;
break;
case SHORT:
tp = short_type;
@ -172,8 +156,13 @@ qualifier_type(tp, typequal)
dtp->tp_typequal = typequal;
dtp->tp_size = tp->tp_size;
switch (fund) {
case POINTER:
case ARRAY:
if (typequal) {
tp->tp_up = qualifier_type(tp->tp_up, typequal);
dtp->tp_typequal = typequal = 0;
}
/* fallthrough */
case POINTER:
case FUNCTION:
case STRUCT:
case UNION:

View file

@ -34,20 +34,28 @@ char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
int nestlevel = -1;
struct idf *
GetIdentifier()
GetIdentifier(skiponerr)
int skiponerr; /* skip the rest of the line on error */
{
/* returns a pointer to the descriptor of the identifier that is
read from the input stream. A null-pointer is returned if
the input does not contain an identifier.
read from the input stream. When the input doe not contain
an identifier, the rest of the line is skipped and a
null-pointer is returned.
The substitution of macros is disabled.
*/
int tmp = UnknownIdIsZero;
int tok;
struct token tk;
ReplaceMacros = 0;
UnknownIdIsZero = ReplaceMacros = 0;
tok = GetToken(&tk);
ReplaceMacros = 1;
return tok == IDENTIFIER ? tk.tk_idf : (struct idf *)0;
UnknownIdIsZero = tmp;
if (tok != IDENTIFIER) {
if (skiponerr && tok != EOI) SkipToNewLine(0);
return (struct idf *)0;
}
return tk.tk_idf;
}
/* domacro() is the control line interpreter. The '#' has already
@ -61,9 +69,13 @@ GetIdentifier()
domacro()
{
struct token tk; /* the token itself */
int toknum;
EoiForNewline = 1;
switch(GetToken(&tk)) { /* select control line action */
ReplaceMacros = 0;
toknum = GetToken(&tk);
ReplaceMacros = 1;
switch(toknum) { /* select control line action */
case IDENTIFIER: /* is it a macro keyword? */
switch (tk.tk_idf->id_resmac) {
case K_DEFINE: /* "define" */
@ -95,7 +107,7 @@ domacro()
the arguments.
*/
if (GetToken(&tk) != INTEGER) {
lexerror("#line without linenumber");
error("bad #line syntax");
SkipToNewLine(0);
}
else
@ -128,8 +140,8 @@ domacro()
EoiForNewline = 0;
}
skip_block()
skip_block(to_endif)
int to_endif;
{
/* skip_block() skips the input from
1) a false #if, #ifdef, #ifndef or #elif until the
@ -142,6 +154,7 @@ skip_block()
register int ch;
register int skiplevel = nestlevel; /* current nesting level */
struct token tk;
int toknum;
NoUnstack++;
for (;;) {
@ -153,10 +166,14 @@ skip_block()
NoUnstack--;
return;
}
UnGetChar();
SkipToNewLine(0);
continue;
}
if (GetToken(&tk) != IDENTIFIER) {
ReplaceMacros = 0;
toknum = GetToken(&tk);
ReplaceMacros = 1;
if (toknum != IDENTIFIER) {
SkipToNewLine(0);
continue;
}
@ -166,13 +183,19 @@ skip_block()
on the same level.
*/
switch(tk.tk_idf->id_resmac) {
default:
SkipToNewLine(0);
break;
case K_IF:
case K_IFDEF:
case K_IFNDEF:
push_if();
SkipToNewLine(0);
break;
case K_ELIF:
if (nestlevel == skiplevel) {
if (ifstack[nestlevel])
lexerror("#elif after #else");
if (!to_endif && nestlevel == skiplevel) {
nestlevel--;
push_if();
if (ifexpr()) {
@ -180,15 +203,19 @@ skip_block()
return;
}
}
else SkipToNewLine(0); /* otherwise done in ifexpr() */
break;
case K_ELSE:
if (ifstack[nestlevel])
lexerror("#else after #else");
++(ifstack[nestlevel]);
if (nestlevel == skiplevel) {
if (!to_endif && nestlevel == skiplevel) {
if (SkipToNewLine(1))
strict("garbage following #endif");
strict("garbage following #else");
NoUnstack--;
return;
}
else SkipToNewLine(0);
break;
case K_ENDIF:
ASSERT(nestlevel > nestlow);
@ -199,6 +226,7 @@ skip_block()
NoUnstack--;
return;
}
else SkipToNewLine(0);
nestlevel--;
break;
}
@ -241,7 +269,7 @@ do_include()
if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
filenm = tk.tk_bts;
else {
lexerror("bad include syntax");
error("bad include syntax");
filenm = (char *)0;
}
AccFileSpecifier = 0;
@ -249,7 +277,7 @@ do_include()
inctable[0] = WorkingDir;
if (filenm) {
if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
fatal("cannot open include file \"%s\"", filenm);
error("cannot open include file \"%s\"", filenm);
}
else {
WorkingDir = getwdir(result);
@ -275,9 +303,8 @@ do_define()
char *get_text();
/* read the #defined macro's name */
if (!(id = GetIdentifier())) {
lexerror("#define: illegal macro name");
SkipToNewLine(0);
if (!(id = GetIdentifier(1))) {
lexerror("illegal #define line");
return;
}
/* there is a formal parameter list if the identifier is
@ -297,7 +324,8 @@ do_define()
if (class(ch) == STNL) {
/* Treat `#define something' as `#define something ""'
*/
repl_text = "";
repl_text = Malloc(1);
*repl_text = '\0';
length = 0;
}
else {
@ -318,35 +346,38 @@ push_if()
do_elif()
{
if (nestlevel <= nestlow || (ifstack[nestlevel])) {
if (nestlevel <= nestlow) {
lexerror("#elif without corresponding #if");
SkipToNewLine(0);
}
else { /* restart at this level as if a #if is detected. */
else { /* restart at this level as if a #if is detected. */
if (ifstack[nestlevel]) {
lexerror("#elif after #else");
SkipToNewLine(0);
}
nestlevel--;
push_if();
skip_block();
skip_block(1);
}
}
do_else()
{
struct token tok;
if (SkipToNewLine(1))
strict("garbage following #else");
if (nestlevel <= nestlow || (ifstack[nestlevel]))
if (nestlevel <= nestlow)
lexerror("#else without corresponding #if");
else { /* mark this level as else-d */
if (ifstack[nestlevel]) {
lexerror("#else after #else");
}
++(ifstack[nestlevel]);
skip_block();
skip_block(1);
}
}
do_endif()
{
struct token tok;
if (SkipToNewLine(1))
strict("garbage following #endif");
if (nestlevel <= nestlow) {
@ -359,7 +390,7 @@ do_if()
{
push_if();
if (!ifexpr()) /* a false #if/#elif expression */
skip_block();
skip_block(0);
}
do_ifdef(how)
@ -369,15 +400,15 @@ do_ifdef(how)
/* how == 1 : ifdef; how == 0 : ifndef
*/
push_if();
if (!(id = GetIdentifier()))
if (!(id = GetIdentifier(1)))
lexerror("illegal #ifdef construction");
/* The next test is a shorthand for:
(how && !id->id_macro) || (!how && id->id_macro)
*/
if (how ^ (id && id->id_macro != 0))
skip_block();
else
skip_block(0);
else if (id)
SkipToNewLine(0);
}
@ -386,15 +417,20 @@ do_undef()
register struct idf *id;
/* Forget a macro definition. */
if (id = GetIdentifier()) {
if (id = GetIdentifier(1)) {
if (id->id_macro) { /* forget the macro */
free_macro(id->id_macro);
id->id_macro = (struct macro *) 0;
if (id->id_macro->mc_flag & NOUNDEF) {
lexerror("it is not allowed to undef %s", id->id_text);
} else {
free(id->id_text);
free_macro(id->id_macro);
id->id_macro = (struct macro *) 0;
}
} /* else: don't complain */
SkipToNewLine(0);
}
else
lexerror("illegal #undef construction");
SkipToNewLine(0);
}
do_error()
@ -488,15 +524,17 @@ macro_def(id, text, nformals, length, flags)
/* macro_def() puts the contents and information of a macro
definition into a structure and stores it into the symbol
table entry belonging to the name of the macro.
A warning is given if the definition overwrites another.
An error is given if there was already a definition
*/
if (newdef) { /* is there a redefinition? */
if (macroeq(newdef->mc_text, text))
return;
lexwarning("redefine \"%s\"", id->id_text);
if (newdef->mc_flag & NOUNDEF) {
lexerror("it is not allowed to redefine %s", id->id_text);
} else if (!macroeq(newdef->mc_text, text))
lexerror("illegal redefine of \"%s\"", id->id_text);
free(text);
return;
}
else
id->id_macro = newdef = new_macro();
id->id_macro = newdef = new_macro();
newdef->mc_text = text; /* replacement text */
newdef->mc_nps = nformals; /* nr of formals */
newdef->mc_length = length; /* length of repl. text */
@ -553,14 +591,14 @@ get_text(formals, length)
register int delim = c;
do {
/* being careful, as ever */
if (pos+3 >= text_size)
text = Srealloc(text,
text_size += RTEXTSIZE);
text[pos++] = c;
if (c == '\\')
text[pos++] = GetChar();
c = GetChar();
/* being careful, as ever */
if (pos+3 >= text_size)
text = Srealloc(text,
(unsigned) (text_size += RTEXTSIZE));
text[pos++] = c;
if (c == '\\')
text[pos++] = GetChar();
c = GetChar();
} while (c != delim && c != EOI && class(c) != STNL);
text[pos++] = c;
c = GetChar();
@ -569,7 +607,8 @@ get_text(formals, length)
if (c == '/') {
c = GetChar();
if (pos+1 >= text_size)
text = Srealloc(text, text_size += RTEXTSIZE);
text = Srealloc(text,
(unsigned) (text_size += RTEXTSIZE));
if (c == '*') {
skipcomment();
text[pos++] = ' ';
@ -593,25 +632,27 @@ get_text(formals, length)
} while (in_idf(c));
id_buf[--id_size] = '\0';
if (n = find_name(id_buf, formals)) {
/* construct the formal parameter mark */
if (pos+1 >= text_size)
text = Srealloc(text,
text_size += RTEXTSIZE);
text[pos++] = FORMALP | (char) n;
/* construct the formal parameter mark */
if (pos+1 >= text_size)
text = Srealloc(text,
(unsigned) (text_size += RTEXTSIZE));
text[pos++] = FORMALP | (char) n;
}
else {
register char *ptr = &id_buf[0];
register char *ptr = &id_buf[0];
while (pos + id_size >= text_size)
text = Srealloc(text,
text_size += RTEXTSIZE);
while (text[pos++] = *ptr++) ;
pos--;
while (pos + id_size >= text_size)
text = Srealloc(text,
(unsigned) (text_size += RTEXTSIZE));
while (text[pos++] = *ptr++)
/* EMPTY */ ;
pos--;
}
}
else {
if (pos+1 >= text_size)
text = Srealloc(text, text_size += RTEXTSIZE);
text = Srealloc(text,
(unsigned) (text_size += RTEXTSIZE));
text[pos++] = c;
c = GetChar();
}

View file

@ -8,9 +8,10 @@
#include "debug.h"
#ifdef DEBUG
#include "nofloat.h"
#include <alloc.h>
#include "nopp.h"
#include "nobitfield.h"
#include <flt_arith.h>
#include "arith.h"
#include "stack.h"
#include "idf.h"
@ -252,8 +253,8 @@ dump_proto(pl)
newline();
while (pl) {
print("%d: %s", argcnt++,
pl->pl_flag == FORMAL ?
(pl->pl_flag == VOID ? "void" : "formal")
pl->pl_flag & PL_FORMAL ?
(pl->pl_flag & PL_VOID ? "void" : "formal")
: "ellipsis");
newline();
if (type = pl->pl_type){
@ -442,9 +443,7 @@ p1_expr(lvl, expr)
expr->ex_depth,
expr->ex_class == Value ? "Value" :
expr->ex_class == String ? "String" :
#ifndef NOFLOAT
expr->ex_class == Float ? "Float" :
#endif NOFLOAT
expr->ex_class == Oper ? "Oper" :
expr->ex_class == Type ? "Type" : "UNKNOWN CLASS"
);
@ -479,11 +478,13 @@ p1_expr(lvl, expr)
);
break;
}
#ifndef NOFLOAT
case Float:
if (!expr->FL_VALUE) {
expr->FL_VALUE = Malloc(FLT_STRLEN);
flt_flt2str(&(expr->FL_ARITH), expr->FL_VALUE, FLT_STRLEN);
}
print("%s\n", expr->FL_VALUE);
break;
#endif NOFLOAT
case Oper:
o = &expr->ex_object.ex_oper;
print("\n");

View file

@ -15,6 +15,7 @@
#include "debug.h"
#include "tokenname.h"
#include <flt_arith.h>
#include "arith.h"
#include "label.h"
#include "expr.h"
@ -32,6 +33,7 @@
#define ERROR 3
#define CRASH 4
#define FATAL 5
#define DO_DEBUG 6
int err_occurred = 0;
@ -93,11 +95,28 @@ strict(va_alist)
va_start(ap);
{
_error(STRICT, FileName, LineNumber, ap);
_error(STRICT, dot.tk_file, dot.tk_line, ap);
}
va_end(ap);
}
#ifdef DEBUG
/*VARARGS*/
debug(va_alist)
va_dcl
{
va_list ap;
va_start(ap);
{
_error(DO_DEBUG, dot.tk_file, dot.tk_line, ap);
/* _error(DO_DEBUG, NILEXPR, ap);
*/
}
va_end(ap);
}
#endif DEBUG
/*VARARGS*/
warning(va_alist)
va_dcl
@ -106,7 +125,9 @@ warning(va_alist)
va_start(ap);
{
_error(WARNING, NILEXPR, ap);
_error(WARNING, dot.tk_file, dot.tk_line, ap);
/* _error(WARNING, NILEXPR, ap);
*/
}
va_end(ap);
}
@ -310,12 +331,18 @@ _error(class, fn, ln, ap)
case FATAL:
remark = "fatal error --";
break;
#ifdef DEBUG
case DO_DEBUG:
remark = "(debug)";
break;
#endif DEBUG
default:
/*NOTREACHED*/;
}
#ifndef LINT
if (ln == last_ln && fn && last_fn && strcmp(fn, last_fn) == 0) {
if (class != DO_DEBUG) /* ??? DEBUG */
if (ln == last_ln && fn && last_fn && strcmp(fn, last_fn) == 0) {
/* we've seen this place before */
e_seen++;
if (e_seen == MAXERR_LINE)

View file

@ -8,12 +8,13 @@
#include "lint.h"
#ifndef LINT
#include "nofloat.h"
#include <em.h>
#include <em_reg.h>
#include <alloc.h>
#include "debug.h"
#include "nobitfield.h"
#include "dataflow.h"
#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "idf.h"
@ -69,7 +70,7 @@ EVAL(expr, val, code, true_label, false_label)
int val, code;
label true_label, false_label;
{
register int gencode = (code == TRUE);
register int gencode = (code == TRUE && expr->ex_type->tp_size > 0);
switch (expr->ex_class) {
case Value: /* just a simple value */
@ -82,18 +83,20 @@ EVAL(expr, val, code, true_label, false_label)
C_lae_dlb(expr->VL_LBL, expr->VL_VALUE);
}
break;
#ifndef NOFLOAT
case Float: /* a floating constant */
if (gencode) {
label datlab = data_label();
if (!expr->FL_VALUE) {
expr->FL_VALUE = Malloc(FLT_STRLEN);
flt_flt2str(&(expr->FL_ARITH), expr->FL_VALUE, FLT_STRLEN);
}
C_df_dlb(datlab);
C_rom_fcon(expr->FL_VALUE, expr->ex_type->tp_size);
C_lae_dlb(datlab, (arith)0);
C_loi(expr->ex_type->tp_size);
}
break;
#endif NOFLOAT
case Oper: /* compound expression */
{
int oper = expr->OP_OPER;
@ -107,6 +110,7 @@ EVAL(expr, val, code, true_label, false_label)
}
if (tp->tp_fund == VOID)
gencode = 0;
switch (oper) {
case '+':
/* We have the following possibilities :
@ -130,13 +134,11 @@ EVAL(expr, val, code, true_label, false_label)
C_cuu();
C_ads(pointer_size);
break;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
C_adf(tp->tp_size);
break;
#endif NOFLOAT
default:
crash("bad type +");
}
@ -152,13 +154,11 @@ EVAL(expr, val, code, true_label, false_label)
case POINTER:
C_ngi(tp->tp_size);
break;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
C_ngf(tp->tp_size);
break;
#endif NOFLOAT
default:
CRASH();
}
@ -192,13 +192,11 @@ EVAL(expr, val, code, true_label, false_label)
C_ads(pointer_size);
}
break;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
C_sbf(tp->tp_size);
break;
#endif NOFLOAT
default:
crash("bad type -");
}
@ -223,14 +221,12 @@ EVAL(expr, val, code, true_label, false_label)
else
C_mli(tp->tp_size);
break;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
/*C_mlf(double_size);*/
C_mlf(tp->tp_size);
break;
#endif NOFLOAT
default:
crash("bad type *");
}
@ -249,14 +245,12 @@ EVAL(expr, val, code, true_label, false_label)
else
C_dvi(tp->tp_size);
break;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
/*C_dvf(double_size);*/
C_dvf(tp->tp_size);
break;
#endif NOFLOAT
default:
crash("bad type /");
}
@ -309,13 +303,11 @@ EVAL(expr, val, code, true_label, false_label)
else
C_cmi(size);
break;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
C_cmf(size);
break;
#endif NOFLOAT
case POINTER:
C_cmp();
break;
@ -543,10 +535,6 @@ EVAL(expr, val, code, true_label, false_label)
ASSERT(is_cp_cst(right));
if (gencode) {
C_adp(right->VL_VALUE);
if (val == RVAL && expr->ex_lvalue == 0) {
load_block(expr->ex_type->tp_size,
expr->ex_type->tp_align);
}
}
break;
case ARROW:
@ -624,11 +612,9 @@ EVAL(expr, val, code, true_label, false_label)
true_label);
break;
case INT2INT:
#ifndef NOFLOAT
case INT2FLOAT:
case FLOAT2INT:
case FLOAT2FLOAT:
#endif NOFLOAT
EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
if (gencode)
conversion(right->ex_type, left->ex_type);
@ -640,9 +626,10 @@ EVAL(expr, val, code, true_label, false_label)
only its lvalue is evaluated, its rvalue is
loaded by the following statements:
*/
if (gencode && val == RVAL && expr->ex_lvalue == 1)
if (gencode && val == RVAL && expr->ex_lvalue == 1) {
load_block(expr->ex_type->tp_size,
expr->ex_type->tp_align);
}
break;
}
default:
@ -782,13 +769,12 @@ assop(type, oper)
break;
}
break;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
switch (oper) {
case PLUSAB:
case PLUSPLUS:
case PLUSPLUS: /* ??? etc... */
case POSTINCR:
C_adf(size);
break;
@ -805,7 +791,6 @@ assop(type, oper)
break;
}
break;
#endif NOFLOAT
case POINTER:
if (oper == MINAB || oper == MINMIN || oper == POSTDECR)
C_ngi(size);
@ -851,7 +836,11 @@ store_val(vl, tp)
register struct idf *id = vl->vl_data.vl_idf;
register struct def *df = id->id_def;
if (df->df_level == L_GLOBAL) {
/* if (df->df_level == L_GLOBAL) { /* } ??? re-examine */
if (df->df_sc == GLOBAL
|| df->df_sc == EXTERN
|| df->df_sc == STATIC
|| df->df_sc == IMPLICIT) {
if (inword)
C_ste_dnam(id->id_text, val);
else
@ -956,7 +945,11 @@ load_val(expr, rlval)
C_lpi(id->id_text);
}
else
if (df->df_level == L_GLOBAL) {
/* if (df->df_level == L_GLOBAL) { /* } ??? re-examine */
if ( df->df_sc == GLOBAL
|| df->df_sc == STATIC
|| df->df_sc == EXTERN
|| df->df_sc == IMPLICIT) {
if (rvalue) {
if (inword)
C_loe_dnam(id->id_text, val);
@ -974,7 +967,7 @@ load_val(expr, rlval)
}
}
else {
ASSERT(df->df_sc != STATIC);
/* ASSERT(df->df_sc != STATIC); */
if (rvalue) {
if (inword || indword)
LoadLocal(df->df_address + val, size);

View file

@ -6,10 +6,11 @@
/* EXPRESSION TREE HANDLING */
#include "lint.h"
#include "nofloat.h"
#include "assert.h"
#include "botch_free.h"
#include <alloc.h>
#include "idf.h"
#include <flt_arith.h>
#include "arith.h"
#include "def.h"
#include "type.h"
@ -21,10 +22,10 @@
#include "declar.h"
#include "sizes.h"
#include "level.h"
#include "noRoption.h"
extern char *symbol2str();
extern char options[];
extern int InSizeof;
int
rank_of(oper)
@ -96,7 +97,6 @@ rank_of(oper)
/*NOTREACHED*/
}
#ifndef NOROPTION
int
rank_of_expression(ex)
register struct expr *ex;
@ -112,15 +112,14 @@ check_conditional(expr, oper, pos_descr)
register struct expr *expr;
char *pos_descr;
{
/* Warn if restricted C is in effect and the expression expr,
which occurs at the position pos_descr, is not lighter than
the operator oper.
/* Since the grammar is LR and the parser is LL, this kludge
here checks if there was a syntax error caused by
the priorities in an expression.
*/
if (options['R'] && rank_of_expression(expr) >= rank_of(oper))
expr_warning(expr, "%s %s is ungrammatical",
if (rank_of_expression(expr) >= rank_of(oper))
expr_error(expr, "%s %s",
symbol2str(expr->OP_OPER), pos_descr);
}
#endif
dot2expr(expp)
struct expr **expp;
@ -140,11 +139,9 @@ dot2expr(expp)
case INTEGER:
int2expr(ex);
break;
#ifndef NOFLOAT
case FLOATING:
float2expr(ex);
break;
#endif NOFLOAT
default:
crash("bad conversion to expression");
/*NOTREACHED*/
@ -163,9 +160,12 @@ idf2expr(expr)
register struct def *def = idf->id_def;
if (def == 0) {
if (AHEAD == '(') /* function call, declare name IMPLICITly */
add_def(idf, IMPLICIT, funint_type, level); /* RM 13 */
else {
if (AHEAD == '(') {
/* function call, declare name IMPLICITly (3.3.2.2) */
warning("implicit declaration of function %s"
, idf->id_text);
add_def(idf, IMPLICIT, funint_type, level);
} else {
if (!is_anon_idf(idf))
error("%s undefined", idf->id_text);
/* declare idf anyway */
@ -180,11 +180,13 @@ idf2expr(expr)
}
else {
#ifndef LINT
def->df_used = 1;
if (!InSizeof)
def->df_used = 1;
#endif LINT
expr->ex_type = def->df_type;
if (expr->ex_type == error_type)
if (expr->ex_type == error_type) {
expr->ex_flags |= EX_ERROR;
}
}
expr->ex_lvalue =
( def->df_type->tp_fund == FUNCTION ||
@ -215,9 +217,9 @@ idf2expr(expr)
}
}
string2expr(expp, typ, str, len)
string2expr(expp, str, len)
register struct expr **expp;
int typ, len;
int len;
char *str;
{
/* The string in the argument is converted into an expression,
@ -229,9 +231,7 @@ string2expr(expp, typ, str, len)
ex->ex_file = dot.tk_file;
ex->ex_line = dot.tk_line;
ex->ex_type = string_type;
/*
ex->ex_type = qualifier_type(ex->ex_type, TQ_CONST);
*/
/* ex->ex_type = qualifier_type(ex->ex_type, TQ_CONST); */
ex->ex_flags |= EX_READONLY;
ex->ex_lvalue = 0;
ex->ex_class = String;
@ -249,7 +249,6 @@ int2expr(expr)
fill_int_expr(expr, dot.tk_ival, dot.tk_fund);
}
#ifndef NOFLOAT
float2expr(expr)
register struct expr *expr;
{
@ -274,9 +273,12 @@ float2expr(expr)
}
expr->ex_class = Float;
expr->FL_VALUE = dot.tk_fval;
flt_str2flt(expr->FL_VALUE, &(expr->FL_ARITH));
ASSERT(flt_status != FLT_NOFLT);
if (flt_status == FLT_OVFL)
expr_warning(expr,"internal floating point overflow");
expr->FL_DATLAB = 0;
}
#endif NOFLOAT
struct expr*
intexpr(ivalue, fund)
@ -287,7 +289,7 @@ intexpr(ivalue, fund)
the size indicated by fund.
*/
register struct expr *expr = new_expr();
expr->ex_file = dot.tk_file;
expr->ex_line = dot.tk_line;
fill_int_expr(expr, ivalue, fund);
@ -324,8 +326,8 @@ fill_int_expr(ex, ivalue, fund)
/* We cannot make a test like
ivalue <= max_unsigned
because, if
sizeof(long) == int_size
holds, max_unsigned may be a negative long in
sizeof(arith) == int_size
holds, max_unsigned may be a negative arith in
which case the comparison results in an unexpected
answer.
*/
@ -392,7 +394,8 @@ new_oper(tp, e1, oper, e2)
expr->ex_depth =
(e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + 1;
expr->ex_flags = (e1_flags | e2->ex_flags) & ~EX_PARENS;
expr->ex_flags = (e1_flags | e2->ex_flags)
& ~(EX_PARENS | EX_READONLY /* ??? | EX_VOLATILE */ );
}
op = &expr->ex_object.ex_oper;
op->op_type = tp;
@ -425,43 +428,24 @@ chk_cst_expr(expp)
the others in the various C compilers. I have tried some
hypotheses to unify them, but all have failed.
This routine will give a warning for those operators
not allowed by K&R, under the R-option only. The anomalies
are cast, logical operators and the expression comma.
Special problems (of which there is only one, sizeof in
Preprocessor #if) have to be dealt with locally
Note that according to K&R the negation ! is illegal in
constant expressions and is indeed rejected by the
Ritchie compiler.
*/
register struct expr *expr = *expp;
register int fund = expr->ex_type->tp_fund;
register int flags = expr->ex_flags;
int err = 0;
#ifdef DEBUG
print_expr("constant_expression", expr);
#endif DEBUG
if ( fund != CHAR && fund != SHORT && fund != INT &&
fund != ENUM && fund != LONG
)
expr_error(expr, "non-numerical constant expression"), err++;
else
if (!is_ld_cst(expr))
expr_error(expr, "expression is not constant"), err++;
#ifndef NOROPTION
if (options['R']) {
if (flags & EX_CAST)
expr_warning(expr, "cast in constant expression");
if (flags & EX_LOGICAL)
expr_warning(expr,
"logical operator in constant expression");
if (flags & EX_COMMA)
expr_warning(expr,
"expression comma in constant expression");
if ( fund != CHAR && fund != SHORT && fund != INT
&& fund != ENUM && fund != LONG) {
expr_error(expr, "non-numerical constant expression");
err++;
} else if (!is_ld_cst(expr)) {
expr_error(expr, "expression is not constant");
err++;
}
#endif NOROPTION
if (err)
erroneous2int(expp);
}
@ -501,7 +485,7 @@ is_ld_cst(expr)
int
is_cp_cst(expr)
register struct expr *expr;
struct expr *expr;
{
/* An expression is a `compile-time constant' if it is a
load-time constant, and the idf is not there.
@ -509,17 +493,31 @@ is_cp_cst(expr)
return is_ld_cst(expr) && expr->VL_CLASS == Const;
}
#ifndef NOFLOAT
int
is_fp_cst(expr)
register struct expr *expr;
struct expr *expr;
{
/* An expression is a `floating-point constant' if it consists
of the float only.
*/
return expr->ex_class == Float;
}
#endif NOFLOAT
int
is_zero_cst(expr)
register struct expr *expr;
{
flt_arith var;
switch(expr->ex_class) {
case Value:
return expr->VL_VALUE == 0;
case Float:
flt_arith2flt((arith) 0, &var);
return flt_cmp(&var, &(expr->FL_ARITH)) == 0;
}
/*NOTREACHED*/
}
free_expression(expr)
register struct expr *expr;
@ -527,6 +525,8 @@ free_expression(expr)
/* The expression expr is freed recursively.
*/
if (expr) {
if (expr->ex_class == Float && expr->FL_VALUE)
free(expr->FL_VALUE);
if (expr->ex_class == Oper) {
free_expression(expr->OP_LEFT);
free_expression(expr->OP_RIGHT);

View file

@ -9,8 +9,6 @@
a union of various goodies, we define them first; so be patient.
*/
#include "nofloat.h"
/* classes of value */
#define Const 1
#define Name 2
@ -31,12 +29,11 @@ struct string {
label sg_datlab; /* global data-label */
};
#ifndef NOFLOAT
struct floating {
char *fl_value; /* pointer to string repr. the fp const. */
flt_arith fl_arith; /* the value in high precision */
label fl_datlab; /* global data_label */
};
#endif NOFLOAT
struct oper {
struct type *op_type; /* resulting type of the operation */
@ -48,9 +45,7 @@ struct oper {
/* The following constants indicate the class of the expression: */
#define Value 0 /* it is a value known at load time */
#define String 1 /* it is a string constant */
#ifndef NOFLOAT
#define Float 2 /* it is a floating point constant */
#endif NOFLOAT
#define Oper 3 /* it is a run-time expression */
#define Type 4 /* only its type is relevant */
@ -66,9 +61,7 @@ struct expr {
union {
struct value ex_value;
struct string ex_string;
#ifndef NOFLOAT
struct floating ex_float;
#endif NOFLOAT
struct oper ex_oper;
} ex_object;
};
@ -82,10 +75,9 @@ struct expr {
#define SG_VALUE ex_object.ex_string.sg_value
#define SG_LEN ex_object.ex_string.sg_len
#define SG_DATLAB ex_object.ex_string.sg_datlab
#ifndef NOFLOAT
#define FL_VALUE ex_object.ex_float.fl_value
#define FL_ARITH ex_object.ex_float.fl_arith
#define FL_DATLAB ex_object.ex_float.fl_datlab
#endif NOFLOAT
#define OP_TYPE ex_object.ex_oper.op_type
#define OP_LEFT ex_object.ex_oper.op_left
#define OP_OPER ex_object.ex_oper.op_oper
@ -94,15 +86,16 @@ struct expr {
/* some bits for the ex_flag field, to keep track of various
interesting properties of an expression.
*/
#define EX_SIZEOF 0001 /* contains sizeof operator */
#define EX_CAST 0002 /* contains cast */
#define EX_LOGICAL 0004 /* contains logical operator */
#define EX_COMMA 0010 /* contains expression comma */
#define EX_PARENS 0020 /* the top level is parenthesized */
#define EX_SIDEEFFECTS 0040 /* expression has side effects */
#define EX_READONLY 0100 /* read only variabele */
#define EX_VOLATILE 0200 /* volatile variabele */
#define EX_ERROR 0400 /* the expression is wrong */
#define EX_SIZEOF 0x001 /* contains sizeof operator */
#define EX_CAST 0x002 /* contains cast */
#define EX_LOGICAL 0x004 /* contains logical operator */
#define EX_COMMA 0x008 /* contains expression comma */
#define EX_PARENS 0x010 /* the top level is parenthesized */
#define EX_SIDEEFFECTS 0x020 /* expression has side effects */
#define EX_READONLY 0x040 /* read only variabele */
#define EX_VOLATILE 0x080 /* volatile variabele */
#define EX_ILVALUE 0x100 /* an illegal lvalue e.g. f().x */
#define EX_ERROR 0x200 /* the expression is wrong */
#define NILEXPR ((struct expr *)0)

View file

@ -8,6 +8,7 @@
{
#include <alloc.h>
#include "lint.h"
#include <flt_arith.h>
#include "arith.h"
#include "LLlex.h"
#include "type.h"
@ -15,12 +16,19 @@
#include "label.h"
#include "expr.h"
#include "code.h"
#include "noRoption.h"
extern struct expr *intexpr();
int InSizeof = 0; /* inside a sizeof- expression */
int ResultKnown = 0; /* result of the expression is already known */
/* Since the grammar in the standard is not LL(n), it is modified so that
* it accepts basically the same grammar. Thsi means that there is no 1-1
* mapping from the grammar in the standard to the grammar given here.
* Such is life.
*/
}
/* 7.1 */
/* 3.3.1 */
primary(register struct expr **expp;) :
IDENTIFIER
{dot2expr(expp);}
@ -30,14 +38,14 @@ primary(register struct expr **expp;) :
string(expp)
|
'(' expression(expp) ')'
{(*expp)->ex_flags |= EX_PARENS;}
{ (*expp)->ex_flags |= EX_PARENS; }
;
/* Character string literals that are adjacent tokens
are concatenated into a single character string
literal.
*/
/* Character string literals that are adjacent tokens
* are concatenated into a single character string
* literal.
*/
string(register struct expr **expp;)
{ register int i, len;
register char *str;
@ -51,12 +59,12 @@ string(register struct expr **expp;)
}
[
STRING
{ /* A pasted string keeps the type of the first
string literal.
The pasting of normal strings and wide
character strings are stated as having an
undefined behaviour.
*/
{ /* A pasted string keeps the type of the first
* string literal.
* The pasting of normal strings and wide
* character strings are stated as having an
* undefined behaviour.
*/
if (dot.tk_fund != fund)
warning("illegal pasting of string literals");
str = Srealloc(str, (unsigned) (--len + dot.tk_len));
@ -64,43 +72,35 @@ string(register struct expr **expp;)
str[len++] = dot.tk_bts[i];
}
]*
{string2expr(expp, STRING, str, len);}
{ string2expr(expp, str, len); }
;
secundary(register struct expr **expp;) :
/* 3.3.2 */
postfix_expression(register struct expr **expp;)
{ int oper;
struct expr *e1 = 0;
struct idf *idf;
}
:
primary(expp)
[
index_pack(expp)
'[' expression(&e1) ']'
{ ch7bin(expp, '[', e1); e1 = 0; }
|
parameter_pack(expp)
'(' parameter_list(&e1)? ')'
{ ch7bin(expp, '(', e1); call_proto(expp); e1 = 0; }
|
selection(expp)
[ '.' | ARROW ] { oper = DOT; }
identifier(&idf) { ch7sel(expp, oper, idf); }
]*
;
index_pack(struct expr **expp;)
{struct expr *e1;}
:
'[' expression(&e1) ']'
{ch7bin(expp, '[', e1);}
;
parameter_pack(struct expr **expp;)
{struct expr *e1 = 0;}
:
'(' parameter_list(&e1)? ')'
{ ch7bin(expp, '(', e1);
call_proto(expp);
}
;
selection(struct expr **expp;)
{int oper; struct idf *idf;}
:
[ '.' | ARROW ]
{oper = DOT;}
identifier(&idf)
{ch7sel(expp, oper, idf);}
[
[
PLUSPLUS { oper = POSTINCR; }
|
MINMIN { oper = POSTDECR; }
]
{ ch7incr(expp, oper); }
]?
;
parameter_list(struct expr **expp;)
@ -108,28 +108,17 @@ parameter_list(struct expr **expp;)
:
assignment_expression(expp)
{any2opnd(expp, PARCOMMA);}
[ ','
[ %persistent
','
assignment_expression(&e1)
{any2opnd(&e1, PARCOMMA);}
{ch7bin(expp, PARCOMMA, e1);}
]*
;
/* 7.2 */
postfixed(struct expr **expp;)
{int oper;}
:
secundary(expp)
[
postop(&oper)
{ch7incr(expp, oper);}
|
empty
]
;
%first first_of_type_specifier, type_specifier;
/* 3.3.3 & 3.3.4 */
unary(register struct expr **expp;)
{struct type *tp; int oper;}
:
@ -139,7 +128,7 @@ unary(register struct expr **expp;)
(*expp)->ex_flags |= EX_CAST;
}
|
postfixed(expp)
postfix_expression(expp)
|
unop(&oper) unary(expp)
{ch7mon(oper, expp);}
@ -147,10 +136,14 @@ unary(register struct expr **expp;)
size_of(expp)
;
/* When an identifier is used in a sizeof()-expression, we must stil not
* mark it as used.
* extern int i; .... sizeof(i) .... need not have a definition for i
*/
size_of(register struct expr **expp;)
{struct type *tp;}
:
SIZEOF
SIZEOF { InSizeof++; } /* handle (sizeof(sizeof(int))) too */
[%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
cast(&tp)
{
@ -161,13 +154,19 @@ size_of(register struct expr **expp;)
unary(expp)
{ch7mon(SIZEOF, expp);}
]
{ InSizeof--; }
;
/* 7.3-7.12 */
/* 3.3.5-3.3.17 */
/* The set of operators in C is stratified in 15 levels, with level
N being treated in RM 7.N. In principle each operator is
assigned a rank, ranging from 1 to 15. Such an expression can
be parsed by a construct like:
N being treated in RM 7.N (although this is not the standard
anymore). The standard describes this in phrase-structure-grammar,
which we are unable to parse. The description that follows comes
from the old C-compiler.
In principle each operator is assigned a rank, ranging
from 1 to 15. Such an expression can be parsed by a construct
like:
binary_expression(int maxrank;)
{int oper;}
:
@ -199,48 +198,57 @@ size_of(register struct expr **expp;)
*/
binary_expression(int maxrank; struct expr **expp;)
{int oper; struct expr *e1;}
{int oper, OldResultKnown; struct expr *e1;}
:
unary(expp)
[%while (rank_of(DOT) <= maxrank && AHEAD != '=')
/* '?', '=', and ',' are no binops, and the test
for AHEAD != '=' keeps the other assignment
operators out
*/
[%while (rank_of(DOT) <= maxrank )
/* '?', '=', and ',' are no binops
*/
binop(&oper)
{ OldResultKnown = ResultKnown;
if (oper == OR || oper == AND) {
if (is_cp_cst(*expp) || is_fp_cst(*expp)) {
if (is_zero_cst(*expp)) {
if (oper == AND) ResultKnown++;
} else if (oper == OR) ResultKnown++;
}
}
}
binary_expression(rank_of(oper)-1, &e1)
{
ch7bin(expp, oper, e1);
ResultKnown = OldResultKnown;
}
]*
;
/* 7.13 */
/* 3.3.15 */
conditional_expression(struct expr **expp;)
/* There is some unfortunate disagreement about what is allowed
between the '?' and the ':' of a conditional_expression.
Although the Ritchie compiler does not even allow
conditional_expressions there, some other compilers (e.g., VAX)
accept a full assignment_expression there, and programs
(like, e.g., emacs) rely on it. So we have little choice.
*/
{struct expr *e1 = 0, *e2 = 0;}
{struct expr *e1 = 0, *e2 = 0; int OldResultKnown, ConstExpr=0;}
:
/* allow all binary operators */
binary_expression(rank_of('?') - 1, expp)
[ '?'
expression(&e1)
{
#ifndef NOROPTION
check_conditional(e1, '?', "between ? and :");
#endif
{ OldResultKnown = ResultKnown;
if (is_cp_cst(*expp) || is_fp_cst(*expp)) {
ConstExpr++;
if (is_zero_cst(*expp)) ResultKnown++;
}
}
expression(&e1)
':'
{ if (ConstExpr) {
if (OldResultKnown == ResultKnown) ResultKnown++;
else ResultKnown = OldResultKnown;
}
}
/* should be: conditional_expression(&e2)
* but that wouldn't work with 0 ? 0 : i = 0
*/
assignment_expression(&e2)
{
#ifndef NOROPTION
check_conditional(e2, '=', "after :");
#endif
check_conditional(e2, '=', "not allowed after :");
ResultKnown = OldResultKnown;
ch7bin(&e1, ':', e2);
opnd2test(expp, '?');
ch7bin(expp, '?', e1);
@ -248,11 +256,10 @@ conditional_expression(struct expr **expp;)
]?
;
/* 7.14 */
/* 3.3.16 */
assignment_expression(struct expr **expp;)
{
int oper;
struct expr *e1 = 0;
{ int oper;
struct expr *e1 = 0;
}
:
conditional_expression(expp)
@ -265,7 +272,7 @@ assignment_expression(struct expr **expp;)
]
;
/* 7.15 */
/* 3.3.17 */
expression(struct expr **expp;)
{struct expr *e1;}
:
@ -283,12 +290,6 @@ unop(int *oper;) :
{*oper = DOT;}
;
postop(int *oper;):
PLUSPLUS {*oper = POSTINCR;}
|
MINMIN {*oper = POSTDECR;}
;
multop:
'*' | '/' | '%'
;
@ -321,30 +322,8 @@ binop(int *oper;) :
;
asgnop(register int *oper;):
'=' {*oper = DOT;}
|
'+' '=' {*oper = PLUSAB;}
|
'-' '=' {*oper = MINAB;}
|
'*' '=' {*oper = TIMESAB;}
|
'/' '=' {*oper = DIVAB;}
|
'%' '=' {*oper = MODAB;}
|
LEFT '=' {*oper = LEFTAB;}
|
RIGHT '=' {*oper = RIGHTAB;}
|
'&' '=' {*oper = ANDAB;}
|
'^' '=' {*oper = XORAB;}
|
'|' '=' {*oper = ORAB;}
|
[ PLUSAB | MINAB | TIMESAB | DIVAB | MODAB | LEFTAB | RIGHTAB
| ANDAB | XORAB | ORAB ]
[ '=' | PLUSAB | MINAB | TIMESAB | DIVAB | MODAB
| LEFTAB | RIGHTAB | ANDAB | XORAB | ORAB ]
{ *oper = DOT; }
;
@ -357,19 +336,16 @@ constant(struct expr **expp;) :
] {dot2expr(expp);}
;
/* 15 */
/* 3.4 */
constant_expression (struct expr **expp;) :
assignment_expression(expp)
{chk_cst_expr(expp);}
conditional_expression(expp)
/* was: assignment_expression(expp) */
{ chk_cst_expr(expp); }
;
identifier(struct idf **idfp;) :
[
IDENTIFIER
|
TYPE_IDENTIFIER
[ IDENTIFIER
| TYPE_IDENTIFIER
]
{
*idfp = dot.tk_idf;
}
{ *idfp = dot.tk_idf; }
;

View file

@ -14,6 +14,7 @@
#include <em.h>
#include <em_reg.h>
#include "debug.h"
#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "idf.h"

View file

@ -7,7 +7,6 @@
#include "lint.h"
#include <em_reg.h>
#include "nofloat.h"
#include "debug.h"
#include "idfsize.h"
#include "botch_free.h"
@ -31,7 +30,6 @@
#include "Lpars.h"
#include "assert.h"
#include "specials.h" /* registration of special identifiers */
#include "noRoption.h"
int idfsize = IDFSIZE;
extern char options[];
@ -226,24 +224,18 @@ declare_idf(ds, dc, lvl)
type = construct_type(POINTER, type, 0, (arith)0,
NO_PROTO);
break;
case ARRAY: /* RM 10.1 */
case ARRAY: /* 3.7.1 */
type = construct_type(POINTER, type->tp_up, 0, (arith)0,
NO_PROTO);
formal_array = 1;
break;
#ifndef NOFLOAT
case FLOAT: /* RM 10.1 */
type = double_type;
break;
#endif NOFLOAT
case FLOAT:
case CHAR:
case SHORT:
/* The RM is not clear about this: we must
convert the parameter from int (they have
been pushed as ints) to the specified type.
The conversion to type int or uint is not
allowed.
*/
/* The conversion is done in formal_cvt(). It is
* not done when the type is float and there is a
* prototype.
*/
break;
}
}
@ -252,29 +244,27 @@ declare_idf(ds, dc, lvl)
*/
/* update the storage class */
if (type && type->tp_fund == FUNCTION) {
if (sc == 0 || (ds->ds_sc_given && sc == AUTO)) /* RM 8.1 */
sc = GLOBAL;
else
if (sc == REGISTER) {
error("function storage class cannot be register");
ds->ds_sc = sc = GLOBAL;
if (lvl != L_GLOBAL) { /* 3.5.1 */
if (sc == 0)
sc = GLOBAL;
else if (sc != EXTERN && sc != IMPLICIT) {
error("illegal storage class %s for function with block-scope"
, symbol2str(sc));
ds->ds_sc = sc = GLOBAL;
}
}
else if (sc == 0)
sc = GLOBAL;
}
else /* non-FUNCTION */
if (sc == 0)
sc = lvl == L_GLOBAL ? GLOBAL
: lvl == L_FORMAL1 || lvl == L_FORMAL2 ? FORMAL
: AUTO;
#ifndef NOROPTION
if (options['R']) { /* some special K & R tests */
/* is it also an enum? */
if (idf->id_enum && idf->id_enum->tg_level == level)
warning("%s is also an enum tag", idf->id_text);
/* is it a universal typedef? */
if (def && def->df_level == L_UNIVERSAL)
warning("redeclaring reserved word %s", idf->id_text);
}
#endif
/* is it a universal typedef? */
if (def && def->df_level == L_UNIVERSAL)
warning("redeclaring reserved word %s", idf->id_text);
#ifdef LINT
if ( def && def->df_level < lvl
@ -330,6 +320,7 @@ declare_idf(ds, dc, lvl)
def->df_file = idf->id_file;
def->df_line = idf->id_line;
}
#if 0 /* be more strict in scope (at least for now) */
else
if ( lvl >= L_LOCAL &&
(type->tp_fund == FUNCTION || sc == EXTERN)
@ -337,16 +328,13 @@ declare_idf(ds, dc, lvl)
/* extern declaration inside function is treated the
same way as global extern declaration
*/
#ifndef NOROPTION
if ( options['R'] &&
(sc == STATIC && type->tp_fund == FUNCTION)
)
if (sc == STATIC && type->tp_fund == FUNCTION)
if (!is_anon_idf(idf))
warning("non-global static function %s",
idf->id_text);
#endif
declare_idf(ds, dc, L_GLOBAL);
}
#endif
else { /* fill in the def block */
register struct def *newdef = new_def();
@ -376,7 +364,8 @@ declare_idf(ds, dc, lvl)
switch (sc) {
case REGISTER:
case AUTO:
if (type->tp_size == (arith)-1) {
if (type->tp_size == (arith)-1
&& type->tp_fund != ARRAY) {
error("size of local %s unknown",
idf->id_text);
/** type = idf->id_def->df_type = int_type; **/
@ -423,10 +412,12 @@ global_redecl(idf, new_sc, tp)
in storage class.
*/
register struct def *def = idf->id_def;
int retval;
if (!equal_type(tp, def->df_type))
if (!(retval = equal_type(tp, def->df_type)))
error("redeclaration of %s with different type", idf->id_text);
else update_proto(tp, def->df_type);
else if (retval == 1)
update_proto(tp, def->df_type);
if (tp->tp_fund == ARRAY) {
/* Multiple array declaration; this may be interesting */
if (tp->tp_size < 0) { /* new decl has [] */
@ -451,6 +442,7 @@ global_redecl(idf, new_sc, tp)
*/
if (new_sc == IMPLICIT)
return; /* no new information */
switch (def->df_sc) { /* the old storage class */
case EXTERN:
switch (new_sc) { /* the new storage class */
@ -458,15 +450,8 @@ global_redecl(idf, new_sc, tp)
case GLOBAL:
break;
case STATIC:
if (def->df_initialized) {
error("cannot redeclare %s to static",
idf->id_text);
}
else {
warning("%s redeclared to static",
idf->id_text);
}
def->df_sc = new_sc;
warning("redeclaration of %s to static ignored"
, idf->id_text);
break;
default:
crash("bad storage class");
@ -481,17 +466,8 @@ global_redecl(idf, new_sc, tp)
case GLOBAL:
break;
case STATIC:
if (def->df_initialized)
error("cannot redeclare %s to static",
idf->id_text);
else {
#ifndef NOROPTION
if (options['R'])
warning("%s redeclared to static",
idf->id_text);
#endif
def->df_sc = STATIC;
}
warning("redeclaration of %s to static ignored"
, idf->id_text);
break;
default:
crash("bad storage class");
@ -500,21 +476,13 @@ global_redecl(idf, new_sc, tp)
break;
case STATIC:
switch (new_sc) { /* the new storage class */
case EXTERN:
if (def->df_initialized)
error("cannot redeclare %s to extern",
idf->id_text);
else {
warning("%s redeclared to extern",
idf->id_text);
def->df_sc = EXTERN;
}
break;
case GLOBAL:
warning("%s redeclared extern", idf->id_text);
def->df_sc = new_sc;
break;
case EXTERN: /* complain at definition */
break;
case STATIC:
if (def->df_type->tp_fund != FUNCTION)
warning("%s was already static",
idf->id_text);
break;
default:
crash("bad storage class");
@ -528,11 +496,6 @@ global_redecl(idf, new_sc, tp)
def->df_sc = new_sc;
break;
case STATIC:
#ifndef NOROPTION
if (options['R'])
warning("%s was implicitly declared as extern",
idf->id_text);
#endif
def->df_sc = new_sc;
break;
default:
@ -568,18 +531,16 @@ good_formal(def, idf)
}
declare_params(dc)
register struct declarator *dc;
struct declarator *dc;
{
/* Declares the formal parameters if they exist.
*/
register struct formal *fm = dc->dc_formal;
while (fm) {
declare_parameter(fm->fm_idf);
fm = fm->next;
}
free_formals(dc->dc_formal);
dc->dc_formal = 0;
}
init_idf(idf)
@ -617,7 +578,76 @@ declare_enum(tp, idf, l)
idf->id_def->df_address = l;
}
declare_formals(fp)
check_formals(idf, dc)
struct idf *idf;
struct declarator *dc;
{
register struct formal *fm = dc->dc_formal;
register struct proto *pl = idf->id_def->df_type->tp_proto;
register struct decl_unary *du = dc->dc_decl_unary;
if (!du) { /* error or typdef'ed function */
error("illegal definition of %s", idf->id_text);
return;
}
while (du && du->du_fund != FUNCTION)
du = du->next;
ASSERT(du);
if (du->du_proto) return;
warning("'%s' old-fashioned function definition", dc->dc_idf->id_text);
if (pl) {
if (pl->pl_flag & PL_ELLIPSIS) {
if (!(du->du_proto) && !(pl->pl_flag & PL_ERRGIVEN))
error("ellipsis terminator in previous declaration");
pl = pl->next;
}
else if (pl->pl_flag & PL_VOID) {
pl = pl->next; /* should be 0 */
}
while(fm && pl) {
if (!equal_type(promoted_type(fm->fm_idf->id_def->df_type)
, pl->pl_type)) {
if (!(pl->pl_flag & PL_ERRGIVEN))
error("incorrect type for parameter %s"
, fm->fm_idf->id_text);
pl->pl_flag |= PL_ERRGIVEN;
}
fm = fm->next;
pl = pl->next;
}
if (pl || fm) {
error("incorrect number of parameters");
}
} else { /* make a pseudo-prototype */
register struct proto *lpl;
while (fm) {
if (pl == 0) pl = lpl = new_proto();
else {
lpl->next = new_proto();
lpl = lpl->next;
}
lpl->pl_flag = PL_FORMAL;
lpl->pl_idf = fm->fm_idf;
lpl->pl_type =
promoted_type(fm->fm_idf->id_def->df_type);
fm = fm->next;
}
if (pl == 0) { /* make func(void) */
pl = new_proto();
pl->pl_flag = PL_VOID;
}
idf->id_def->df_type->tp_pseudoproto = pl;
}
free_formals(dc->dc_formal);
dc->dc_formal = 0;
}
declare_formals(idf, fp)
struct idf *idf;
arith *fp;
{
/* Declares those formals as int that haven't been declared
@ -628,6 +658,7 @@ declare_formals(fp)
register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
arith f_offset = (arith)0;
register int nparams = 0;
int hasproto = idf->id_def->df_type->tp_proto != 0;
#ifdef DEBUG
if (options['t'])
@ -636,13 +667,22 @@ declare_formals(fp)
while (se) {
register struct def *def = se->se_idf->id_def;
/* this stacklevel may also contain tags. ignore them */
if (!def || def->df_level < L_FORMAL1 ) {
se = se->next;
continue;
}
def->df_address = f_offset;
/* the alignment convention for parameters is: align on
word boundaries, i.e. take care that the following
parameter starts on a new word boundary.
*/
f_offset = align(f_offset + def->df_type->tp_size, (int) word_size);
formal_cvt(def); /* cvt int to char or short, if necessary */
/* cvt int to char or short and double to float, if necessary
*/
formal_cvt(hasproto, def);
se = se->next;
def->df_level = L_FORMAL2; /* CJ */
RegisterAccount(def->df_address, def->df_type->tp_size,
@ -662,11 +702,10 @@ regtype(tp)
case INT:
case LONG:
return reg_any;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
return reg_float;
#endif NOFLOAT
case POINTER:
return reg_pointer;
}

View file

@ -40,7 +40,6 @@ struct idf {
struct sdef *id_sdef; /* selector tags */
struct tag *id_struct; /* struct and union tags */
struct tag *id_enum; /* enum tags */
int id_proto; /* non-zero don't complain about proto */
int id_special; /* special action needed at occurrence */
};

View file

@ -74,22 +74,22 @@ init_pp()
/* __DATE__ */
sprintf(dbuf, "\"%.3s %.2d %d\"", months[tp->tm_mon],
tp->tm_mday, tp->tm_year+1900);
macro_def(str2idf("__DATE__"), dbuf, -1, 12, NOFLAG);
macro_def(str2idf("__DATE__"), dbuf, -1, strlen(dbuf), NOUNDEF);
/* __TIME__ */
sprintf(tbuf, "\"%.2d:%.2d:%.2d\"", tp->tm_hour, tp->tm_min, tp->tm_sec);
macro_def(str2idf("__TIME__"), tbuf, -1, 10, NOFLAG);
macro_def(str2idf("__TIME__"), tbuf, -1, strlen(tbuf), NOUNDEF);
/* __LINE__ */
macro_def(str2idf("__LINE__"), "0", -1, 1, FUNC);
macro_def(str2idf("__LINE__"), "0", -1, 1, NOUNDEF | FUNC);
/* __FILE__ */
macro_def(str2idf("__FILE__"), "", -1, 1, FUNC);
macro_def(str2idf("__FILE__"), "", -1, 1, NOUNDEF | FUNC);
/* __STDC__ */
macro_def(str2idf("__STDC__"), "1", -1, 1, NOFLAG);
macro_def(str2idf("__STDC__"), "1", -1, 1, NOUNDEF);
/* defined(??) */
macro_def(str2idf("defined"), "", 1, 1, FUNC);
macro_def(str2idf("defined"), "", 1, 1, NOUNDEF | FUNC);
}
#endif NOPP

View file

@ -34,7 +34,7 @@ getwdir(fn)
return "";
if (p) {
*p = '\0';
fn = Salloc(fn, p - &fn[0] + 1);
fn = Salloc(fn,(unsigned) (p - &fn[0] + 1));
*p = '/';
return fn;
}
@ -43,9 +43,13 @@ getwdir(fn)
#endif NOPP
int NoUnstack;
int InputLevel;
#if 0
#endif
AtEoIT()
{
InputLevel--;
unstackrepl();
return 0;
}

View file

@ -9,7 +9,7 @@
/* Note: The following macro only garuantees one PushBack.
*/
#define UnGetChar() ChPushBack(LexSave)
#define UnGetChar() ((LexSave != EOI) ? ChPushBack(LexSave) : 0)
extern int LexSave; /* last character read by GetChar */
extern int GetChar(); /* character input, with trigraph parsing */

View file

@ -7,12 +7,12 @@
{
#include "lint.h"
#include "nofloat.h"
#include <em.h>
#include "debug.h"
#include <alloc.h>
#include <assert.h>
#include "nobitfield.h"
#include <flt_arith.h>
#include "arith.h"
#include "label.h"
#include "expr.h"
@ -27,7 +27,6 @@
#include "level.h"
#include "def.h"
#include "LLlex.h"
#include "noRoption.h"
#include "estack.h"
#ifdef LINT
#include "l_lint.h"
@ -45,13 +44,15 @@ struct sdef *gen_align_to_next();
struct e_stack *p_stack;
}
/* initial_value recursively guides the initialisation expression.
Upto now, the initialisation of a union is not allowed!
*/
/* 7 */
/* initial_value recursively guides the initialisation expression.
*/
/* 3.5 */
{ static int pack_level; }
initial_value(register struct type **tpp; register struct expr **expp;) :
{ if (tpp) gen_tpcheck(tpp, 0); }
{ if (tpp) gen_tpcheck(tpp); }
[
{ if (pack_level == 0) gen_error = 0; }
assignment_expression(expp)
{
#ifdef LINT
@ -71,7 +72,6 @@ initial_value(register struct type **tpp; register struct expr **expp;) :
;
initial_value_pack(struct type **tpp; struct expr **expp;)
{ static int pack_level; }
:
'{'
{ if (pack_level == 0) gen_error = 0; pack_level++; }
@ -108,7 +108,7 @@ initial_value_list(register struct type **tpp; struct expr **expp;)
;
{
gen_tpcheck(tpp, union_allowed)
gen_tpcheck(tpp)
struct type **tpp;
{
register struct type *tp;
@ -418,24 +418,14 @@ pad(tpx)
register struct type *tp = tpx;
register arith sz = tp->tp_size;
gen_tpcheck(&tpx, 1);
gen_tpcheck(&tpx);
if (gen_error) return;
switch (tp->tp_fund) {
case UNION:
#ifndef NOROPTION
if (options['R']) {
warning("initialisation of unions not allowed");
}
#endif
break;
#ifndef NOBITFIELD
case FIELD:
if (tp->tp_fund == FIELD) {
put_bf(tp, (arith)0);
return;
#endif NOBITFIELD
default:
break;
}
#endif NOBITFIELD
while (sz >= word_size) {
C_con_cst((arith) 0);
@ -498,16 +488,21 @@ check_ival(expp, tp)
C_con_dlb(expr->VL_LBL, expr->VL_VALUE);
}
break;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
ch7cast(expp, '=', tp);
expr = *expp;
#ifdef DEBUG
print_expr("init-expr after cast", expr);
#endif DEBUG
if (expr->ex_class == Float)
if (expr->ex_class == Float) {
if (!expr->FL_VALUE) {
expr->FL_VALUE = Malloc(FLT_STRLEN);
flt_flt2str(&(expr->FL_ARITH), expr->FL_VALUE, FLT_STRLEN);
}
C_con_fcon(expr->FL_VALUE, expr->ex_type->tp_size);
}
#ifdef NOTDEF
Coercion from int to float is now always done compile time.
@ -529,7 +524,6 @@ and also to prevent runtime coercions for compile-time constants.
else
illegal_init_cst(expr);
break;
#endif NOFLOAT
#ifndef NOBITFIELD
case FIELD:
@ -562,13 +556,13 @@ ch_array(tpp, ex)
struct expr *ex;
{
register struct type *tp = *tpp;
register arith length = ex->SG_LEN;
char *s;
register int length = ex->SG_LEN, i;
register char *to, *from, *s;
ASSERT(ex->ex_class == String);
if (tp->tp_size == (arith)-1) {
/* set the dimension */
tp = *tpp = construct_type(ARRAY, tp->tp_up, 0, length, NO_PROTO);
tp = *tpp = construct_type(ARRAY, tp->tp_up, 0, (arith)length, NO_PROTO);
}
else {
arith dim = tp->tp_size / tp->tp_up->tp_size;
@ -580,10 +574,14 @@ ch_array(tpp, ex)
}
/* throw out the characters of the already prepared string */
s = Malloc((unsigned) (length));
clear(s, (int) (length));
strncpy(s, ex->SG_VALUE, (int) length);
clear(s, length);
i = length <= ex->SG_LEN ? length : ex->SG_LEN;
to = s; from = ex->SG_VALUE;
while(--i >= 0) {
*to++ = *from++;
}
free(ex->SG_VALUE);
str_cst(s, (int) (length));
str_cst(s, length);
free(s);
}
@ -651,7 +649,7 @@ zero_bytes(sd)
*/
register int n = sd->sd_sdef->sd_offset - sd->sd_offset -
size_of_type(sd->sd_type, "struct member");
register int count = n;
int count = n;
while (n-- > 0)
con_nullbyte();

View file

@ -12,6 +12,7 @@
#include <alloc.h> /* for st_free */
#include "interface.h"
#include "assert.h"
#include <flt_arith.h>
#include "arith.h" /* definition arith */
#include "label.h" /* definition label */
#include "expr.h"
@ -23,7 +24,6 @@
#include "stack.h"
#include "type.h"
#include "level.h"
#include "nofloat.h"
#include "l_lint.h"
#include "l_state.h"

View file

@ -13,6 +13,7 @@
#include "debug.h"
#include "interface.h"
#include "assert.h"
#include <flt_arith.h>
#include "arith.h" /* definition arith */
#include "label.h" /* definition label */
#include "expr.h"
@ -24,7 +25,6 @@
#include "stack.h"
#include "type.h"
#include "level.h"
#include "nofloat.h"
#include "l_lint.h"
#include "l_state.h"
#include "l_outdef.h"

View file

@ -11,6 +11,7 @@
#include <alloc.h> /* for st_free */
#include "interface.h"
#include <flt_arith.h>
#include "arith.h" /* definition arith */
#include "label.h" /* definition label */
#include "expr.h"
@ -22,7 +23,6 @@
#include "stack.h"
#include "type.h"
#include "level.h"
#include "nofloat.h"
#include "l_state.h"
extern char *symbol2str();
@ -140,7 +140,8 @@ lint_new_oper(expr)
break;
case '~':
if (r_fund == ENUM || r_fund == FLOAT || r_fund == DOUBLE)
if (r_fund == ENUM || r_fund == FLOAT || r_fund == DOUBLE
/* ??? || r_fund == LNGDBL */ )
warning("~ on %s", symbol2str(r_fund));
break;
@ -285,6 +286,7 @@ numsize(fund)
case LONG: return 4;
case FLOAT: return 5;
case DOUBLE: return 6;
case LNGDBL: return 7;
default: return 0;
}
}
@ -300,8 +302,8 @@ lint_ptr_conv(from, to)
{
/* X -> X ok -- this includes struct -> struct, of any size
* X -> CHAR ok
* DOUBLE -> X ok
* FLOAT -> LONG -> INT -> SHORT ok
* LNGDBL -> X ok
* DOUBLE -> FLOAT -> LONG -> INT -> SHORT ok
*/
if (from == to)
return;
@ -309,10 +311,18 @@ lint_ptr_conv(from, to)
if (to == CHAR)
return;
if (from == DOUBLE)
if (from == LNGDBL)
return;
switch (from) {
case DOUBLE:
switch(to) {
case FLOAT:
case INT:
case SHORT:
return;
}
break;
case FLOAT:
switch (to) {
case LONG:

View file

@ -11,6 +11,7 @@
#include <alloc.h>
#include "interface.h"
#include <flt_arith.h>
#include "arith.h"
#include "assert.h"
#include "type.h"
@ -442,6 +443,7 @@ outargtype(tp)
case LONG:
case FLOAT:
case DOUBLE:
case LNGDBL:
case VOID:
case ERRONEOUS:
if (tp->tp_unsigned)

View file

@ -13,6 +13,7 @@
#include "interface.h"
#include "assert.h"
#include "debug.h"
#include <flt_arith.h>
#include "arith.h" /* definition arith */
#include "label.h" /* definition label */
#include "expr.h"
@ -24,7 +25,6 @@
#include "stack.h"
#include "type.h"
#include "level.h"
#include "nofloat.h"
#include "l_lint.h"
#include "l_brace.h"
#include "l_state.h"

View file

@ -12,7 +12,6 @@
#include "arith.h"
#include "def.h"
#include "type.h"
#include "noRoption.h"
extern char options[];
@ -33,25 +32,10 @@ enter_label(idf, defining)
idf->id_text);
}
else { /* there may still be room for it */
#ifndef NOROPTION
if (options['R'] && def->df_sc == TYPEDEF)
warning("label %s is also a typedef",
idf->id_text);
#endif
if (def->df_level == level) /* but alas, no */
error("%s is not a label", idf->id_text);
else {
register int lvl = def->df_level + 1;
#ifndef NOROPTION
if (options['R'] && def->df_level > L_LOCAL)
warning("label %s is not function-wide",
idf->id_text);
#endif
if (lvl < L_LOCAL)
lvl = L_LOCAL;
add_def(idf, LABEL, label_type, lvl);
add_def(idf, LABEL, label_type, L_LOCAL);
}
}
}

View file

@ -12,8 +12,9 @@
these flags can be set simultaneously.
*/
#define NOFLAG 0 /* no special flags */
#define FUNC 01 /* function attached */
#define NOREPLACE 02 /* don't replace */
#define FUNC 0x1 /* function attached */
#define NOUNDEF 0x2 /* special macro */
#define NOREPLACE 0x4 /* prevent recursion */
#define FORMALP 0200 /* mask for creating macro formal parameter */

View file

@ -6,7 +6,6 @@
/* MAIN PROGRAM */
#include "lint.h"
#include "nofloat.h"
#include <system.h>
#include "nopp.h"
#include "target_sizes.h"
@ -25,7 +24,6 @@
#include "LLlex.h"
#include <alloc.h>
#include "specials.h"
#include "noRoption.h"
#include "nocross.h"
#include "sizes.h"
#include "align.h"
@ -55,11 +53,9 @@ arith
dword_size = (2 * SZ_WORD),
int_size = SZ_INT,
long_size = SZ_LONG,
#ifndef NOFLOAT
float_size = SZ_FLOAT,
double_size = SZ_DOUBLE,
lngdbl_size = SZ_LNGDBL,
#endif NOFLOAT
pointer_size = SZ_POINTER;
int
@ -67,11 +63,9 @@ int
word_align = AL_WORD,
int_align = AL_INT,
long_align = AL_LONG,
#ifndef NOFLOAT
float_align = AL_FLOAT,
double_align = AL_DOUBLE,
lngdbl_align = AL_LNGDBL,
#endif NOFLOAT
pointer_align = AL_POINTER,
struct_align = AL_STRUCT,
union_align = AL_UNION;
@ -113,7 +107,7 @@ main(argc, argv)
{
char *par = &argv[1][1];
do_option(par, 1);
do_option(par);
argc--, argv++;
}
#ifdef LINT
@ -240,7 +234,7 @@ init()
transparent to the user.
*/
gen_type = standard_type(GENERIC, 0, 1, (arith)1);
char_type = standard_type(CHAR, 0, 1, (arith)1);
schar_type = standard_type(CHAR, 0, 1, (arith)1);
uchar_type = standard_type(CHAR, UNSIGNED, 1, (arith)1);
short_type = standard_type(SHORT, 0, short_align, short_size);
@ -259,11 +253,9 @@ init()
long_type = standard_type(LONG, 0, long_align, long_size);
ulong_type = standard_type(LONG, UNSIGNED, long_align, long_size);
#ifndef NOFLOAT
float_type = standard_type(FLOAT, 0, float_align, float_size);
double_type = standard_type(DOUBLE, 0, double_align, double_size);
lngdbl_type = standard_type(LNGDBL, 0, lngdbl_align, lngdbl_size);
#endif NOFLOAT
void_type = standard_type(VOID, 0, 1, (arith)0);
label_type = standard_type(LABEL, 0, 0, (arith)0);
error_type = standard_type(ERRONEOUS, 0, 1, (arith)1);
@ -292,17 +284,15 @@ init()
if ((int)short_size > (int)int_size || (int)int_size > (int)long_size)
fatal("sizes of short/int/long decreasing");
/* Build a type for function returning int, RM 13 */
/* Build a type for function returning int (3.3.2.2) */
funint_type = construct_type(FUNCTION, int_type, 0, (arith)0, NO_PROTO);
string_type = construct_type(POINTER, char_type, 0, (arith)0, NO_PROTO);
string_type = construct_type(POINTER, schar_type, 0, (arith)0, NO_PROTO);
/* Define the standard type identifiers. */
add_def(str2idf("char"), TYPEDEF, char_type, L_UNIVERSAL);
add_def(str2idf("char"), TYPEDEF, schar_type, L_UNIVERSAL);
add_def(str2idf("int"), TYPEDEF, int_type, L_UNIVERSAL);
#ifndef NOFLOAT
add_def(str2idf("float"), TYPEDEF, float_type, L_UNIVERSAL);
add_def(str2idf("double"), TYPEDEF, double_type, L_UNIVERSAL);
#endif NOFLOAT
add_def(str2idf("void"), TYPEDEF, void_type, L_UNIVERSAL);
stack_level();
}
@ -372,17 +362,16 @@ preprocess()
char sbuf[1024]; /* a transient buffer */
char *bts2str();
print("\"%s\" ", bts2str(dot.tk_bts, dot.tk_len, sbuf));
print("\"%s\" ", bts2str(dot.tk_bts, dot.tk_len -
1, sbuf));
break;
}
case INTEGER:
print("%ld ", dot.tk_ival);
break;
#ifndef NOFLOAT
case FLOATING:
print("%s ", dot.tk_fval);
break;
#endif NOFLOAT
case EOI:
case EOF:
return;

View file

@ -8,7 +8,6 @@
#include "lint.h"
#include "botch_free.h"
#include <alloc.h>
#include "nofloat.h"
#include "nopp.h"
#include "idfsize.h"
#include "nobitfield.h"
@ -20,7 +19,6 @@
#include "align.h"
#include "use_tmp.h"
#include "dataflow.h"
#include "noRoption.h"
#ifndef NOPP
extern char **inctable;
@ -86,14 +84,6 @@ next_option: /* to allow combined one-char options */
goto next_option;
#endif LINT
case 'R': /* strict version */
#ifndef NOROPTION
options[opt] = 1;
#else NOROPTION
warning("-R option not implemented");
#endif NOROPTION
goto next_option;
#ifdef ___XXX___
deleted, is now a debug-flag
case 'C' : /* E option + comment output */
@ -284,28 +274,22 @@ deleted, is now a debug-flag
long_align = algn;
break;
case 'f': /* float */
#ifndef NOFLOAT
if (sz != (arith)0)
float_size = sz;
if (algn != 0)
float_align = algn;
#endif NOFLOAT
break;
case 'd': /* double */
#ifndef NOFLOAT
if (sz != (arith)0)
double_size = sz;
if (algn != 0)
double_align = algn;
#endif NOFLOAT
break;
case 'x': /* long double */
#ifndef NOFLOAT
if (sz != (arith)0)
lngdbl_size = sz;
if (algn != 0)
lngdbl_align = algn;
#endif NOFLOAT
break;
case 'p': /* pointer */
if (sz != (arith)0)

View file

@ -38,15 +38,13 @@ struct pkey {
extern struct idf *GetIdentifier();
do_pragma()
{
register struct pkey *pkp;
register struct idf *id;
struct token tk;
int flag;
if ((id = GetIdentifier()) != (struct idf *)0) {
if ((id = GetIdentifier(1)) != (struct idf *)0) {
/* Lineair search - why bother ?
*/
for (pkp = &pragmas[0]; pkp->pk_key != P_UNKNOWN; pkp++)
@ -67,8 +65,8 @@ do_pragma()
strict("unimplemented pragma directive");
break;
}
SkipToNewLine(0);
}
SkipToNewLine(0);
else strict("unrecognized pragma line");
}
#endif

View file

@ -47,6 +47,7 @@
{
#include "lint.h"
#include "nopp.h"
#include <flt_arith.h>
#include "arith.h"
#include "LLlex.h"
#include "idf.h"
@ -86,10 +87,10 @@ control_if_expression
}
;
/* 10 */
/* 3.7 */
program:
[%persistent external_definition]*
{unstack_world();}
{ unstack_world(); }
;
/* A C identifier definition is remarkable in that it formulates
@ -176,29 +177,28 @@ non_function(register struct decspecs *ds; register struct declarator *dc;)
';'
;
/* 10.1 */
/* 3.7.1 */
function(struct decspecs *ds; struct declarator *dc;)
{
arith fbytes;
register struct idf *idf = dc->dc_idf;
}
:
{ register struct idf *idf = dc->dc_idf;
{
#ifdef LINT
lint_start_function();
#endif LINT
init_idf(idf);
stack_level(); /* L_FORMAL1 declarations */
if (dc->dc_formal)
strict("'%s' old-fashioned function declaration",
idf->id_text);
declare_params(dc);
begin_proc(ds, idf); /* sets global function info */
stack_level(); /* L_FORMAL2 declarations */
declare_protos(idf, dc);
declare_protos(dc);
}
declaration*
{
declare_formals(&fbytes);
check_formals(idf, dc); /* check style-mixtures */
declare_formals(idf, &fbytes);
#ifdef LINT
lint_formals();
#endif LINT

View file

@ -13,6 +13,7 @@
#include <alloc.h>
#include "Lpars.h"
#include "level.h"
#include <flt_arith.h>
#include "arith.h"
#include "align.h"
#include "stack.h"
@ -29,6 +30,25 @@
extern char options[];
check_for_void(pl)
register struct proto *pl;
{
register int errcnt = 0;
if (!pl) return;
if ((pl->pl_flag & PL_VOID) && !(pl->next)) return;
while (pl) {
if (pl->pl_flag & PL_VOID) {
if (!errcnt && !(pl->pl_flag & PL_ERRGIVEN))
error("illegal use of void in argument list");
pl->pl_flag |= PL_ERRGIVEN;
errcnt++;
}
pl = pl->next;
}
}
add_proto(pl, ds, dc, level)
struct proto *pl;
struct decspecs *ds;
@ -50,7 +70,7 @@ add_proto(pl, ds, dc, level)
ASSERT(ds->ds_type != (struct type *)0);
pl->pl_flag = FORMAL;
pl->pl_flag = PL_FORMAL;
if ((idf = dc->dc_idf) != (struct idf *)0)
def = idf->id_def;
type = declare_type(ds->ds_type, dc);
@ -58,9 +78,9 @@ add_proto(pl, ds, dc, level)
extern char *symbol2str();
error("unknown %s-type", symbol2str(type->tp_fund));
} else if (type->tp_size == 0) {
pl->pl_flag = VOID;
if (idf != (struct idf *)0)
strict("illegal use of void in argument list");
error("illegal use of void in argument list");
else pl->pl_flag = PL_VOID;
}
/* Perform some special conversions for parameters.
@ -70,7 +90,7 @@ add_proto(pl, ds, dc, level)
remove_proto_idfs(type->tp_proto);
type = construct_type(POINTER, type, 0, (arith) 0, NO_PROTO);
} else if (type->tp_fund == ARRAY) {
type = construct_type(POINTER, type, 0, (arith) 0, NO_PROTO);
type = construct_type(POINTER, type->tp_up, 0, (arith) 0, NO_PROTO);
formal_array = 1;
}
@ -84,7 +104,7 @@ add_proto(pl, ds, dc, level)
sc = (ds->ds_sc_given && ds->ds_sc != REGISTER) ?
0 : sc == 0 ? FORMAL : REGISTER;
if (def && (def->df_level == level || def->df_level < L_PROTO)) {
if (def && (def->df_level == level /* || def->df_level < L_PROTO */ )) {
/* redeclaration at the same level */
error("parameter %s redeclared", idf->id_text);
} else if (idf != (struct idf *)0) {
@ -111,6 +131,8 @@ add_proto(pl, ds, dc, level)
...
{ int func(int a, int b);
...
}
}
The idf's a and b declared in the prototype declaration
do not go at any level, they are simply ignored.
@ -118,6 +140,7 @@ add_proto(pl, ds, dc, level)
f(int a, int b) {
...
}
They should go at level L_FORMAL2. But at this stage
we don't know whether we have a prototype or function
@ -131,8 +154,25 @@ add_proto(pl, ds, dc, level)
pl->pl_type = type;
}
declare_protos(idf, dc)
register struct idf *idf;
struct tag *
gettag(tp, idpp)
struct type *tp;
struct idf **idpp;
{
struct tag *tg;
while (tp->tp_up) tp = tp->tp_up;
*idpp = tp->tp_idf;
switch(tp->tp_fund) {
case ENUM: tg = tp->tp_idf->id_enum; break;
case UNION:
case STRUCT: tg = tp->tp_idf->id_struct; break;
default: return (struct tag *)0;
}
return tg;
}
declare_protos(dc)
register struct declarator *dc;
{
/* At this points we know that the idf's in protolist are formal
@ -153,12 +193,17 @@ declare_protos(idf, dc)
du = du->next;
pl = du ? du->du_proto : NO_PROTO;
if (pl) {
#if 0 /* the id_proto member is deleted (???) */
idf->id_proto = 0;
#endif /* 0 */
do {
struct tag *tg;
struct idf *idp = 0;
type = pl->pl_type;
/* `...' only for type checking */
if (pl->pl_flag == ELLIPSIS) {
if (pl->pl_flag & PL_ELLIPSIS) {
pl = pl->next;
continue;
}
@ -181,6 +226,12 @@ declare_protos(idf, dc)
def->df_level = L_FORMAL2;
stack_idf(pl->pl_idf, stl);
pl = pl->next;
tg = gettag(type, &idp);
if (tg && tg->tg_level <= L_PROTO) {
tg->tg_level = L_FORMAL2;
stack_idf(idp, stl);
}
} while (pl);
}
#ifdef DEBUG
@ -265,6 +316,50 @@ free_proto_list(pl)
}
}
/* struct/union and enum tags can be declared inside prototypes
* remove them from the symbol-table
*/
remove_proto_tag(tp)
struct type *tp;
{
struct idf *ident;
struct tag *tg, *otg = 0;
while(tp->tp_up) tp = tp->tp_up;
ident = tp->tp_idf;
switch(tp->tp_fund) {
case ENUM: tg = ident->id_enum; break;
case UNION:
case STRUCT: tg = ident->id_struct; break;
default: return;
}
while (tg && tg->tg_type != tp) {
otg = tg;
tg = tg->next;
}
if (tg ->tg_level > L_PROTO) return;
#ifdef DEBUG
if (options['t'])
print("Removing idf %s from list\n",
ident->id_text);
#endif
if (!otg) {
switch(tp->tp_fund) {
case ENUM: ident->id_enum = tg->next; break;
case UNION:
case STRUCT: ident->id_struct = tg->next; break;
}
free_tag(tg);
}
else {
otg->next = tg->next;
free_tag(tg);
}
}
remove_proto_idfs(pl)
register struct proto *pl;
{
@ -283,15 +378,19 @@ remove_proto_idfs(pl)
#endif
/* Remove all the definitions made within
a prototype.
??? is this really necessary (Hans)
wasn't this done before in the declaration
*/
if (pl->pl_flag == FORMAL) {
#if 0
if (pl->pl_flag & PL_FORMAL) {
register struct type *tp = pl->pl_type;
while (tp && tp->tp_fund != FUNCTION)
tp = tp->tp_up;
if (tp)
remove_proto_idfs(tp->tp_proto);
debug("remove_proto_idfs(tp->tp_proto)");
}
#endif
def = pl->pl_idf->id_def;
if (def && def->df_level <= L_PROTO){
pl->pl_idf->id_def = def->next;
@ -299,6 +398,9 @@ remove_proto_idfs(pl)
}
pl->pl_idf = (struct idf *) 0;
}
if (pl->pl_type) {
remove_proto_tag(pl->pl_type);
}
pl = pl->next;
}
}
@ -316,7 +418,7 @@ call_proto(expp)
register struct expr *left = (*expp)->OP_LEFT;
register struct expr *right = (*expp)->OP_RIGHT;
register struct proto *pl = NO_PROTO;
static struct proto ellipsis = { 0, 0, 0, ELLIPSIS };
static struct proto ellipsis = { 0, 0, 0, PL_ELLIPSIS };
if (left != NILEXPR) { /* in case of an error */
register struct type *tp = left->ex_type;
@ -333,18 +435,6 @@ call_proto(expp)
struct expr **estack[NPARAMS];
struct proto *pstack[NPARAMS];
if (pl == NO_PROTO) {
register struct idf *idf;
if (left->ex_class != Value || left->VL_CLASS != Name) {
strict("no prototype supplied");
}
else if (! (idf = left->VL_IDF)->id_proto) {
strict("'%s' no prototype supplied", idf->id_text);
idf->id_proto++;
}
}
/* stack up the parameter expressions */
while (ex->ex_class == Oper && ex->OP_OPER == PARCOMMA) {
if (ecnt == STDC_NPARAMS)
@ -362,7 +452,7 @@ call_proto(expp)
/* Declarations like int f(void) do not expect any
parameters.
*/
if (pl && pl->pl_flag == VOID) {
if (pl && pl->pl_flag & PL_VOID) {
strict("no parameters expected");
pl = NO_PROTO;
}
@ -391,17 +481,17 @@ call_proto(expp)
error("more parameters than specified in prototype");
break;
}
else if (pstack[pcnt]->pl_flag != ELLIPSIS) {
else if (!(pstack[pcnt]->pl_flag & PL_ELLIPSIS)) {
ch7cast(estack[ecnt],CASTAB,pstack[pcnt]->pl_type);
pcnt--;
} else
any2parameter(estack[ecnt]);
}
if (pcnt >= 0 && pstack[0]->pl_flag != ELLIPSIS)
if (pcnt >= 0 && !(pstack[0]->pl_flag & PL_ELLIPSIS))
error("less parameters than specified in prototype");
} else {
if (pl && pl->pl_flag != VOID)
if (pl && !(pl->pl_flag & PL_VOID))
error("less parameters than specified in prototype");
}
}

View file

@ -9,9 +9,14 @@ struct proto {
struct proto *next;
struct type *pl_type; /* parameter type */
struct idf *pl_idf; /* parameter identifier */
short pl_flag; /* ELLIPSIS or FORMAL */
short pl_flag; /* see define's */
};
#define NO_PROTO ((struct proto *)0)
#define NO_PROTO ((struct proto *)0)
#define PL_VOID 0x01
#define PL_FORMAL 0x02
#define PL_ELLIPSIS 0x04
#define PL_ERRGIVEN 0x08
/* ALLOCDEF "proto" 10 */

View file

@ -27,7 +27,9 @@
#include "argbuf.h"
#include "replace.h"
struct repl *ReplaceList; /* list of currently active macros */
extern struct idf *GetIdentifier();
extern int InputLevel;
struct repl *ReplaceList; /* list of currently active macros */
int
replace(idf)
@ -38,15 +40,23 @@ replace(idf)
higher interface to the real thing: expand_macro().
*/
struct repl *repl;
int size;
if (!(idf->id_macro)) return 0;
if (idf->id_macro->mc_flag & NOREPLACE){
return 0;
}
repl = new_repl();
repl->r_ptr = repl->r_text;
repl->r_args = new_args();
if (!expand_macro(repl, idf, (struct idf *)0))
repl->r_idf = idf;
/* repl->r_level = InputLevel; /* ?? temporary */
if (!expand_macro(repl, idf)) {
return 0;
free_args(repl->r_args);
}
InputLevel++;
InsertText(repl->r_text, repl->r_ptr - repl->r_text);
repl->r_level = InputLevel;
idf->id_macro->mc_flag |= NOREPLACE;
repl->next = ReplaceList;
ReplaceList = repl;
return 1;
@ -54,24 +64,33 @@ replace(idf)
unstackrepl()
{
struct repl *repl = ReplaceList;
#ifdef PERSONAL_TOUCH
if (repl == NO_REPL) {
print("Leendert, you don't understand the principle yet\n");
return;
}
#else
ASSERT(repl != NO_REPL);
#endif
ReplaceList = repl->next;
free_repl(repl);
Unstacked++;
}
expand_macro(repl, idf, previdf)
EnableMacros()
{
register struct repl *r = ReplaceList, *prev = 0;
ASSERT(Unstacked > 0);
while(r) {
struct repl *nxt = r->next;
if (r->r_level > InputLevel) {
r->r_idf->id_macro->mc_flag &= ~NOREPLACE;
if (!prev) ReplaceList = nxt;
else prev->next = nxt;
free_args(r->r_args);
free_repl(r);
}
else prev = r;
r = nxt;
}
Unstacked = 0;
}
expand_macro(repl, idf)
register struct repl *repl;
register struct idf *idf;
struct idf *previdf;
{
/* expand_macro() does the actual macro replacement.
"idf" is a description of the identifier which
@ -85,6 +104,10 @@ expand_macro(repl, idf, previdf)
ment list associated with "idf" is expanded.
expand_macro() returns 1 if the replacement succeeded
and 0 if some error occurred.
A special case is "defined". This acts as a unary operator
on a single, unexpanded identifier, which may be surrounded
by parenthesis. The function expand_defined handles this.
*/
register struct macro *mac = idf->id_macro;
struct args *args = repl->r_args;
@ -94,44 +117,37 @@ expand_macro(repl, idf, previdf)
if (mac->mc_flag & FUNC) {
/* the following assertion won't compile:
ASSERT(!strcmp("defined", idf->id_text));
expand the assert macro by hand (??? dirty, temporary)
*/
#ifdef DEBUG
if (strcmp("defined", idf->id_text))
crash("in %s, %u: assertion %s failed",
__FILE__, __LINE__ - 2,
"strcmp(\"defined\", idf->id_text)");
#endif
if (!AccDefined) return 0;
expand_defined(repl);
return 1;
}
ch = GetChar();
ch = skipspaces(ch,1);
if (ch != '(') { /* no replacement if no () */
/* This is obscure. See the examples for the replace
algorithm in section 3`.8.3.5.
/* This is obscure. See the examples for the
replace algorithm in section 3`.8.3.5.
lexwarning("macro %s needs arguments", idf->id_text);
*/
UnGetChar();
return 0;
} else
getactuals(args, idf);
getactuals(repl, idf);
if (mac->mc_flag & FUNC) {
struct idf *param = str2idf(args->a_rawbuf);
*repl->r_ptr++ = param->id_macro ? '1' : '0';
*repl->r_ptr = '\0';
return 1;
}
}
if (mac->mc_flag & FUNC) /* this macro leads to special action */
macro_func(idf);
if (mac->mc_nps == -1) {
register int size = mac->mc_length;
register char *text = mac->mc_text;
ASSERT((repl->r_ptr+size) < &(repl->r_text[LAPBUF]));
while (size-- > 0)
*repl->r_ptr++ = *text++;
*repl->r_ptr = '\0';
} else
macro2buffer(repl, idf, args);
macro2buffer(repl, idf, args);
/* According to the ANSI definition:
@ -143,23 +159,56 @@ expand_macro(repl, idf, previdf)
character based, we have a problem.
For now: just insert a space after all tokens,
until ANSI fixes this flaw.
^^^^^^^^^^^^^^^^^^^^^^^^^^ tsk tsk tsk
*/
*repl->r_ptr++ = ' ';
if (*repl->r_ptr != TOKSEP) *repl->r_ptr++ = TOKSEP;
*repl->r_ptr = '\0';
if (idf != previdf)
maccount(repl, idf);
return 1;
}
getactuals(args, idf)
register struct args *args;
expand_defined(repl)
register struct repl *repl;
{
register int ch = GetChar();
struct idf *id;
int parens = 0;
ch = skipspaces(ch, 0);
if (ch == '(') {
parens++;
ch = GetChar();
ch = skipspaces(ch, 0);
}
if ((class(ch) != STIDF) && (class(ch) != STELL)) {
error("identifier missing");
if (parens && ch != ')') error(") missing");
if (!parens || ch != ')') UnGetChar();
*repl->r_ptr++ = '0';
*repl->r_ptr = '\0';
return;
}
UnGetChar();
id = GetIdentifier(0);
ASSERT(id || class(ch) == STELL);
ch = GetChar();
ch = skipspaces(ch, 0);
if (parens && ch != ')') error(") missing");
if (!parens || ch != ')') UnGetChar();
*repl->r_ptr++ = (id && id->id_macro) ? '1' : '0';
*repl->r_ptr = '\0';
}
getactuals(repl, idf)
struct repl* repl;
register struct idf *idf;
{
/* Get the actual parameters from the input stream.
The hard part is done by actual(), only comma's and
other syntactic trivialities are checked here.
*/
register struct args *args = repl->r_args;
register int nps = idf->id_macro->mc_nps;
register int argcnt;
register int ch;
@ -169,12 +218,12 @@ getactuals(args, idf)
args->a_rawvec[0] = args->a_rawptr = &args->a_rawbuf[0];
if ((ch = GetChar()) != ')') {
PushBack();
while ((ch = actual(args, idf)) != ')' ) {
while ((ch = actual(repl)) != ')' ) {
if (ch != ',') {
lexerror("illegal macro call");
return;
}
stash(args, '\0');
stash(repl, '\0', 1);
++argcnt;
args->a_expvec[argcnt] = args->a_expptr;
args->a_rawvec[argcnt] = args->a_rawptr;
@ -183,30 +232,73 @@ getactuals(args, idf)
if (argcnt >= NPARAMS)
fatal("argument vector overflow");
}
stash(args, '\0');
stash(repl, '\0', 1);
++argcnt;
}
if (argcnt < nps)
lexerror("too few macro arguments");
if (argcnt > nps)
else if (argcnt > nps)
lexerror("too many macro arguments");
}
saveraw(repl)
struct repl *repl;
{
register struct repl *nrepl = ReplaceList;
register struct args *ap = nrepl->r_args;
struct args *args = repl->r_args;
register char *p;
/* stash identifier name */
for (p = nrepl->r_idf->id_text; *p != '\0'; p++)
*args->a_rawptr++ = *p;
/* The following code deals with expanded function
like macro calls. It makes the following code
work:
#define def(a,b) x(a,b)
#define glue(a,b) a ## b
glue(abc,def(a,b))
Results in:
abcdef(a,b);
*/
if (ap->a_rawvec[0]) {
/* stash arguments */
register int i;
*args->a_rawptr++ = '(';
for (i = 0; ap->a_rawvec[i] != (char *)0; i++) {
for (p = ap->a_rawvec[i]; *p != '\0'; p++)
*args->a_rawptr++ = *p;
*args->a_rawptr++ = ',';
}
*(args->a_rawptr-1) = ')'; /* delete last ',' */
}
}
int
actual(args, idf)
register struct args *args;
register struct idf *idf;
actual(repl)
struct repl *repl;
{
/* This routine deals with the scanning of an actual parameter.
It keeps in account the openning and clossing brackets,
It keeps in account the opening and closing brackets,
preprocessor numbers, strings and character constants.
*/
register int ch;
register int level = 0;
register int level = 0, nostashraw = 0;
while (1) {
ch = GetChar();
if (Unstacked) {
nostashraw -= Unstacked;
if (nostashraw < 0) nostashraw = 0;
EnableMacros();
}
if (class(ch) == STIDF || class(ch) == STELL) {
/* Scan a preprocessor identifier token. If the
token is a macro, it is expanded first.
@ -217,7 +309,12 @@ actual(args, idf)
register int pos = -1;
register int hash;
extern int idfsize;
int size;
int NoExpandMacro;
if (ch == NOEXPM) {
NoExpandMacro= 1;
ch = GetChar();
} else NoExpandMacro = 0;
hash = STARTHASH();
do {
@ -235,47 +332,62 @@ actual(args, idf)
replacement list, it's expanded.
*/
idef = idf_hashed(buf, p - buf, hash);
if (idef->id_macro) /* expand macro identifier */
expand_actual(args, idef, idf);
else
if (NoExpandMacro || !replace(idef)) {
if ((idef->id_macro
&& (idef->id_macro->mc_flag & NOREPLACE))
|| NoExpandMacro)
stash(repl, NOEXPM, !nostashraw);
for (p = buf; *p != '\0'; p++)
stash(args, *p);
} else if (class(ch) == STNUM || class(ch) == '.') {
/* preprocessor number token. No this is no joke,
the commitee decided (in all it's wisdom) that
a preprocessing number has the following regular
expression:
[0-9"."]{[0-9"."a-zA-Z_]|{[Ee][+-]}}*
stash(repl, *p, !nostashraw);
} else {
if (!nostashraw) saveraw(repl);
nostashraw++;
}
} else if (class(ch) == STNUM) {
/* a preprocessing number has the following
regular expression:
[0-9|"."[0-9]]{[0-9"."a-zA-Z_]|{[Ee][+-]}}*
*/
do {
stash(args, ch);
stash(repl, ch, !nostashraw);
if (ch == '.') {
ch = GetChar();
if (class(ch) != STNUM) {
UnGetChar();
continue;
}
else stash(repl, ch, !nostashraw);
}
ch = GetChar();
while (in_idf(ch) || ch == '.') {
stash(repl, ch, !nostashraw);
if ((ch = GetChar()) == 'e' || ch == 'E') {
stash(repl, ch, !nostashraw);
ch = GetChar();
if (ch == '+' || ch == '-') {
stash(args, ch);
stash(repl, ch, !nostashraw);
ch = GetChar();
}
}
} while (class(ch) == STNUM || class(ch) == STIDF ||
class(ch) == STELL || ch == '.');
}
UnGetChar();
} else if (ch == '(' || ch == '[' || ch == '{') {
/* a comma may occur within these constructions */
level++;
stash(args, ch);
stash(repl, ch, !nostashraw);
} else if (ch == ')' || ch == ']' || ch == '}') {
level--;
/* clossing parenthesis of macro call */
if (ch == ')' && level < 0)
return ')';
stash(args, ch);
stash(repl, ch, !nostashraw);
} else if (ch == ',') {
if (level <= 0) { /* comma separator for next argument */
if (level)
lexerror("unbalanced parenthesis");
return ',';
if (!nostashraw)
return ','; /* ??? */
}
stash(args, ch);
stash(repl, ch, !nostashraw);
} else if (ch == '\n') {
/* newlines are accepted as white spaces */
LineNumber++;
@ -294,16 +406,20 @@ actual(args, idf)
*/
if (ch == '#')
domacro();
else if (ch == EOI) {
lexerror("unterminated macro call");
return ')';
}
UnGetChar();
stash(args, ' ');
stash(repl, ' ', !nostashraw);
} else if (ch == '/') {
/* comments are treated as one white space token */
if ((ch = GetChar()) == '*') {
if ((ch = GetChar()) == '*' && !InputLevel) {
skipcomment();
stash(args, ' ');
stash(repl, ' ', !nostashraw);
} else {
UnGetChar();
stash(args, '/');
stash(repl, '/', !nostashraw);
}
} else if (ch == '\'' || ch == '"') {
/* Strings are considered as ONE token, thus no
@ -311,129 +427,28 @@ actual(args, idf)
*/
register int match = ch;
stash(args, ch);
stash(repl, ch, !nostashraw);
while ((ch = GetChar()) != EOI) {
if (ch == match)
break;
if (ch == '\\') {
stash(args, ch);
stash(repl, ch, !nostashraw);
ch = GetChar();
} else if (ch == '\n') {
lexerror("newline in string");
LineNumber++;
stash(args, match);
stash(repl, match, !nostashraw);
break;
}
stash(args, ch);
stash(repl, ch, !nostashraw);
}
if (ch != match) {
lexerror("unterminated macro call");
return ')';
}
stash(args, ch);
stash(repl, ch, !nostashraw);
} else
stash(args, ch);
}
}
expand_actual(args, idef, idf)
register struct args *args;
register struct idf *idf, *idef;
{
struct repl *nrepl = new_repl();
register char *p;
nrepl->r_args = new_args();
nrepl->r_ptr = nrepl->r_text;
if (expand_macro(nrepl, idef, idf)) {
register struct args *ap = nrepl->r_args;
for (p = nrepl->r_text; p < nrepl->r_ptr; p++)
*args->a_expptr++ = *p;
/* stash idef name */
for (p = idef->id_text; *p != '\0'; p++)
*args->a_rawptr++ = *p;
/* The following code deals with expanded function
like macro calls. It makes the following code
work:
#define def(a,b) x(a,b)
#define glue(a,b) a ## b
glue(abc,def(a,b))
Results in:
abcdef(a,b);
*/
if (ap->a_rawvec[0]) {
/* stash arguments */
register int i;
*args->a_rawptr++ = '(';
for (i = 0; ap->a_rawvec[i] != (char *)0; i++) {
for (p = ap->a_rawvec[i]; *p != '\0'; p++)
*args->a_rawptr++ = *p;
*args->a_rawptr++ = ',';
}
*--args->a_rawptr = ')';
++args->a_rawptr; /* one too far */
}
} else /* something happened during the macro expansion */
for (p = idef->id_text; *p != '\0'; p++)
stash(args, *p);
free_args(nrepl->r_args);
free_repl(nrepl);
}
maccount(repl, idf)
register struct repl *repl;
register struct idf *idf;
{
/* To prevent re-expansion of already expanded macro's we count
the occurrences of the currently expanded macro name in the
replacement list. This is mainly to prevent recursion as in:
#define f(a) f(2 * (a))
f(y+1);
This results in:
f(2*(y+1));
When reading the inserted text we decrement the count of a
macro name until it's zero. Then we start expanding it again.
*/
register char *text = repl->r_text;
register int pos = -1;
extern int idfsize;
while (*text != '\0') {
if (*text == '\'' || *text == '"') {
register int delim;
for (delim = *text++; *text != delim; text++)
if (*text == '\\')
text++;
text++;
} else
if (class(*text) == STIDF || class(*text) == STELL) {
char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
register char *p = buf;
do {
if (++pos < idfsize)
*p++ = *text;
text++;
} while (in_idf(*text));
*p++ = '\0';
if (!strcmp(idf->id_text, buf))
idf->id_macro->mc_count++;
} else
text++;
stash(repl, ch, !nostashraw);
}
}
@ -459,7 +474,7 @@ macro_func(idef)
break;
case 'L': /* __LINE__ */
mac->mc_text = long2str((long)LineNumber, 10);
mac->mc_length = 1;
mac->mc_length = strlen(mac->mc_text);
break;
default:
crash("(macro_func)");
@ -499,98 +514,124 @@ macro2buffer(repl, idf, args)
smarter should be done (but even a DFA is O(|s|)).
*/
register char *ptr = idf->id_macro->mc_text;
register char *tmpptr;
int err = 0;
char *stringify();
while (*ptr) {
ASSERT(repl->r_ptr < &(repl->r_text[LAPBUF]));
if (*ptr == '\'' || *ptr == '"') {
register int delim = *ptr;
ASSERT(repl->r_ptr < &(repl->r_text[LAPBUF]));
if (*ptr == '\'' || *ptr == '"') {
register int delim = *ptr;
do {
*repl->r_ptr++ = *ptr;
if (*ptr == '\\')
*repl->r_ptr++ = *++ptr;
if (*ptr == '\0') {
lexerror("unterminated string");
*repl->r_ptr = '\0';
return;
}
ptr++;
} while (*ptr != delim || *ptr == '\0');
*repl->r_ptr++ = *ptr++;
} else if (*ptr == '#') {
if (*++ptr == '#') {
/* ## - paste operator */
ptr++;
do {
*repl->r_ptr++ = *ptr;
if (*ptr == '\\')
*repl->r_ptr++ = *++ptr;
if (*ptr == '\0') {
lexerror("unterminated string");
*repl->r_ptr = '\0';
return;
}
ptr++;
} while (*ptr != delim || *ptr == '\0');
*repl->r_ptr++ = *ptr++;
} else if (*ptr == '#') {
if (*++ptr == '#') {
/* ## - paste operator */
ptr++;
/* trim the actual replacement list */
--repl->r_ptr;
while (is_wsp(*repl->r_ptr) &&
repl->r_ptr >= repl->r_text)
--repl->r_ptr;
/* trim the actual replacement list */
--repl->r_ptr;
while (is_wsp(*repl->r_ptr)
&& repl->r_ptr >= repl->r_text)
--repl->r_ptr;
/* ## occurred at the beginning of the
replacement list.
*/
if (repl->r_ptr == repl->r_text)
goto paste;
++repl->r_ptr;
/* ## occurred at the beginning of the
replacement list.
*/
if (repl->r_ptr == repl->r_text
&& is_wsp(*repl->r_ptr)) {
err = 1;
break;
}
/* skip space in macro replacement list */
while ((*ptr & FORMALP) == 0 && is_wsp(*ptr))
ptr++;
while(*repl->r_ptr == TOKSEP
&& repl->r_ptr >= repl->r_text)
--repl->r_ptr;
/* ## occurred at the end of the
replacement list.
*/
if (*ptr & FORMALP) {
register int n = *ptr++ & 0177;
register char *p;
ASSERT(n != 0);
p = args->a_rawvec[n-1];
while (is_wsp(*p))
p++;
while (*p)
*repl->r_ptr++ = *p++;
} else if (*ptr == '\0')
goto paste;
} else
ptr = stringify(repl, ptr, args);
} else if (*ptr & FORMALP) {
/* insert actual parameter */
tmpptr = repl->r_ptr;
++repl->r_ptr;
/* skip space in macro replacement list */
while ((*ptr & FORMALP) == 0 && is_wsp(*ptr))
ptr++;
/* ## occurred at the end of the replacement list.
*/
if (*ptr & FORMALP) {
register int n = *ptr++ & 0177;
register char *p, *q;
ASSERT(n != 0);
register char *p;
/* This is VERY dirty, we look ahead for the
## operater. If it's found we use the raw
argument buffer instead of the expanded
one.
*/
for (p = ptr; (*p & FORMALP) == 0 && is_wsp(*p); p++)
/* VOID */;
if (*p == '#' && p[1] == '#')
q = args->a_rawvec[n-1];
else
q = args->a_expvec[n-1];
while (*q)
*repl->r_ptr++ = *q++;
*repl->r_ptr++ = ' ';
ASSERT(n > 0);
p = args->a_rawvec[n-1];
if (p) { /* else macro argument missing */
while (is_wsp(*p))
p++;
if (*p == NOEXPM) p++;
while (*p)
*repl->r_ptr++ = *p++;
}
if (in_idf(*tmpptr + 1)) {
while (in_idf(*tmpptr)
&& tmpptr >= repl->r_text)
tmpptr--;
if (*tmpptr == NOEXPM) *tmpptr = TOKSEP;
}
} else if (*ptr == '\0') {
err = 1;
break;
} else {
if (in_idf(*ptr)) {
while (in_idf(*tmpptr)
&& tmpptr >= repl->r_text)
tmpptr--;
if (*tmpptr == NOEXPM) *tmpptr = TOKSEP;
}
}
} else
*repl->r_ptr++ = *ptr++;
ptr = stringify(repl, ptr, args);
} else if (*ptr & FORMALP) {
/* insert actual parameter */
register int n = *ptr++ & 0177;
register char *p, *q;
ASSERT(n > 0);
/* This is VERY dirty, we look ahead for the
## operater. If it's found we use the raw
argument buffer instead of the expanded
one.
*/
for (p = ptr; (*p & FORMALP) == 0 && is_wsp(*p); p++)
/* EMPTY */;
if (*p == '#' && p[1] == '#')
q = args->a_rawvec[n-1];
else
q = args->a_expvec[n-1];
p = repl->r_ptr;
if (q) /* else macro argument missing */
while (*q)
*repl->r_ptr++ = *q++;
if (*repl->r_ptr != TOKSEP)
*repl->r_ptr++ = TOKSEP;
} else
*repl->r_ptr++ = *ptr++;
}
*repl->r_ptr = '\0';
return;
paste:
/* Sorry, i know this looks a bit like
a unix device driver code.
*/
lexerror("illegal use of the ## operator");
if (err)
lexerror("illegal use of the ## operator");
return;
}
@ -625,7 +666,7 @@ stringify(repl, ptr, args)
register char *p;
ASSERT(n != 0);
p = args->a_expvec[n-1];
p = args->a_rawvec[n-1];
*repl->r_ptr++ = '"';
while (*p) {
if (is_wsp(*p)) {
@ -645,7 +686,8 @@ stringify(repl, ptr, args)
backslash = *p == '\\';
if (*p == '"' || (delim && *p == '\\'))
*repl->r_ptr++ = '\\';
*repl->r_ptr++ = *p++;
if (*p == TOKSEP || *p == NOEXPM) p++;
else *repl->r_ptr++ = *p++;
}
/* trim spaces in the replacement list */
@ -658,20 +700,23 @@ stringify(repl, ptr, args)
return ptr;
}
stash(args, ch)
register struct args *args;
stash(repl, ch, stashraw)
struct repl *repl;
register int ch;
int stashraw;
{
/* Stash characters into the macro expansion buffer.
*/
register struct args *args = repl->r_args;
if (args->a_expptr >= &(args->a_expbuf[ARGBUF]))
fatal("macro argument buffer overflow");
*args->a_expptr++ = ch;
if (args->a_rawptr >= &(args->a_rawbuf[ARGBUF]))
fatal("raw macro argument buffer overflow");
*args->a_rawptr++ = ch;
if (stashraw) {
if (args->a_rawptr >= &(args->a_rawbuf[ARGBUF]))
fatal("raw macro argument buffer overflow");
*args->a_rawptr++ = ch;
}
}
#endif NOPP

View file

@ -1,8 +1,10 @@
struct repl {
struct repl *next;
struct idf *r_idf; /* name of the macro */
struct args *r_args; /* replacement parameters */
char r_text[LAPBUF]; /* replacement text */
int r_level; /* level of insertion */
char *r_ptr; /* replacement text pointer */
char r_text[LAPBUF]; /* replacement text */
};
/* ALLOCDEF "repl" 4 */

View file

@ -166,7 +166,7 @@ copyact(ch1, ch2, lvl)
case '/':
LoadChar(ch);
if (ch == '*') { /* skip comment */
if (ch == '*' && !InputLevel) { /* skip comment */
skipcomment();
continue;
}

View file

@ -5,16 +5,13 @@
/* $Header$ */
/* VARIOUS TARGET MACHINE SIZE DESCRIPTORS */
#include "nofloat.h"
#include "nocross.h"
#include "target_sizes.h"
#ifndef NOCROSS
extern arith
short_size, word_size, dword_size, int_size, long_size,
#ifndef NOFLOAT
float_size, double_size, lngdbl_size,
#endif NOFLOAT
pointer_size;
#else NOCROSS
#define short_size (SZ_SHORT)
@ -22,11 +19,9 @@ extern arith
#define dword_size (2*SZ_WORD)
#define int_size (SZ_INT)
#define long_size (SZ_LONG)
#ifndef NOFLOAT
#define float_size (SZ_FLOAT)
#define double_size (SZ_DOUBLE)
#define lngdbl_size (SZ_LNGDBL)
#endif NOFLOAT
#define pointer_size (SZ_POINTER)
#endif NOCROSS

View file

@ -12,6 +12,8 @@
#include "input.h"
#ifndef NOPP
extern int InputLevel;
int
skipspaces(ch, skipnl)
register int ch;
@ -19,12 +21,19 @@ skipspaces(ch, skipnl)
/* skipspaces() skips any white space and returns the first
non-space character.
*/
register int nlseen = 0;
for (;;) {
while (class(ch) == STSKIP)
ch = GetChar();
if (skipnl && class(ch) == STNL) {
ch = GetChar();
++LineNumber;
LineNumber++;
nlseen++;
continue;
}
if (ch == TOKSEP && InputLevel) {
ch = GetChar();
continue;
}
@ -32,7 +41,7 @@ skipspaces(ch, skipnl)
if (ch == '/') {
ch = GetChar();
if (ch == '*') {
if (ch == '*' && !InputLevel) {
skipcomment();
ch = GetChar();
}
@ -41,7 +50,10 @@ skipspaces(ch, skipnl)
return '/';
}
}
else
else if(nlseen && ch == '#') {
domacro();
ch = GetChar();
} else
return ch;
}
}
@ -53,10 +65,9 @@ SkipToNewLine(garbage)
register int ch;
register int pstrict = 0;
UnGetChar();
while ((ch = GetChar()) != '\n') {
if (ch == '/') {
if ((ch = GetChar()) == '*') {
if ((ch = GetChar()) == '*' && !InputLevel) {
skipcomment();
continue;
}

View file

@ -6,7 +6,6 @@
/* S T A C K / U N S T A C K R O U T I N E S */
#include "lint.h"
#include "nofloat.h"
#include <system.h>
#include <em.h>
#include "debug.h"
@ -21,7 +20,6 @@
#include "struct.h"
#include "level.h"
#include "mes.h"
#include "noRoption.h"
/* #include <em_reg.h> */
@ -84,8 +82,9 @@ stack_level_of(lvl)
return local_level;
stl = &UniversalLevel;
while (stl->sl_level != lvl)
while (stl->sl_level != lvl) {
stl = stl->sl_next;
}
return stl;
}
@ -214,25 +213,18 @@ unstack_world()
def->df_sc = EXTERN;
*/
if ( def->df_sc == STATIC
&& def->df_type->tp_fund == FUNCTION
&& !def->df_initialized
) {
if (def->df_sc == STATIC
&& def->df_type->tp_fund == FUNCTION
&& !def->df_initialized) {
/* orphaned static function */
#ifndef NOROPTION
if (options['R'])
warning("static function %s never defined, %s",
idf->id_text,
"changed to extern"
);
#endif
warning("static function %s never defined, %s"
, idf->id_text
, "changed to extern");
def->df_sc = EXTERN;
}
if (
def->df_alloc == ALLOC_SEEN &&
!def->df_initialized
) {
if (def->df_alloc == ALLOC_SEEN
&& !def->df_initialized) {
/* space must be allocated */
bss(idf);
if (def->df_sc != STATIC)

View file

@ -12,6 +12,7 @@
#include "debug.h"
#include "botch_free.h"
#include <flt_arith.h>
#include "arith.h"
#include "LLlex.h"
#include "type.h"
@ -29,12 +30,12 @@
extern int level;
}
/* Each statement construction is stacked in order to trace a
statement to such a construction. Example: a case statement should
be recognized as a piece of the most enclosing switch statement.
*/
/* Each statement construction is stacked in order to trace a
* statement to such a construction. Example: a case statement should
* be recognized as a piece of the most enclosing switch statement.
*/
/* 9 */
/* 3.6 */
statement
{
#ifdef LINT
@ -104,9 +105,9 @@ expression_statement
}
;
/* 3.6.1 (partially) */
label
{ struct idf *idf;
}
{ struct idf *idf; }
:
identifier(&idf)
{
@ -125,6 +126,7 @@ label
}
;
/* 3.6.4.1 */
if_statement
{
struct expr *expr;
@ -186,6 +188,7 @@ if_statement
]
;
/* 3.6.5.3 */
while_statement
{
struct expr *expr;
@ -233,6 +236,7 @@ while_statement
}
;
/* 3.6.5.2 */
do_statement
{ struct expr *expr;
label l_break = text_label();
@ -279,6 +283,7 @@ do_statement
}
;
/* 3.6.5.3 */
for_statement
{ struct expr *e_init = 0, *e_test = 0, *e_incr = 0;
label l_break = text_label();
@ -350,6 +355,7 @@ for_statement
}
;
/* 3.6.4.2 */
switch_statement
{
struct expr *expr;
@ -375,6 +381,7 @@ switch_statement
}
;
/* 3.6.1 (partially) */
case_statement
{
struct expr *expr;
@ -393,6 +400,7 @@ case_statement
statement
;
/* 3.6.1 (partially) */
default_statement
:
DEFAULT
@ -406,6 +414,7 @@ default_statement
statement
;
/* 3.6.6.4 */
return_statement
{ struct expr *expr = 0;
}
@ -436,6 +445,7 @@ return_statement
';'
;
/* 3.6.6.1 (partially) */
jump
{ struct idf *idf;
}
@ -452,6 +462,7 @@ jump
}
;
/* 3.6.2 */
compound_statement:
'{'
{

View file

@ -23,7 +23,6 @@
#include "level.h"
#include "assert.h"
#include "sizes.h"
#include "noRoption.h"
/* Type of previous selector declared with a field width specified,
if any. If a selector is declared with no field with it is set to 0.
@ -78,14 +77,6 @@ add_sel(stp, tp, idf, sdefpp, szp, fd) /* this is horrible */
register struct sdef *newsdef;
int lvl = tg->tg_level;
#ifndef NOROPTION
if (options['R'] && !is_anon_idf(idf)) {
/* a K & R test */
if (idf->id_struct && idf->id_struct->tg_level == level)
warning("%s is also a struct/union tag", idf->id_text);
}
#endif
if (stp->tp_fund == STRUCT) {
#ifndef NOBITFIELD
if (fd == 0) { /* no field width specified */
@ -105,24 +96,11 @@ add_sel(stp, tp, idf, sdefpp, szp, fd) /* this is horrible */
#endif NOBITFIELD
}
else { /* (stp->tp_fund == UNION) */
if (fd) {
error("fields not allowed in unions");
free_field(fd);
fd = 0;
}
if (fd) offset = add_field(szp, fd, &tp, idf, stp);
offset = (arith)0;
}
check_selector(idf, stp);
#ifndef NOROPTION
if (options['R']) {
if ( sdef && sdef->sd_level == lvl &&
( sdef->sd_offset != offset ||
!equal_type(sdef->sd_type, tp))
) /* RM 8.5 */
warning("selector %s redeclared", idf->id_text);
}
#endif
newsdef = new_sdef();
newsdef->sd_sdef = (struct sdef *) 0;
@ -159,7 +137,10 @@ add_sel(stp, tp, idf, sdefpp, szp, fd) /* this is horrible */
stp->tp_align = lcm(stp->tp_align, tp->tp_align);
}
else
if (stp->tp_fund == UNION) {
if (stp->tp_fund == UNION && fd == 0) {
/* Note: the case that a bitfield is declared is
handled by add_field() !
*/
arith sel_size = size_of_type(tp, "member");
if (*szp < sel_size)
@ -198,47 +179,29 @@ declare_struct(fund, idf, tpp)
register struct tag **tgp;
register struct tag *tg;
if (!idf)
idf = gen_idf();
tgp = (fund == ENUM ? &idf->id_enum : &idf->id_struct);
#ifndef NOROPTION
if (options['R'] && !is_anon_idf(idf)) {
/* a K & R test */
if ( fund != ENUM &&
idf->id_sdef && idf->id_sdef->sd_level == level
) {
warning("%s is also a selector", idf->id_text);
}
if ( fund == ENUM &&
idf->id_def && idf->id_def->df_level == level
) {
warning("%s is also a variable", idf->id_text);
}
}
#endif
tg = *tgp;
if (tg && tg->tg_type->tp_size < 0 && tg->tg_type->tp_fund == fund) {
/* An unfinished declaration has preceded it, possibly on
an earlier level. We just fill in the answer.
*/
if (tg
&& tg->tg_type->tp_size < 0
&& tg->tg_type->tp_fund == fund
&& tg->tg_level == level) {
/* An unfinished declaration has preceded it.
We just fill in the answer.
*/
if (tg->tg_busy) {
error("recursive declaration of struct/union %s",
idf->id_text);
declare_struct(fund, gen_idf(), tpp);
}
else {
#ifndef NOROPTION
if (options['R'] && tg->tg_level != level)
warning("%s declares %s in different range",
idf->id_text, symbol2str(fund));
#endif
/* hint: if (level <= L_PROTO) */
*tpp = tg->tg_type;
}
}
else
if (tg && tg->tg_level == level) {
else if (tg && tg->tg_level == level && tg->tg_type->tp_size >= 0) {
/* There is an already defined struct/union of this name
on our level!
*/
@ -307,15 +270,7 @@ idf2sdef(idf, tp)
/* Tp not met; any unique identification will do. */
if (sdef = idf->id_sdef) {
/* There is an identification */
if (uniq_selector(sdef)) {
/* and it is unique, so we accept */
warning("selector %s applied to alien type",
idf->id_text);
}
else {
/* it is ambiguous */
error("ambiguous use of selector %s", idf->id_text);
}
error("illegal use of selector %s", idf->id_text);
return sdef;
}
@ -328,6 +283,7 @@ idf2sdef(idf, tp)
return sdef;
}
#if 0
int
uniq_selector(idf_sdef)
register struct sdef *idf_sdef;
@ -352,6 +308,7 @@ uniq_selector(idf_sdef)
}
return 1;
}
#endif
#ifndef NOBITFIELD
arith
@ -365,8 +322,7 @@ add_field(szp, fd, fdtpp, idf, stp)
/* The address where this selector is put is returned. If the
selector with specified width does not fit in the word, or
an explicit alignment is given, a new address is needed.
Note that the fields are packed into machine words (according
to the RM.)
Note that the fields are packed into machine words.
*/
long bits_in_type = word_size * 8;
static int field_offset = (arith)0;
@ -392,9 +348,10 @@ add_field(szp, fd, fdtpp, idf, stp)
switch ((*fdtpp)->tp_fund) {
case CHAR:
case SHORT:
case INT:
case ENUM:
case LONG:
strict("non-portable field type");
case INT:
/* right type; size OK? */
if ((*fdtpp)->tp_size > word_size) {
error("bit field type %s does not fit in a word",
@ -461,6 +418,8 @@ add_field(szp, fd, fdtpp, idf, stp)
else /* adjust the field at the left */
fd->fd_shift = bits_in_type - bits_declared;
if (stp->tp_fund == UNION) bits_declared = (arith)0;
return field_offset;
}
#endif NOBITFIELD

View file

@ -5,7 +5,6 @@
/* $Header$ */
/* S W I T C H - S T A T E M E N T A D M I N I S T R A T I O N */
#include "nofloat.h"
#include <em.h>
#include "debug.h"
#include "botch_free.h"
@ -14,13 +13,14 @@
#include "Lpars.h"
#include "idf.h"
#include "label.h"
#include <flt_arith.h>
#include "arith.h"
#include "switch.h"
#include "code.h"
#include "assert.h"
#include "expr.h"
#include "type.h"
#include "noRoption.h"
#include "sizes.h"
extern char options[];
@ -39,9 +39,10 @@ compact(nr, low, up)
static struct switch_hdr *switch_stack = 0;
/* (EB 86.05.20) The following rules hold for switch statements:
- the expression E in "switch(E)" is cast to 'int' (RM 9.7)
- the expression E in "case E:" must be 'int' (RM 9.7)
- the values in the CSA/CSB tables are words (EM 7.4)
- the expression E in "switch(E)" shall have integral type (3.6.4.2)
- the expression E in "case E:" is converted to the promoted type
of the controlling expression
- the values in the CSA/CSB tables are words (EM 7.4) (??? JvE)
For simplicity, we suppose int_size == word_size.
*/
@ -54,22 +55,21 @@ code_startswitch(expp)
register label l_table = text_label();
register label l_break = text_label();
register struct switch_hdr *sh = new_switch_hdr();
int fund = any2arith(expp, SWITCH); /* INT, LONG or DOUBLE */
int fund = any2arith(expp, SWITCH);
/* INT, LONG, FLOAT, DOUBLE or LNGDBL */
switch (fund) {
case LONG:
#ifndef NOROPTION
if (options['R'])
warning("long in switch (cast to int)");
#endif
if (long_size > int_size)
warning("can't switch on longs (cast to int)");
int2int(expp, int_type);
break;
#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
error("float/double in switch");
case LNGDBL:
error("floating point type in switch");
erroneous2int(expp);
break;
#endif NOFLOAT
}
stack_stmt(l_break, NO_LABEL);
sh->sh_break = l_break;

View file

@ -5,7 +5,6 @@
/* $Header$ */
/* T Y P E D E F I N I T I O N M E C H A N I S M */
#include "nofloat.h"
#include "nobitfield.h"
#include "botch_free.h"
#include <alloc.h>
@ -28,14 +27,12 @@ extern struct type *field_of();
line parameters.
*/
struct type
*char_type, *uchar_type,
*schar_type, *uchar_type,
*short_type, *ushort_type,
*word_type, *uword_type,
*int_type, *uint_type,
*long_type, *ulong_type,
#ifndef NOFLOAT
*float_type, *double_type, *lngdbl_type,
#endif NOFLOAT
*void_type, *gen_type, *label_type,
*string_type, *funint_type, *error_type;
@ -56,6 +53,19 @@ create_type(fund)
return ntp;
}
struct type *
promoted_type(tp)
struct type *tp;
{
if (tp->tp_fund == CHAR || tp->tp_fund == SHORT) {
if (tp->tp_unsigned == UNSIGNED && tp->tp_size == int_size)
return uint_type;
else return int_type;
} else if (tp->tp_fund == FLOAT)
return double_type;
else return tp;
}
struct type *
construct_type(fund, tp, qual, count, pl)
register struct type *tp;
@ -123,8 +133,19 @@ function_of(tp, pl, qual)
register struct type *dtp = tp->tp_function;
/* look for a type with the right qualifier */
#if 0
/* the code doesn't work in the following case:
int func();
int func(int a, int b) { return q(a); }
because updating the type works inside the data-structures for that type
thus, a new type is created for very function. This may change in the
future, when declarations with empty parameter lists become obsolete.
*/
while (dtp && (dtp->tp_typequal != qual || dtp->tp_proto != pl))
dtp = dtp->next;
#else
dtp = 0;
#endif
if (!dtp) {
dtp = create_type(FUNCTION);

View file

@ -5,7 +5,6 @@
/* $Header$ */
/* TYPE DESCRIPTOR */
#include "nofloat.h"
#include "nobitfield.h"
struct type {
@ -23,6 +22,7 @@ struct type {
struct type *tp_pointer;/* to POINTER */
struct type *tp_array; /* to ARRAY */
struct proto *tp_proto; /* prototype list */
struct proto *tp_pseudoproto; /* pseudo prototype list */
struct type *tp_function;/* to FUNCTION */
};
@ -30,26 +30,24 @@ struct type {
/* Type qualifiers. Note: TQ_VOLATILE and TQ_CONST can be
'ored' to specify: extern const volatile int a;
*/
#define TQ_VOLATILE 01
#define TQ_CONST 02
#define TQ_VOLATILE 0x01
#define TQ_CONST 0x02
extern struct type
*create_type(), *standard_type(), *construct_type(), *pointer_to(),
*array_of(), *function_of();
*array_of(), *function_of(), *promoted_type();
#ifndef NOBITFIELD
extern struct type *field_of();
#endif NOBITFIELD
extern struct type
*char_type, *uchar_type,
*schar_type, *uchar_type,
*short_type, *ushort_type,
*word_type, *uword_type,
*int_type, *uint_type,
*long_type, *ulong_type,
#ifndef NOFLOAT
*float_type, *double_type, *lngdbl_type,
#endif NOFLOAT
*void_type, *gen_type, *label_type,
*string_type, *funint_type, *error_type;