#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 */
#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
#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 */
#include "lint.h"
#include <alloc.h>
-#include "nofloat.h"
#include "idfsize.h"
#include "numsize.h"
#include "debug.h"
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 */
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;
*/
PushLex()
{
- ASSERT(LexSP < 2);
+ ASSERT(LexSP < MAX_LL_DEPTH);
ASSERT(ASIDE == 0); /* ASIDE = 0; */
GetToken(&ahead);
LexStack[LexSP++] = dot;
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.
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;
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 */
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 '<':
'>', &(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();
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");
return ptok->tk_symb = INTEGER;
}
UnGetChar();
+ /* fallthrough */
case STIDF:
{
register char *tg = &buf[0];
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) {
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;
}
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();
-
- 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();
- }
+ } else ch = GetChar();
}
+ store('\0');
+ UnGetChar();
- /* 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();
+ 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;
}
-
- *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;
+ /* 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;
}
- 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);
}
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);
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();
}
lexerror("end-of-file inside %s", nm);
break;
}
- if (ch == '\\')
+ if (ch == '\\' && !AccFileSpecifier)
ch = quoted(GetChar());
str[pos++] = ch;
if (pos == str_size)
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;
+}
to it.
*/
-#include "nofloat.h"
#include "file_info.h"
#include "nopp.h"
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;
};
#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;
/* PARSER ERROR ADMINISTRATION */
#include <alloc.h>
-#include "nofloat.h"
#include "idf.h"
#include "arith.h"
#include "LLlex.h"
dot.tk_fund = INT;
dot.tk_ival = 1;
break;
-#ifndef NOFLOAT
case FLOATING:
dot.tk_fval = Salloc("0.0", 4);
break;
-#endif NOFLOAT
}
}
#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 */
#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
#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 */
# 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
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
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
# 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 \
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 \
# .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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
#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 */
#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
#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 */
/* $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
#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)
#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"
#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;
{
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);
int2float(e1p, float_type);
return;
}
-#endif NOFLOAT
/* Now they are INT or LONG */
u1 = (*e1p)->ex_type->tp_unsigned;
*/
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
*/
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");
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);
}
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),
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;
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);
return exp->ex_type->tp_fund;
}
-#ifndef NOFLOAT
int2float(expp, tp)
register struct expr **expp;
struct type *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);
else
*expp = arith2arith(tp, FLOAT2FLOAT, *expp);
}
-#endif NOFLOAT
array2pointer(exp)
register struct expr *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)
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",
{
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:
/* To handle default argument promotions
*/
any2opnd(expp, '(');
-#ifndef NOFLOAT
if ((*expp)->ex_type->tp_fund == FLOAT)
float2float(expp, double_type);
-#endif NOFLOAT
}
#ifndef NOBITFIELD
}
#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
#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)
* 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"
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
"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));
return;
}
}
- } /* oper == ARROW */
+ } else { /* oper == '.' */
+ /* nothing */
+ }
exp = *expp;
switch (tp->tp_fund) {
case POINTER: /* for int *p; p->next = ... */
*/
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) {
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;
}
}
}
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;
}
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;
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;
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) {
);
(*expp)->ex_type = tp; /* brute force */
}
+ if (oper == CAST) {
+ (*expp)->ex_flags |= EX_ILVALUE;
+ }
}
/* Determine whether two types are equal.
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) {
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:
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);
}
}
+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;
{
(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)
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
case INT:
case LONG:
case ENUM:
-#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
-#endif NOFLOAT
return 1;
#ifndef NOBITFIELD
case FIELD:
* 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();
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:
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) {
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,
(*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);
case ORAB:
opnd2integral(expp, oper);
opnd2integral(&expr, oper);
- /* Fall through */
+ /* fallthrough */
case '/':
case DIVAB:
case TIMESAB:
case '|':
opnd2integral(expp, oper);
opnd2integral(&expr, oper);
- /* Fall through */
+ /* fallthrough */
case '*':
arithbalance(expp, oper, &expr);
commutative_binop(expp, oper, expr);
expr = *expp;
*expp = etmp;
}
- /*FALLTHROUGH*/
+ /* fallthrough */
case PLUSAB:
case POSTINCR:
case PLUSPLUS:
ch7bin(expp, ',', expr);
}
}
- else
+ else {
*expp = new_oper(int_type, *expp, oper, expr);
+ }
(*expp)->ex_flags |= EX_LOGICAL;
break;
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) :
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)
* 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"
#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)
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 */
(*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
#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)) {
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)) {
);
}
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;
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) :
%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[] = {
% ISHEX
%
%C
-1:a-fA-F
+1:0-9a-fA-F
%Tchar ishex[] = {
%p
%T};
%p
%T};
%
-% ISSUF
-%
-%C
-1:lLuU
-%Tchar issuf[] = {
-%p
-%T};
-%
% ISWSP
%
%C
#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.
*/
#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
#include <alloc.h>
#include "dataflow.h"
#include "use_tmp.h"
+#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "idf.h"
#include "specials.h"
#include "atw.h"
#include "assert.h"
-#include "noRoption.h"
#include "file_info.h"
#ifdef LINT
#include "l_lint.h"
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;
/* 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);
DfaStartFunction(name);
#endif DATAFLOW
+
/* set global function info */
func_name = name;
if (def->df_type->tp_fund != FUNCTION) {
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);
/* 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;
}
}
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 */
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");
*/
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;
#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;
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);
}
}
#include "lint.h"
#ifndef LINT
-#include "nofloat.h"
#include <em.h>
#include "arith.h"
#include "type.h"
#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.
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);
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);
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);
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;
}
#include "target_sizes.h"
#include "idf.h"
+#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "label.h"
#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;
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
*/
}
}
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;
break;
if (uns) {
o1 >>= 1;
- o1 &= ~mach_long_sign;
+ o1 &= ~arith_sign;
o1 >>= (o2-1);
}
else
/* 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
/* 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
}
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;
}
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];
}
#include <alloc.h>
#include "nobitfield.h"
#include "debug.h"
+#include <flt_arith.h>
#include "arith.h"
#include "LLlex.h"
#include "label.h"
#endif LINT
}
-/* 8 */
+/* 3.5 */
declaration
{struct decspecs Ds;}
:
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
{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 ]
}
;
-/* 8.2 */
+/* 3.5.2 */
type_specifier(struct type **tpp;)
/* Used in struct/union declarations and in casts; only the
type is relevant.
enum_specifier(&ds->ds_type)
;
-/* 8.3 */
+/* 3.5 */
init_declarator_list(struct decspecs *ds;):
init_declarator(ds)
[ ',' init_declarator(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);
}
;
-/* 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)");
}
'='
{
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) {
#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);
}
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;
formal_list (struct formal **fmp;)
:
- formal(fmp) [ ',' formal(fmp) ]*
+ formal(fmp) [ %persistent ',' formal(fmp) ]*
;
formal(struct formal **fmp;)
(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
]
]
{ 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++;
}
:
parameter_decl(plp)
[ %while (AHEAD != ELLIPSIS)
+ %persistent
',' parameter_decl(plp)
]*
;
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);}
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)
'*' type_qualifier_list(qual)
;
-
/* Type qualifiers may come in three flavours:
volatile, const, const volatile.
These all have different semantic properties:
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) {
]
;
-
empty:
;
-
-/* 8.8 */
-/* included in the IDENTIFIER/TYPE_IDENTIFIER mechanism */
#include "botch_free.h"
#include <alloc.h>
+#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "proto.h"
/* $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"
#include "type.h"
#include "level.h"
#include "def.h"
-#include "noRoption.h"
extern char options[];
extern int level;
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;
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:
if (ds->ds_unsigned == SIGNED) {
switch (tp->tp_fund) {
case CHAR:
- tp = char_type;
+ tp = schar_type;
break;
case SHORT:
tp = short_type;
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:
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
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" */
the arguments.
*/
if (GetToken(&tk) != INTEGER) {
- lexerror("#line without linenumber");
+ error("bad #line syntax");
SkipToNewLine(0);
}
else
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
register int ch;
register int skiplevel = nestlevel; /* current nesting level */
struct token tk;
+ int toknum;
NoUnstack++;
for (;;) {
NoUnstack--;
return;
}
+ UnGetChar();
SkipToNewLine(0);
continue;
}
- if (GetToken(&tk) != IDENTIFIER) {
+ ReplaceMacros = 0;
+ toknum = GetToken(&tk);
+ ReplaceMacros = 1;
+ if (toknum != IDENTIFIER) {
SkipToNewLine(0);
continue;
}
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()) {
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);
NoUnstack--;
return;
}
+ else SkipToNewLine(0);
nestlevel--;
break;
}
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;
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);
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
if (class(ch) == STNL) {
/* Treat `#define something' as `#define something ""'
*/
- repl_text = "";
+ repl_text = Malloc(1);
+ *repl_text = '\0';
length = 0;
}
else {
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) {
{
push_if();
if (!ifexpr()) /* a false #if/#elif expression */
- skip_block();
+ skip_block(0);
}
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);
}
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()
/* 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 */
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();
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++] = ' ';
} 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];
-
- while (pos + id_size >= text_size)
- text = Srealloc(text,
- text_size += RTEXTSIZE);
- while (text[pos++] = *ptr++) ;
- pos--;
+ register char *ptr = &id_buf[0];
+
+ 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();
}
#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"
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){
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"
);
);
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");
#include "debug.h"
#include "tokenname.h"
+#include <flt_arith.h>
#include "arith.h"
#include "label.h"
#include "expr.h"
#define ERROR 3
#define CRASH 4
#define FATAL 5
+#define DO_DEBUG 6
int err_occurred = 0;
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
va_start(ap);
{
- _error(WARNING, NILEXPR, ap);
+ _error(WARNING, dot.tk_file, dot.tk_line, ap);
+ /* _error(WARNING, NILEXPR, ap);
+ */
}
va_end(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)
#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"
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 */
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;
}
if (tp->tp_fund == VOID)
gencode = 0;
+
switch (oper) {
case '+':
/* We have the following possibilities :
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 +");
}
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();
}
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 -");
}
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 *");
}
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 /");
}
else
C_cmi(size);
break;
-#ifndef NOFLOAT
case FLOAT:
case DOUBLE:
case LNGDBL:
C_cmf(size);
break;
-#endif NOFLOAT
case POINTER:
C_cmp();
break;
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:
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);
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:
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;
break;
}
break;
-#endif NOFLOAT
case POINTER:
if (oper == MINAB || oper == MINMIN || oper == POSTDECR)
C_ngi(size);
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
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);
}
}
else {
- ASSERT(df->df_sc != STATIC);
+ /* ASSERT(df->df_sc != STATIC); */
if (rvalue) {
if (inword || indword)
LoadLocal(df->df_address + val, size);
/* 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"
#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)
/*NOTREACHED*/
}
-#ifndef NOROPTION
int
rank_of_expression(ex)
register struct expr *ex;
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;
case INTEGER:
int2expr(ex);
break;
-#ifndef NOFLOAT
case FLOATING:
float2expr(ex);
break;
-#endif NOFLOAT
default:
crash("bad conversion to expression");
/*NOTREACHED*/
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 */
}
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 ||
}
}
-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,
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;
fill_int_expr(expr, dot.tk_ival, dot.tk_fund);
}
-#ifndef NOFLOAT
float2expr(expr)
register struct expr *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)
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);
/* 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.
*/
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;
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);
}
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.
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;
/* 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);
a union of various goodies, we define them first; so be patient.
*/
-#include "nofloat.h"
-
/* classes of value */
#define Const 1
#define Name 2
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 */
/* 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 */
union {
struct value ex_value;
struct string ex_string;
-#ifndef NOFLOAT
struct floating ex_float;
-#endif NOFLOAT
struct oper ex_oper;
} ex_object;
};
#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
/* 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)
{
#include <alloc.h>
#include "lint.h"
+#include <flt_arith.h>
#include "arith.h"
#include "LLlex.h"
#include "type.h"
#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);}
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;
}
[
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));
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;)
:
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;}
:
(*expp)->ex_flags |= EX_CAST;
}
|
- postfixed(expp)
+ postfix_expression(expp)
|
unop(&oper) unary(expp)
{ch7mon(oper, 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)
{
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;}
:
*/
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);
]?
;
-/* 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)
]
;
-/* 7.15 */
+/* 3.3.17 */
expression(struct expr **expp;)
{struct expr *e1;}
:
{*oper = DOT;}
;
-postop(int *oper;):
- PLUSPLUS {*oper = POSTINCR;}
-|
- MINMIN {*oper = POSTDECR;}
-;
-
multop:
'*' | '/' | '%'
;
;
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; }
;
] {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; }
;
#include <em.h>
#include <em_reg.h>
#include "debug.h"
+#include <flt_arith.h>
#include "arith.h"
#include "type.h"
#include "idf.h"
#include "lint.h"
#include <em_reg.h>
-#include "nofloat.h"
#include "debug.h"
#include "idfsize.h"
#include "botch_free.h"
#include "Lpars.h"
#include "assert.h"
#include "specials.h" /* registration of special identifiers */
-#include "noRoption.h"
int idfsize = IDFSIZE;
extern char options[];
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;
}
}
*/
/* 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
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)
/* 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();
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; **/
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 [] */
*/
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 */
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");
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");
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");
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:
}
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)
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
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'])
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,
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;
}
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 */
};
/* __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
return "";
if (p) {
*p = '\0';
- fn = Salloc(fn, p - &fn[0] + 1);
+ fn = Salloc(fn,(unsigned) (p - &fn[0] + 1));
*p = '/';
return fn;
}
#endif NOPP
int NoUnstack;
+int InputLevel;
+#if 0
+#endif
AtEoIT()
{
+ InputLevel--;
unstackrepl();
return 0;
}
/* 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 */
{
#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"
#include "level.h"
#include "def.h"
#include "LLlex.h"
-#include "noRoption.h"
#include "estack.h"
#ifdef LINT
#include "l_lint.h"
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
;
initial_value_pack(struct type **tpp; struct expr **expp;)
- { static int pack_level; }
:
'{'
{ if (pack_level == 0) gen_error = 0; pack_level++; }
;
{
-gen_tpcheck(tpp, union_allowed)
+gen_tpcheck(tpp)
struct type **tpp;
{
register struct type *tp;
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);
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.
else
illegal_init_cst(expr);
break;
-#endif NOFLOAT
#ifndef NOBITFIELD
case FIELD:
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;
}
/* 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);
}
*/
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();
#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"
#include "stack.h"
#include "type.h"
#include "level.h"
-#include "nofloat.h"
#include "l_lint.h"
#include "l_state.h"
#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"
#include "stack.h"
#include "type.h"
#include "level.h"
-#include "nofloat.h"
#include "l_lint.h"
#include "l_state.h"
#include "l_outdef.h"
#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"
#include "stack.h"
#include "type.h"
#include "level.h"
-#include "nofloat.h"
#include "l_state.h"
extern char *symbol2str();
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;
case LONG: return 4;
case FLOAT: return 5;
case DOUBLE: return 6;
+ case LNGDBL: return 7;
default: return 0;
}
}
{
/* 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;
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:
#include <alloc.h>
#include "interface.h"
+#include <flt_arith.h>
#include "arith.h"
#include "assert.h"
#include "type.h"
case LONG:
case FLOAT:
case DOUBLE:
+ case LNGDBL:
case VOID:
case ERRONEOUS:
if (tp->tp_unsigned)
#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"
#include "stack.h"
#include "type.h"
#include "level.h"
-#include "nofloat.h"
#include "l_lint.h"
#include "l_brace.h"
#include "l_state.h"
#include "arith.h"
#include "def.h"
#include "type.h"
-#include "noRoption.h"
extern char options[];
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);
}
}
}
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 */
/* MAIN PROGRAM */
#include "lint.h"
-#include "nofloat.h"
#include <system.h>
#include "nopp.h"
#include "target_sizes.h"
#include "LLlex.h"
#include <alloc.h>
#include "specials.h"
-#include "noRoption.h"
#include "nocross.h"
#include "sizes.h"
#include "align.h"
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
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;
{
char *par = &argv[1][1];
- do_option(par, 1);
+ do_option(par);
argc--, argv++;
}
#ifdef LINT
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);
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);
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();
}
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;
#include "lint.h"
#include "botch_free.h"
#include <alloc.h>
-#include "nofloat.h"
#include "nopp.h"
#include "idfsize.h"
#include "nobitfield.h"
#include "align.h"
#include "use_tmp.h"
#include "dataflow.h"
-#include "noRoption.h"
#ifndef NOPP
extern char **inctable;
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 */
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)
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++)
strict("unimplemented pragma directive");
break;
}
+ SkipToNewLine(0);
}
- SkipToNewLine(0);
-
+ else strict("unrecognized pragma line");
}
#endif
{
#include "lint.h"
#include "nopp.h"
+#include <flt_arith.h>
#include "arith.h"
#include "LLlex.h"
#include "idf.h"
}
;
-/* 10 */
+/* 3.7 */
program:
[%persistent external_definition]*
- {unstack_world();}
+ { unstack_world(); }
;
/* A C identifier definition is remarkable in that it formulates
';'
;
-/* 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
#include <alloc.h>
#include "Lpars.h"
#include "level.h"
+#include <flt_arith.h>
#include "arith.h"
#include "align.h"
#include "stack.h"
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;
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);
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.
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;
}
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) {
...
{ 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.
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
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
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;
}
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
}
}
+/* 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;
{
#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;
}
pl->pl_idf = (struct idf *) 0;
}
+ if (pl->pl_type) {
+ remove_proto_tag(pl->pl_type);
+ }
pl = pl->next;
}
}
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;
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)
/* 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;
}
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");
}
}
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 */
#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)
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;
unstackrepl()
{
- struct repl *repl = ReplaceList;
+ Unstacked++;
+}
-#ifdef PERSONAL_TOUCH
- if (repl == NO_REPL) {
- print("Leendert, you don't understand the principle yet\n");
- return;
+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;
}
-#else
- ASSERT(repl != NO_REPL);
-#endif
- ReplaceList = repl->next;
- free_repl(repl);
+ Unstacked = 0;
}
-expand_macro(repl, idf, previdf)
+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
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;
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:
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;
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;
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.
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 {
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++;
*/
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
*/
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);
}
}
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)");
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;
-
- 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;
-
- /* ## occurred at the beginning of the
- replacement list.
- */
- if (repl->r_ptr == repl->r_text)
- goto paste;
- ++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;
-
- 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 */
+ 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++;
+
+ /* 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
+ && is_wsp(*repl->r_ptr)) {
+ err = 1;
+ break;
+ }
+
+ while(*repl->r_ptr == TOKSEP
+ && repl->r_ptr >= repl->r_text)
+ --repl->r_ptr;
+
+ 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);
-
- /* 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];
+ register char *p;
- 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;
}
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)) {
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 */
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
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 */
case '/':
LoadChar(ch);
- if (ch == '*') { /* skip comment */
+ if (ch == '*' && !InputLevel) { /* skip comment */
skipcomment();
continue;
}
/* $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)
#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
#include "input.h"
#ifndef NOPP
+extern int InputLevel;
+
int
skipspaces(ch, skipnl)
register int ch;
/* 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;
}
if (ch == '/') {
ch = GetChar();
- if (ch == '*') {
+ if (ch == '*' && !InputLevel) {
skipcomment();
ch = GetChar();
}
return '/';
}
}
- else
+ else if(nlseen && ch == '#') {
+ domacro();
+ ch = GetChar();
+ } else
return ch;
}
}
register int ch;
register int pstrict = 0;
- UnGetChar();
while ((ch = GetChar()) != '\n') {
if (ch == '/') {
- if ((ch = GetChar()) == '*') {
+ if ((ch = GetChar()) == '*' && !InputLevel) {
skipcomment();
continue;
}
/* 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"
#include "struct.h"
#include "level.h"
#include "mes.h"
-#include "noRoption.h"
/* #include <em_reg.h> */
return local_level;
stl = &UniversalLevel;
- while (stl->sl_level != lvl)
+ while (stl->sl_level != lvl) {
stl = stl->sl_next;
+ }
return stl;
}
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)
#include "debug.h"
#include "botch_free.h"
+#include <flt_arith.h>
#include "arith.h"
#include "LLlex.h"
#include "type.h"
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
}
;
+/* 3.6.1 (partially) */
label
- { struct idf *idf;
- }
+ { struct idf *idf; }
:
identifier(&idf)
{
}
;
+/* 3.6.4.1 */
if_statement
{
struct expr *expr;
]
;
+/* 3.6.5.3 */
while_statement
{
struct expr *expr;
}
;
+/* 3.6.5.2 */
do_statement
{ struct expr *expr;
label l_break = text_label();
}
;
+/* 3.6.5.3 */
for_statement
{ struct expr *e_init = 0, *e_test = 0, *e_incr = 0;
label l_break = text_label();
}
;
+/* 3.6.4.2 */
switch_statement
{
struct expr *expr;
}
;
+/* 3.6.1 (partially) */
case_statement
{
struct expr *expr;
statement
;
+/* 3.6.1 (partially) */
default_statement
:
DEFAULT
statement
;
+/* 3.6.6.4 */
return_statement
{ struct expr *expr = 0;
}
';'
;
+/* 3.6.6.1 (partially) */
jump
{ struct idf *idf;
}
}
;
+/* 3.6.2 */
compound_statement:
'{'
{
#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.
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 */
#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;
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)
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!
*/
/* 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;
}
return sdef;
}
+#if 0
int
uniq_selector(idf_sdef)
register struct sdef *idf_sdef;
}
return 1;
}
+#endif
#ifndef NOBITFIELD
arith
/* 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;
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",
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
/* $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"
#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[];
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.
*/
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;
/* $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>
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;
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;
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);
/* $Header$ */
/* TYPE DESCRIPTOR */
-#include "nofloat.h"
#include "nobitfield.h"
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 */
};
/* 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;