Browse Source

lots and lots of changes & improvements

eck 35 years ago
parent
commit
fa4e6eecb4
59 changed files with 1830 additions and 1575 deletions
  1. 0 12
      lang/cem/cemcom.ansi/BigPars
  2. 271 220
      lang/cem/cemcom.ansi/LLlex.c
  3. 0 5
      lang/cem/cemcom.ansi/LLlex.h
  4. 0 3
      lang/cem/cemcom.ansi/LLmessage.c
  5. 0 12
      lang/cem/cemcom.ansi/LintPars
  6. 31 65
      lang/cem/cemcom.ansi/Makefile
  7. 0 12
      lang/cem/cemcom.ansi/SmallPars
  8. 0 5
      lang/cem/cemcom.ansi/align.h
  9. 51 68
      lang/cem/cemcom.ansi/arith.c
  10. 4 0
      lang/cem/cemcom.ansi/arith.h
  11. 150 45
      lang/cem/cemcom.ansi/ch7.c
  12. 21 19
      lang/cem/cemcom.ansi/ch7bin.c
  13. 26 24
      lang/cem/cemcom.ansi/ch7mon.c
  14. 5 12
      lang/cem/cemcom.ansi/char.tab
  15. 5 1
      lang/cem/cemcom.ansi/class.h
  16. 59 39
      lang/cem/cemcom.ansi/code.c
  17. 1 14
      lang/cem/cemcom.ansi/conversion.c
  18. 41 35
      lang/cem/cemcom.ansi/cstoper.c
  19. 48 26
      lang/cem/cemcom.ansi/declar.g
  20. 1 0
      lang/cem/cemcom.ansi/declarator.c
  21. 8 19
      lang/cem/cemcom.ansi/decspecs.c
  22. 105 64
      lang/cem/cemcom.ansi/domacro.c
  23. 8 7
      lang/cem/cemcom.ansi/dumpidf.c
  24. 30 3
      lang/cem/cemcom.ansi/error.c
  25. 22 29
      lang/cem/cemcom.ansi/eval.c
  26. 57 57
      lang/cem/cemcom.ansi/expr.c
  27. 12 19
      lang/cem/cemcom.ansi/expr.str
  28. 107 131
      lang/cem/cemcom.ansi/expression.g
  29. 1 0
      lang/cem/cemcom.ansi/field.c
  30. 123 84
      lang/cem/cemcom.ansi/idf.c
  31. 0 1
      lang/cem/cemcom.ansi/idf.str
  32. 6 6
      lang/cem/cemcom.ansi/init.c
  33. 5 1
      lang/cem/cemcom.ansi/input.c
  34. 1 1
      lang/cem/cemcom.ansi/input.h
  35. 30 32
      lang/cem/cemcom.ansi/ival.g
  36. 1 1
      lang/cem/cemcom.ansi/l_ev_ord.c
  37. 1 1
      lang/cem/cemcom.ansi/l_lint.c
  38. 15 5
      lang/cem/cemcom.ansi/l_misc.c
  39. 2 0
      lang/cem/cemcom.ansi/l_outdef.c
  40. 1 1
      lang/cem/cemcom.ansi/l_states.c
  41. 1 17
      lang/cem/cemcom.ansi/label.c
  42. 3 2
      lang/cem/cemcom.ansi/macro.str
  43. 7 18
      lang/cem/cemcom.ansi/main.c
  44. 0 16
      lang/cem/cemcom.ansi/options.c
  45. 3 5
      lang/cem/cemcom.ansi/pragma.c
  46. 9 9
      lang/cem/cemcom.ansi/program.g
  47. 117 27
      lang/cem/cemcom.ansi/proto.c
  48. 7 2
      lang/cem/cemcom.ansi/proto.str
  49. 320 275
      lang/cem/cemcom.ansi/replace.c
  50. 3 1
      lang/cem/cemcom.ansi/replace.str
  51. 1 1
      lang/cem/cemcom.ansi/scan.c
  52. 0 5
      lang/cem/cemcom.ansi/sizes.h
  53. 16 5
      lang/cem/cemcom.ansi/skip.c
  54. 10 18
      lang/cem/cemcom.ansi/stack.c
  55. 18 7
      lang/cem/cemcom.ansi/statement.g
  56. 23 64
      lang/cem/cemcom.ansi/struct.c
  57. 13 13
      lang/cem/cemcom.ansi/switch.c
  58. 25 4
      lang/cem/cemcom.ansi/type.c
  59. 5 7
      lang/cem/cemcom.ansi/type.str

+ 0 - 12
lang/cem/cemcom.ansi/BigPars

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

+ 271 - 220
lang/cem/cemcom.ansi/LLlex.c

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

+ 0 - 5
lang/cem/cemcom.ansi/LLlex.h

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

+ 0 - 3
lang/cem/cemcom.ansi/LLmessage.c

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

+ 0 - 12
lang/cem/cemcom.ansi/LintPars

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

+ 31 - 65
lang/cem/cemcom.ansi/Makefile

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

+ 0 - 12
lang/cem/cemcom.ansi/SmallPars

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

+ 0 - 5
lang/cem/cemcom.ansi/align.h

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

+ 51 - 68
lang/cem/cemcom.ansi/arith.c

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

+ 4 - 0
lang/cem/cemcom.ansi/arith.h

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

+ 150 - 45
lang/cem/cemcom.ansi/ch7.c

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

+ 21 - 19
lang/cem/cemcom.ansi/ch7bin.c

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

+ 26 - 24
lang/cem/cemcom.ansi/ch7mon.c

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

+ 5 - 12
lang/cem/cemcom.ansi/char.tab

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

+ 5 - 1
lang/cem/cemcom.ansi/class.h

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

+ 59 - 39
lang/cem/cemcom.ansi/code.c

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

+ 1 - 14
lang/cem/cemcom.ansi/conversion.c

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

+ 41 - 35
lang/cem/cemcom.ansi/cstoper.c

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

+ 48 - 26
lang/cem/cemcom.ansi/declar.g

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

+ 1 - 0
lang/cem/cemcom.ansi/declarator.c

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

+ 8 - 19
lang/cem/cemcom.ansi/decspecs.c

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

+ 105 - 64
lang/cem/cemcom.ansi/domacro.c

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

+ 8 - 7
lang/cem/cemcom.ansi/dumpidf.c

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

+ 30 - 3
lang/cem/cemcom.ansi/error.c

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

+ 22 - 29
lang/cem/cemcom.ansi/eval.c

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

+ 57 - 57
lang/cem/cemcom.ansi/expr.c

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

+ 12 - 19
lang/cem/cemcom.ansi/expr.str

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

+ 107 - 131
lang/cem/cemcom.ansi/expression.g

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

+ 1 - 0
lang/cem/cemcom.ansi/field.c

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

+ 123 - 84
lang/cem/cemcom.ansi/idf.c

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

+ 0 - 1
lang/cem/cemcom.ansi/idf.str

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

+ 6 - 6
lang/cem/cemcom.ansi/init.c

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

+ 5 - 1
lang/cem/cemcom.ansi/input.c

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

+ 1 - 1
lang/cem/cemcom.ansi/input.h

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

+ 30 - 32
lang/cem/cemcom.ansi/ival.g

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

+ 1 - 1
lang/cem/cemcom.ansi/l_ev_ord.c

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

+ 1 - 1
lang/cem/cemcom.ansi/l_lint.c

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

+ 15 - 5
lang/cem/cemcom.ansi/l_misc.c

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

+ 2 - 0
lang/cem/cemcom.ansi/l_outdef.c

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

+ 1 - 1
lang/cem/cemcom.ansi/l_states.c

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

+ 1 - 17
lang/cem/cemcom.ansi/label.c

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

+ 3 - 2
lang/cem/cemcom.ansi/macro.str

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

+ 7 - 18
lang/cem/cemcom.ansi/main.c

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

+ 0 - 16
lang/cem/cemcom.ansi/options.c

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

+ 3 - 5
lang/cem/cemcom.ansi/pragma.c

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

+ 9 - 9
lang/cem/cemcom.ansi/program.g

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

+ 117 - 27
lang/cem/cemcom.ansi/proto.c

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

+ 7 - 2
lang/cem/cemcom.ansi/proto.str

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

+ 320 - 275
lang/cem/cemcom.ansi/replace.c

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

+ 3 - 1
lang/cem/cemcom.ansi/replace.str

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

+ 1 - 1
lang/cem/cemcom.ansi/scan.c

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

+ 0 - 5
lang/cem/cemcom.ansi/sizes.h

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

+ 16 - 5
lang/cem/cemcom.ansi/skip.c

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

+ 10 - 18
lang/cem/cemcom.ansi/stack.c

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

+ 18 - 7
lang/cem/cemcom.ansi/statement.g

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

+ 23 - 64
lang/cem/cemcom.ansi/struct.c

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

+ 13 - 13
lang/cem/cemcom.ansi/switch.c

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

+ 25 - 4
lang/cem/cemcom.ansi/type.c

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

+ 5 - 7
lang/cem/cemcom.ansi/type.str

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