Initial revision
authorceriel <none@none>
Tue, 7 Feb 1989 11:04:05 +0000 (11:04 +0000)
committerceriel <none@none>
Tue, 7 Feb 1989 11:04:05 +0000 (11:04 +0000)
108 files changed:
lang/cem/cemcom.ansi/.distr [new file with mode: 0644]
lang/cem/cemcom.ansi/BigPars [new file with mode: 0644]
lang/cem/cemcom.ansi/LLlex.c [new file with mode: 0644]
lang/cem/cemcom.ansi/LLlex.h [new file with mode: 0644]
lang/cem/cemcom.ansi/LLmessage.c [new file with mode: 0644]
lang/cem/cemcom.ansi/LintPars [new file with mode: 0644]
lang/cem/cemcom.ansi/Makefile [new file with mode: 0644]
lang/cem/cemcom.ansi/Makefile.erik [new file with mode: 0644]
lang/cem/cemcom.ansi/Resolve [new file with mode: 0755]
lang/cem/cemcom.ansi/SmallPars [new file with mode: 0644]
lang/cem/cemcom.ansi/Version.c [new file with mode: 0644]
lang/cem/cemcom.ansi/align.h [new file with mode: 0644]
lang/cem/cemcom.ansi/arith.c [new file with mode: 0644]
lang/cem/cemcom.ansi/arith.h [new file with mode: 0644]
lang/cem/cemcom.ansi/asm.c [new file with mode: 0644]
lang/cem/cemcom.ansi/assert.h [new file with mode: 0644]
lang/cem/cemcom.ansi/atw.h [new file with mode: 0644]
lang/cem/cemcom.ansi/blocks.c [new file with mode: 0644]
lang/cem/cemcom.ansi/cem.1 [new file with mode: 0644]
lang/cem/cemcom.ansi/cem.c [new file with mode: 0644]
lang/cem/cemcom.ansi/cemcom.1 [new file with mode: 0644]
lang/cem/cemcom.ansi/ch7.c [new file with mode: 0644]
lang/cem/cemcom.ansi/ch7bin.c [new file with mode: 0644]
lang/cem/cemcom.ansi/ch7mon.c [new file with mode: 0644]
lang/cem/cemcom.ansi/char.tab [new file with mode: 0644]
lang/cem/cemcom.ansi/class.h [new file with mode: 0644]
lang/cem/cemcom.ansi/code.c [new file with mode: 0644]
lang/cem/cemcom.ansi/code.str [new file with mode: 0644]
lang/cem/cemcom.ansi/conversion.c [new file with mode: 0644]
lang/cem/cemcom.ansi/cstoper.c [new file with mode: 0644]
lang/cem/cemcom.ansi/dataflow.c [new file with mode: 0644]
lang/cem/cemcom.ansi/declar.g [new file with mode: 0644]
lang/cem/cemcom.ansi/declar.str [new file with mode: 0644]
lang/cem/cemcom.ansi/declarator.c [new file with mode: 0644]
lang/cem/cemcom.ansi/decspecs.c [new file with mode: 0644]
lang/cem/cemcom.ansi/decspecs.str [new file with mode: 0644]
lang/cem/cemcom.ansi/def.str [new file with mode: 0644]
lang/cem/cemcom.ansi/domacro.c [new file with mode: 0644]
lang/cem/cemcom.ansi/dumpidf.c [new file with mode: 0644]
lang/cem/cemcom.ansi/error.c [new file with mode: 0644]
lang/cem/cemcom.ansi/estack.str [new file with mode: 0644]
lang/cem/cemcom.ansi/eval.c [new file with mode: 0644]
lang/cem/cemcom.ansi/expr.c [new file with mode: 0644]
lang/cem/cemcom.ansi/expr.str [new file with mode: 0644]
lang/cem/cemcom.ansi/expression.g [new file with mode: 0644]
lang/cem/cemcom.ansi/field.c [new file with mode: 0644]
lang/cem/cemcom.ansi/field.str [new file with mode: 0644]
lang/cem/cemcom.ansi/file_info.h [new file with mode: 0644]
lang/cem/cemcom.ansi/idf.c [new file with mode: 0644]
lang/cem/cemcom.ansi/idf.str [new file with mode: 0644]
lang/cem/cemcom.ansi/init.c [new file with mode: 0644]
lang/cem/cemcom.ansi/input.c [new file with mode: 0644]
lang/cem/cemcom.ansi/input.h [new file with mode: 0644]
lang/cem/cemcom.ansi/interface.h [new file with mode: 0644]
lang/cem/cemcom.ansi/ival.g [new file with mode: 0644]
lang/cem/cemcom.ansi/l_brace.str [new file with mode: 0644]
lang/cem/cemcom.ansi/l_class.h [new file with mode: 0644]
lang/cem/cemcom.ansi/l_comment.c [new file with mode: 0644]
lang/cem/cemcom.ansi/l_comment.h [new file with mode: 0644]
lang/cem/cemcom.ansi/l_dummy.c [new file with mode: 0644]
lang/cem/cemcom.ansi/l_ev_ord.c [new file with mode: 0644]
lang/cem/cemcom.ansi/l_lint.c [new file with mode: 0644]
lang/cem/cemcom.ansi/l_lint.h [new file with mode: 0644]
lang/cem/cemcom.ansi/l_misc.c [new file with mode: 0644]
lang/cem/cemcom.ansi/l_outdef.c [new file with mode: 0644]
lang/cem/cemcom.ansi/l_outdef.str [new file with mode: 0644]
lang/cem/cemcom.ansi/l_state.str [new file with mode: 0644]
lang/cem/cemcom.ansi/l_states.c [new file with mode: 0644]
lang/cem/cemcom.ansi/label.c [new file with mode: 0644]
lang/cem/cemcom.ansi/label.h [new file with mode: 0644]
lang/cem/cemcom.ansi/level.h [new file with mode: 0644]
lang/cem/cemcom.ansi/macro.str [new file with mode: 0644]
lang/cem/cemcom.ansi/main.c [new file with mode: 0644]
lang/cem/cemcom.ansi/make.allocd [new file with mode: 0755]
lang/cem/cemcom.ansi/make.hfiles [new file with mode: 0755]
lang/cem/cemcom.ansi/make.next [new file with mode: 0755]
lang/cem/cemcom.ansi/make.tokcase [new file with mode: 0755]
lang/cem/cemcom.ansi/make.tokfile [new file with mode: 0755]
lang/cem/cemcom.ansi/mcomm.c [new file with mode: 0644]
lang/cem/cemcom.ansi/mes.h [new file with mode: 0644]
lang/cem/cemcom.ansi/nmclash.c [new file with mode: 0644]
lang/cem/cemcom.ansi/options [new file with mode: 0644]
lang/cem/cemcom.ansi/options.c [new file with mode: 0644]
lang/cem/cemcom.ansi/pragma.c [new file with mode: 0644]
lang/cem/cemcom.ansi/program.g [new file with mode: 0644]
lang/cem/cemcom.ansi/proto.c [new file with mode: 0644]
lang/cem/cemcom.ansi/proto.str [new file with mode: 0644]
lang/cem/cemcom.ansi/replace.c [new file with mode: 0644]
lang/cem/cemcom.ansi/replace.str [new file with mode: 0644]
lang/cem/cemcom.ansi/scan.c [new file with mode: 0644]
lang/cem/cemcom.ansi/sizes.h [new file with mode: 0644]
lang/cem/cemcom.ansi/skip.c [new file with mode: 0644]
lang/cem/cemcom.ansi/specials.h [new file with mode: 0644]
lang/cem/cemcom.ansi/stack.c [new file with mode: 0644]
lang/cem/cemcom.ansi/stack.str [new file with mode: 0644]
lang/cem/cemcom.ansi/statement.g [new file with mode: 0644]
lang/cem/cemcom.ansi/stb.c [new file with mode: 0644]
lang/cem/cemcom.ansi/stmt.str [new file with mode: 0644]
lang/cem/cemcom.ansi/struct.c [new file with mode: 0644]
lang/cem/cemcom.ansi/struct.str [new file with mode: 0644]
lang/cem/cemcom.ansi/switch.c [new file with mode: 0644]
lang/cem/cemcom.ansi/switch.str [new file with mode: 0644]
lang/cem/cemcom.ansi/tokenname.c [new file with mode: 0644]
lang/cem/cemcom.ansi/tokenname.h [new file with mode: 0644]
lang/cem/cemcom.ansi/type.c [new file with mode: 0644]
lang/cem/cemcom.ansi/type.str [new file with mode: 0644]
lang/cem/cemcom.ansi/util.c [new file with mode: 0644]
lang/cem/cemcom.ansi/util.str [new file with mode: 0644]

diff --git a/lang/cem/cemcom.ansi/.distr b/lang/cem/cemcom.ansi/.distr
new file mode 100644 (file)
index 0000000..b556550
--- /dev/null
@@ -0,0 +1,101 @@
+Version.c
+Makefile
+Resolve
+nmclash.c
+LLlex.c
+LLlex.h
+LLmessage.c
+SmallPars
+BigPars
+LintPars
+align.h
+arith.c
+arith.h
+asm.c
+assert.h
+atw.h
+blocks.c
+cem.1
+cem.c
+cemcom.1
+ch7.c
+ch7bin.c
+ch7mon.c
+char.tab
+class.h
+code.c
+code.str
+conversion.c
+cstoper.c
+dataflow.c
+declar.g
+declar.str
+declarator.c
+decspecs.c
+decspecs.str
+def.str
+domacro.c
+dumpidf.c
+error.c
+estack.str
+eval.c
+expr.c
+expr.str
+expression.g
+field.c
+field.str
+file_info.h
+idf.c
+idf.str
+init.c
+input.c
+input.h
+interface.h
+ival.g
+l_brace.str
+l_class.h
+l_comment.c
+l_dummy.c
+l_ev_ord.c
+l_lint.c
+l_lint.h
+l_misc.c
+l_outdef.c
+l_outdef.str
+l_state.str
+l_states.c
+label.c
+label.h
+level.h
+macro.str
+main.c
+make.allocd
+make.hfiles
+make.next
+make.tokcase
+make.tokfile
+mcomm.c
+mes.h
+options
+options.c
+program.g
+replace.c
+scan.c
+sizes.h
+skip.c
+specials.h
+stack.c
+stack.str
+statement.g
+stb.c
+stmt.str
+struct.c
+struct.str
+switch.c
+switch.str
+tokenname.c
+tokenname.h
+type.c
+type.str
+util.str
+util.c
diff --git a/lang/cem/cemcom.ansi/BigPars b/lang/cem/cemcom.ansi/BigPars
new file mode 100644 (file)
index 0000000..08aaa58
--- /dev/null
@@ -0,0 +1,145 @@
+!File: lint.h
+#undef LINT            1       /* if defined, 'lint' is produced       */
+
+
+!File: pathlength.h
+#define PATHLENGTH     1024    /* max. length of path to file          */
+
+
+!File: errout.h
+#define        ERROUT          STDERR  /* file pointer for writing messages    */
+#define        MAXERR_LINE     5       /* maximum number of error messages given
+                                       on the same input line.         */
+
+
+!File: idfsize.h
+#define        IDFSIZE 64      /* maximum significant length of an identifier  */
+
+
+!File: numsize.h
+#define        NUMSIZE 256     /* maximum length of a numeric constant         */
+
+
+!File: nparams.h
+#define        NPARAMS 32      /* maximum number of parameters of macros       */
+
+
+!File: ifdepth.h
+#define        IFDEPTH 256     /* maximum number of nested if-constructions    */
+
+
+!File: density.h
+#define        DENSITY 2       /* see switch.[ch] for an explanation           */
+
+
+!File: lapbuf.h
+#define        LAPBUF  4096    /* size of macro actual parameter buffer        */
+
+
+!File: strsize.h
+#define ISTRSIZE       32      /* minimum number of bytes allocated for
+                                       storing a string                */
+#define RSTRSIZE       16      /* step size in enlarging the memory for
+                                       the storage of a string         */
+
+
+!File: target_sizes.h
+#define MAXSIZE                8       /* the maximum of the SZ_* constants    */
+
+/* target machine sizes        */
+#define        SZ_CHAR         (arith)1
+#define        SZ_SHORT        (arith)2
+#define SZ_WORD                (arith)4
+#define        SZ_INT          (arith)4
+#define        SZ_LONG         (arith)4
+#ifndef NOFLOAT
+#define        SZ_FLOAT        (arith)4
+#define        SZ_DOUBLE       (arith)8
+#endif NOFLOAT
+#define        SZ_POINTER      (arith)4
+
+/* target machine alignment requirements       */
+#define        AL_CHAR         1
+#define        AL_SHORT        SZ_SHORT
+#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
+
+
+!File: botch_free.h
+#undef BOTCH_FREE      1       /* when defined, botch freed memory, as a check */
+
+
+!File: dataflow.h
+#define DATAFLOW       1       /* produce some compile-time xref       */
+
+
+!File: debug.h
+#undef DEBUG           1       /* perform various self-tests           */
+
+
+!File: use_tmp.h
+#define PREPEND_SCOPES 1       /* collect exa, exp, ina and inp commands
+                                       and if USE_TMP is defined let them
+                                       precede the rest of the generated
+                                       compact code    */
+#define USE_TMP                1       /* use C_insertpart, C_endpart mechanism
+                                       to generate EM-code in the order needed
+                                       for the code-generators. If not defined,
+                                       the old-style peephole optimizer is
+                                       needed. */
+
+
+!File: parbufsize.h
+#define PARBUFSIZE     1024
+
+
+!File: textsize.h
+#define ITEXTSIZE      32      /* 1st piece of memory for repl. text   */
+#define RTEXTSIZE      16      /* stepsize for enlarging repl.text     */
+
+
+!File: inputtype.h
+#define INP_READ_IN_ONE        1       /* read input file in one       */
+
+
+!File: nopp.h
+#undef NOPP            1       /* if NOT defined, use built-int preprocessor */
+
+
+!File: nobitfield.h
+#undef NOBITFIELD      1       /* if NOT defined, implement bitfields  */
+
+
+!File: spec_arith.h
+/* describes internal compiler arithmetics */
+#undef SPECIAL_ARITHMETICS     /* something different from native long */
+
+
+!File: static.h
+#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 */
+
+
+!File: regcount.h
+#undef REGCOUNT                1       /* count occurrences for register messages */
+
+
diff --git a/lang/cem/cemcom.ansi/LLlex.c b/lang/cem/cemcom.ansi/LLlex.c
new file mode 100644 (file)
index 0000000..592bf04
--- /dev/null
@@ -0,0 +1,777 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*                 L E X I C A L   A N A L Y Z E R                     */
+
+#include       "lint.h"
+#include       <alloc.h>
+#include       "nofloat.h"
+#include       "idfsize.h"
+#include       "numsize.h"
+#include       "debug.h"
+#include       "strsize.h"
+#include       "nopp.h"
+#include       "input.h"
+#include       "arith.h"
+#include       "def.h"
+#include       "macro.h"
+#include       "idf.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "class.h"
+#include       "assert.h"
+#include       "sizes.h"
+
+/* Data about the token yielded */
+struct token dot, ahead, aside;
+
+#ifndef NOPP
+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                   */
+#endif
+int AccFileSpecifier = 0;      /* return filespecifier <...>           */
+int EoiForNewline = 0;         /* return EOI upon encountering newline */
+int File_Inserted = 0;         /* a file has just been inserted        */
+int LexSave = 0;               /* last character read by GetChar       */
+#define MAX_LL_DEPTH   2
+
+static struct token LexStack[MAX_LL_DEPTH];
+static LexSP = 0;
+
+/*     In PushLex() the actions are taken in order to initialise or
+       re-initialise the lexical scanner.
+       E.g. at the invocation of a sub-parser that uses LLlex(), the
+       state of the current parser should be saved.
+*/
+PushLex()
+{
+       ASSERT(LexSP < 2);
+       ASSERT(ASIDE == 0);     /* ASIDE = 0;   */
+       GetToken(&ahead);
+       LexStack[LexSP++] = dot;
+}
+
+PopLex()
+{
+       ASSERT(LexSP > 0);
+       dot = LexStack[--LexSP];
+}
+
+int
+LLlex()
+{
+       /*      LLlex() plays the role of Lexical Analyzer for the C parser.
+               The look-ahead and putting aside of tokens are taken into
+               account.
+       */
+       if (ASIDE) {    /* a token is put aside         */
+               dot = aside;
+               ASIDE = 0;
+       }
+       else {          /* read ahead and return the old one    */
+#ifdef LINT
+               lint_comment_ahead();
+#endif LINT
+               dot = ahead;
+               /*      the following test is performed due to the dual
+                       task of LLlex(): it is also called for parsing the
+                       restricted constant expression following a #if or
+                       #elif.  The newline character causes EOF to be
+                       returned in this case to stop the LLgen parsing task.
+               */
+               if (DOT != EOI)
+                       GetToken(&ahead);
+               else
+                       DOT = EOF;
+       }
+       return DOT;
+}
+
+
+char   *string_token();
+arith  char_constant();
+
+
+int
+GetToken(ptok)
+       register struct token *ptok;
+{
+       /*      LexToken() 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.
+       */
+       char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
+       register int ch, nch;
+
+       if (File_Inserted) {
+               File_Inserted = 0;
+               goto firstline;
+       }
+
+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;
+
+       switch (class(ch)) {    /* detect character class       */
+       case STNL:              /* newline, vertical space or formfeed  */
+firstline:
+               LineNumber++;                   /* also at vs and ff    */
+               ptok->tk_file = FileName;
+               ptok->tk_line = LineNumber;
+               if (EoiForNewline)      /* called in control line       */
+                       /*      a newline in a control line indicates the
+                               end-of-information of the line.
+                       */
+                       return ptok->tk_symb = EOI;
+               while ((ch = GetChar()), (ch == '#' || class(ch) == STSKIP)) {
+                       /* blanks are allowed before hashes */
+                       if (ch == '#') {
+                               /* a control line follows */
+                               domacro();
+                               if (File_Inserted) {
+                                       File_Inserted = 0;
+                                       goto firstline;
+                               }
+                       }
+               }
+                       /*      We have to loop here, because in
+                               `domacro' the nl, vt or ff is read. The
+                               character following it may again be a `#'.
+                       */
+               goto go_on;
+       case STSKIP:            /* just skip the skip characters        */
+               goto again;
+       case STGARB:            /* garbage character                    */
+               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  */
+               switch (ch) {
+               case '!':
+                       if (nch == '=')
+                               return ptok->tk_symb = NOTEQUAL;
+                       UnGetChar();
+                       return ptok->tk_symb = ch;
+               case '&':
+                       if (nch == '&')
+                               return ptok->tk_symb = AND;
+                       UnGetChar();
+                       return ptok->tk_symb = ch;
+               case '+':
+                       if (nch == '+')
+                               return ptok->tk_symb = PLUSPLUS;
+                       UnGetChar();
+                       return ptok->tk_symb = ch;
+               case '-':
+                       if (nch == '-')
+                               return ptok->tk_symb = MINMIN;
+                       if (nch == '>')
+                               return ptok->tk_symb = ARROW;
+                       UnGetChar();
+                       return ptok->tk_symb = ch;
+               case '<':
+                       if (AccFileSpecifier) {
+                               UnGetChar();    /* pushback nch */
+                               ptok->tk_bts = string_token("file specifier",
+                                                       '>', &(ptok->tk_len));
+                               return ptok->tk_symb = FILESPECIFIER;
+                       }
+                       if (nch == '<')
+                               return ptok->tk_symb = LEFT;
+                       if (nch == '=')
+                               return ptok->tk_symb = LESSEQ;
+                       UnGetChar();
+                       return ptok->tk_symb = ch;
+               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 == '>')
+                               return ptok->tk_symb = RIGHT;
+                       UnGetChar();
+                       return ptok->tk_symb = ch;
+               case '|':
+                       if (nch == '|')
+                               return ptok->tk_symb = OR;
+                       UnGetChar();
+                       return ptok->tk_symb = ch;
+               }
+       case STCHAR:                            /* character constant   */
+               ptok->tk_ival = char_constant("character");
+               ptok->tk_fund = INT;
+               return ptok->tk_symb = INTEGER;
+       case STSTR:                                     /* string       */
+               ptok->tk_bts = string_token("string", '"', &(ptok->tk_len));
+               ptok->tk_fund = CHAR;           /* string of characters */
+               return ptok->tk_symb = STRING;
+       case STELL:             /* wide character constant/string prefix */
+               nch = GetChar();
+               if (nch == '"') {
+                       ptok->tk_bts = string_token("wide character string",
+                                       '"', &(ptok->tk_len));
+                       ptok->tk_fund = WCHAR;  /* string of wide characters */
+                       return ptok->tk_symb = STRING;
+               } else if (nch == '\'') {
+                       ptok->tk_ival = char_constant("wide character");
+                       ptok->tk_fund = INT;
+                       return ptok->tk_symb = INTEGER;
+               }
+               UnGetChar();
+       case STIDF:
+       {
+               register char *tg = &buf[0];
+               register int pos = -1;
+               register int hash;
+               register struct idf *idef;
+               extern int idfsize;             /* ??? */
+
+               hash = STARTHASH();
+               do      {                       /* read the identifier  */
+                       if (++pos < idfsize) {
+                               *tg++ = ch;
+                               hash = ENHASH(hash, ch, pos);
+                       }
+                       ch = GetChar();
+               } while (in_idf(ch));
+
+               hash = STOPHASH(hash);
+               if (ch != EOI)
+                       UnGetChar();
+               *tg++ = '\0';   /* mark the end of the identifier       */
+               idef = ptok->tk_idf = idf_hashed(buf, tg - buf, hash);
+               idef->id_file = ptok->tk_file;
+               idef->id_line = ptok->tk_line;
+#ifndef NOPP
+               if (idef->id_macro && ReplaceMacros) {
+                       if (idef->id_macro->mc_count > 0)
+                               idef->id_macro->mc_count--;
+                       else if (replace(idef))
+                               goto again;
+               }
+               if (UnknownIdIsZero && idef->id_reserved != SIZEOF) {
+                       ptok->tk_ival = (arith)0;
+                       ptok->tk_fund = INT;
+                       return ptok->tk_symb = INTEGER;
+               }
+#endif NOPP
+               ptok->tk_symb = (
+                       idef->id_reserved ? idef->id_reserved
+                       : idef->id_def && idef->id_def->df_sc == TYPEDEF ?
+                               TYPE_IDENTIFIER
+                       : IDENTIFIER
+               );
+               return IDENTIFIER;
+       }
+       case STNUM:                             /* a numeric constant   */
+       {
+               register char *np = &buf[1];
+               register int base = 10;
+               register int vch;
+               register arith val = 0;
+
+               if (ch == '.') {
+#ifndef NOFLOAT
+                       /*      A very embarrasing ambiguity. We have either a
+                               floating point number or field operator or
+                               ELLIPSIS.
+                       */
+                       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();
+                               return ptok->tk_symb = '.';
+                       } else
+                               *np++ = '0';
+                       UnGetChar();
+#else
+                       if ((ch = GetChar()) == '.') {
+                               if ((ch = 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 = 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;
+                               }
+                               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();
+                       }
+               }
+
+               /*      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++ = '\0';
+               buf[0] = '-';   /* good heavens...      */
+               if (np == &buf[NUMSIZE+1]) {
+                       lexerror("floating constant too long");
+                       ptok->tk_fval = Salloc("0.0",(unsigned) 5) + 1;
+               }
+               else
+                       ptok->tk_fval = Salloc(buf,(unsigned) (np - buf)) + 1;
+               return ptok->tk_symb = FLOATING;
+#endif NOFLOAT
+       }
+       case STEOI:                     /* end of text on source file   */
+               return ptok->tk_symb = EOI;
+       default:                                /* this cannot happen   */
+               crash("bad class for char 0%o", ch);
+       }
+       /*NOTREACHED*/
+}
+
+skipcomment()
+{
+       /*      The last character read has been the '*' of '/_*'.  The
+               characters, except NL and EOI, between '/_*' and the first
+               occurring '*_/' are not interpreted.
+               NL only affects the LineNumber.  EOI is not legal.
+
+               Important note: it is not possible to stop skipping comment
+               beyond the end-of-file of an included file.
+               EOI is returned by LoadChar only on encountering EOF of the
+               top-level file...
+       */
+       register int c;
+
+       NoUnstack++;
+       c = GetChar();
+#ifdef LINT
+       lint_start_comment();
+       lint_comment_char(c);
+#endif LINT
+       do {
+               while (c != '*') {
+                       if (class(c) == STNL) {
+                               ++LineNumber;
+                       } 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);
+#endif LINT
+               } /* last Character seen was '*' */
+               c = GetChar();
+#ifdef LINT
+               lint_comment_char(c);
+#endif LINT
+       } while (c != '/');
+#ifdef LINT
+       lint_end_comment();
+#endif LINT
+       NoUnstack--;
+}
+
+arith
+char_constant(nm)
+       char *nm;
+{
+       register arith val = 0;
+       register int ch;
+       int size = 0;
+
+       ch = GetChar();
+       if (ch == '\'')
+               lexerror("%s constant too short", nm);
+       else
+       while (ch != '\'') {
+               if (ch == '\n') {
+                       lexerror("newline in %s constant", nm);
+                       LineNumber++;
+                       break;
+               }
+               if (ch == '\\')
+                       ch = quoted(GetChar());
+               if (ch >= 128) ch -= 256;
+               val = val*256 + ch;
+               size++;
+               ch = GetChar();
+       }
+       if (size > 1)
+               strict("%s constant includes more than one character", nm);
+       if (size > (int)int_size)
+               lexerror("%s constant too long", nm);
+       return val;
+}
+
+char *
+string_token(nm, stop_char, plen)
+       char *nm;
+       int *plen;
+{
+       register int ch;
+       register int str_size;
+       register char *str = Malloc((unsigned) (str_size = ISTRSIZE));
+       register int pos = 0;
+       
+       ch = GetChar();
+       while (ch != stop_char) {
+               if (ch == '\n') {
+                       lexerror("newline in %s", nm);
+                       LineNumber++;
+                       break;
+               }
+               if (ch == EOI) {
+                       lexerror("end-of-file inside %s", nm);
+                       break;
+               }
+               if (ch == '\\')
+                       ch = quoted(GetChar());
+               str[pos++] = ch;
+               if (pos == str_size)
+                       str = Srealloc(str, (unsigned) (str_size += RSTRSIZE));
+               ch = GetChar();
+       }
+       str[pos++] = '\0'; /* for filenames etc. */
+       *plen = pos;
+       return str;
+}
+
+int
+quoted(ch)
+       register int ch;
+{      
+       /*      quoted() replaces an escaped character sequence by the
+               character meant.
+       */
+       /* first char after backslash already in ch */
+       if (!is_oct(ch)) {              /* a quoted char */
+               switch (ch) {
+               case 'n':
+                       ch = '\n';
+                       break;
+               case 't':
+                       ch = '\t';
+                       break;
+               case 'b':
+                       ch = '\b';
+                       break;
+               case 'r':
+                       ch = '\r';
+                       break;
+               case 'f':
+                       ch = '\f';
+                       break;
+               case 'a':               /* alert */
+                       ch = '\007';
+                       break;
+               case 'v':               /* vertical tab */
+                       ch = '\013';
+                       break;
+               case 'x':               /* quoted hex */
+               {
+                       register int hex = 0;
+                       register int vch;
+
+                       for (;;) {
+                               ch = GetChar();
+                               if (vch = val_in_base(ch, 16), vch == -1)
+                                       break;
+                               hex = hex * 16 + vch;
+                       }
+                       UnGetChar();
+                       ch = hex;
+               }
+               }
+       }
+       else {                          /* a quoted octal */
+               register int oct = 0, cnt = 0;
+
+               do {
+                       oct = oct*8 + (ch-'0');
+                       ch = GetChar();
+               } while (is_oct(ch) && ++cnt < 3);
+               UnGetChar();
+               ch = oct;
+       }
+       return ch&0377;
+}
+
+
+int
+val_in_base(ch, base)
+       register int ch;
+{
+       switch (base) {
+       case 8:
+               return (is_dig(ch) && ch < '9') ? ch - '0' : -1;
+       case 10:
+       case 16:
+               return is_dig(ch) ? ch - '0'
+                       : is_hex(ch) ? (ch - 'a' + 10) & 017
+                       : -1;
+       default:
+               fatal("(val_in_base) illegal base value %d", base);
+               /* NOTREACHED */
+       }
+}
+
+
+int
+GetChar()
+{
+       /*      The routines GetChar and trigraph parses the trigraph
+               sequences and removes occurences of \\\n.
+       */
+       register int ch;
+
+again:
+       LoadChar(ch);
+
+       /* possible trigraph sequence */
+       if (ch == '?')
+               ch = trigraph();
+
+       /* \\\n are removed from the input stream */
+       if (ch == '\\') {
+               LoadChar(ch);
+               if (ch == '\n') {
+                       ++LineNumber;
+                       goto again;
+               }
+               PushBack();
+               ch = '\\';
+       }
+       return(LexSave = ch);
+}
+
+
+int
+trigraph()
+{
+       register int ch;
+
+       LoadChar(ch);
+       if (ch == '?') {
+               LoadChar(ch);
+               switch (ch) {           /* its a trigraph */
+               case '=':
+                       ch =  '#';
+                       return(ch);
+               case '(':
+                       ch = '[';
+                       return(ch);
+               case '/':
+                       ch = '\\';
+                       return(ch);
+               case ')':
+                       ch = ']';
+                       return(ch);
+               case '\'':
+                       ch = '^';
+                       return(ch);
+               case '<':
+                       ch = '{';
+                       return(ch);
+               case '!':
+                       ch = '|';
+                       return(ch);
+               case '>':
+                       ch = '}';
+                       return(ch);
+               case '-':
+                       ch = '~';
+                       return(ch);
+               }
+               PushBack();
+       }
+       PushBack();
+       return('?');
+}
diff --git a/lang/cem/cemcom.ansi/LLlex.h b/lang/cem/cemcom.ansi/LLlex.h
new file mode 100644 (file)
index 0000000..fb1318c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* D E F I N I T I O N S   F O R   T H E   L E X I C A L   A N A L Y Z E R */
+
+/*     A token from the input stream is represented by an integer,
+       called a "symbol", but it may have other information associated
+       to it.
+*/
+
+#include "nofloat.h"
+#include "file_info.h"
+#include "nopp.h"
+
+/* the structure of a token:   */
+struct token   {
+       int tok_symb;           /* the token itself */
+       char *tok_file;         /* the file it (probably) comes from */
+       unsigned int tok_line;  /* the line it (probably) comes from */
+       int tok_fund;
+       union   {
+               struct idf *tok_idf;    /* for IDENTIFIER & TYPE_IDENTIFIER */
+               struct  {               /* for STRING */
+                       char *tok_bts;  /* row of bytes */
+                       int tok_len;    /* length of row of bytes */
+               } tok_string;
+               arith tok_ival;         /* for INTEGER */
+#ifndef NOFLOAT
+               char *tok_fval;         /* for FLOATING */
+#endif NOFLOAT
+       } tok_data;
+};
+
+#define tk_symb        tok_symb
+#define tk_file        tok_file
+#define tk_line        tok_line
+#define tk_fund        tok_fund
+#define tk_idf tok_data.tok_idf
+#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;
+
+#ifndef NOPP
+extern int ReplaceMacros;      /* "LLlex.c"    */
+extern int AccDefined;         /* "LLlex.c"    */
+extern int Unstacked;          /* "LLlex.c"    */
+extern int UnknownIdIsZero;    /* "LLlex.c"    */
+#endif NOPP
+extern int EoiForNewline;      /* "LLlex.c"    */
+extern int AccFileSpecifier;   /* "LLlex.c"    */
+extern int SkipEscNewline;     /* "LLlex.c"    */
+extern int File_Inserted;      /* "LLlex.c"    */
+
+extern int NoUnstack;          /* buffer.c     */
+
+extern int err_occurred;       /* "error.c"    */
+
+#define        DOT     dot.tk_symb
+#define        AHEAD   ahead.tk_symb
+#define        ASIDE   aside.tk_symb
+
+#define EOF    (-1)
diff --git a/lang/cem/cemcom.ansi/LLmessage.c b/lang/cem/cemcom.ansi/LLmessage.c
new file mode 100644 (file)
index 0000000..23005c9
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*             PARSER ERROR ADMINISTRATION             */
+
+#include       <alloc.h>
+#include       "nofloat.h"
+#include       "idf.h"
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+
+extern char *symbol2str();
+
+LLmessage(tk)  {
+       err_occurred = 1;
+       if (tk < 0)     {
+               error("end of file expected");
+       }
+       else if (tk)    {
+               error("%s missing", symbol2str(tk));
+               insert_token(tk);
+       }
+       else
+               error("%s deleted", symbol2str(DOT));
+}
+
+insert_token(tk)
+       int tk;
+{
+       aside = dot;
+
+       DOT = tk;
+
+       switch (tk)     {
+       /* The operands need some body */
+       case IDENTIFIER:
+               dot.tk_idf = gen_idf();
+               break;
+       case TYPE_IDENTIFIER:
+               dot.tk_idf = str2idf("int");
+               break;
+       case STRING:
+               dot.tk_bts = Salloc("", 1);
+               dot.tk_len = 1;
+               break;
+       case INTEGER:
+               dot.tk_fund = INT;
+               dot.tk_ival = 1;
+               break;
+#ifndef NOFLOAT
+       case FLOATING:
+               dot.tk_fval = Salloc("0.0", 4);
+               break;
+#endif NOFLOAT
+       }
+}
diff --git a/lang/cem/cemcom.ansi/LintPars b/lang/cem/cemcom.ansi/LintPars
new file mode 100644 (file)
index 0000000..37266f8
--- /dev/null
@@ -0,0 +1,145 @@
+!File: lint.h
+#define        LINT            1       /* if defined, 'lint' is produced       */
+
+
+!File: pathlength.h
+#define PATHLENGTH     1024    /* max. length of path to file          */
+
+
+!File: errout.h
+#define        ERROUT          STDERR  /* file pointer for writing messages    */
+#define        MAXERR_LINE     5       /* maximum number of error messages given
+                                       on the same input line.         */
+
+
+!File: idfsize.h
+#define        IDFSIZE 64      /* maximum significant length of an identifier  */
+
+
+!File: numsize.h
+#define        NUMSIZE 256     /* maximum length of a numeric constant         */
+
+
+!File: nparams.h
+#define        NPARAMS 32      /* maximum number of parameters of macros       */
+
+
+!File: ifdepth.h
+#define        IFDEPTH 256     /* maximum number of nested if-constructions    */
+
+
+!File: density.h
+#define        DENSITY 2       /* see switch.[ch] for an explanation           */
+
+
+!File: lapbuf.h
+#define        LAPBUF  4096    /* size of macro actual parameter buffer        */
+
+
+!File: strsize.h
+#define ISTRSIZE       32      /* minimum number of bytes allocated for
+                                       storing a string                */
+#define RSTRSIZE       8       /* step size in enlarging the memory for
+                                       the storage of a string         */
+
+
+!File: target_sizes.h
+#define MAXSIZE                8       /* the maximum of the SZ_* constants    */
+
+/* target machine sizes        */
+#define        SZ_CHAR         (arith)1
+#define        SZ_SHORT        (arith)2
+#define SZ_WORD                (arith)4
+#define        SZ_INT          (arith)4
+#define        SZ_LONG         (arith)4
+#ifndef NOFLOAT
+#define        SZ_FLOAT        (arith)4
+#define        SZ_DOUBLE       (arith)8
+#endif NOFLOAT
+#define        SZ_POINTER      (arith)4
+
+/* target machine alignment requirements       */
+#define        AL_CHAR         1
+#define        AL_SHORT        SZ_SHORT
+#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
+
+
+!File: botch_free.h
+#undef BOTCH_FREE      1       /* when defined, botch freed memory, as a check */
+
+
+!File: dataflow.h
+#undef DATAFLOW        1       /* produce some compile-time xref       */
+
+
+!File: debug.h
+#undef DEBUG           1       /* perform various self-tests           */
+
+
+!File: use_tmp.h
+#undef PREPEND_SCOPES  1       /* collect exa, exp, ina and inp commands
+                                       and if USE_TMP is defined let them
+                                       precede the rest of the generated
+                                       compact code    */
+#undef USE_TMP         1       /* use C_insertpart, C_endpart mechanism
+                                       to generate EM-code in the order needed
+                                       for the code-generators. If not defined,
+                                       the old-style peephole optimizer is
+                                       needed. */
+
+
+!File: parbufsize.h
+#define PARBUFSIZE     1024
+
+
+!File: textsize.h
+#define ITEXTSIZE      8       /* 1st piece of memory for repl. text   */
+#define RTEXTSIZE      8       /* stepsize for enlarging repl.text     */
+
+
+!File: inputtype.h
+#define INP_READ_IN_ONE        1       /* read input file in one       */
+
+
+!File: nopp.h
+#undef NOPP            1       /* if NOT defined, use built-int preprocessor */
+
+
+!File: nobitfield.h
+#undef NOBITFIELD      1       /* if NOT defined, implement bitfields  */
+
+
+!File: spec_arith.h
+/* describes internal compiler arithmetics */
+#undef SPECIAL_ARITHMETICS     /* something different from native long */
+
+
+!File: static.h
+#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 */
+
+
+!File: regcount.h
+#undef REGCOUNT                1       /* count occurrences for register messages */
+
+
diff --git a/lang/cem/cemcom.ansi/Makefile b/lang/cem/cemcom.ansi/Makefile
new file mode 100644 (file)
index 0000000..5c131d1
--- /dev/null
@@ -0,0 +1,1091 @@
+# $Header$
+#      M A K E F I L E   F O R   A C K   C - C O M P I L E R
+
+# Machine and environ dependent definitions
+EMHOME = ../../..
+CC = /proj/em/Work/bin/fcc.cc
+CFLOW = cflow
+MAKE = make
+MKDEP = $(EMHOME)/bin/mkdep
+PRID = $(EMHOME)/bin/prid
+CID = $(EMHOME)/bin/cid
+
+# Libraries and EM interface definitions
+SYSLIB = $(EMHOME)/modules/lib/libsystem.a
+EMKLIB = $(EMHOME)/modules/lib/libemk.a $(EMHOME)/lib/em_data.a
+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
+EMMESLIB = $(EMHOME)/modules/lib/libem_mes.a
+EMMESOLIB = $(EMHOME)/modules/lib/libem_mesO.a
+EMMESCELIB = $(EMHOME)/modules/lib/libem_mesCE.a
+MACH = sun3
+EMCELIB = $(EMHOME)/lib/$(MACH)/ce.a \
+               $(EMHOME)/lib/$(MACH)/back.a \
+               $(EMHOME)/modules/lib/libobject.a $(EMHOME)/lib/em_data.a
+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)
+ELIBS = $(INPLIB) $(EMMESLIB) $(EMELIB) $(PRTLIB) $(STRLIB) \
+       $(ALLOCLIB) $(MALLOC) $(SYSLIB)
+OLIBS = $(INPLIB) $(EMMESOLIB) $(EMOLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) \
+       $(ALLOCLIB) $(MALLOC) $(SYSLIB)
+CELIBS = $(INPLIB) $(EMMESCELIB) $(EMCELIB) $(PRTLIB) $(STRLIB) \
+       $(ALLOCLIB) $(MALLOC) $(SYSLIB)
+LLIBS = $(INPLIB) $(EMMESLIB) $(PRTLIB) $(STRLIB) \
+       $(ALLOCLIB) $(MALLOC) $(SYSLIB)
+LIB_INCLUDES = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg
+EM_INCLUDES = -I$(EMHOME)/h
+SYSLLIB = $(EMHOME)/modules/lib/llib-lsystem.ln
+EMKLLIB = $(EMHOME)/modules/lib/llib-lemk.ln
+EMELLIB = $(EMHOME)/modules/lib/llib-leme.ln
+STRLLIB = $(EMHOME)/modules/lib/llib-lstring.ln
+PRTLLIB = $(EMHOME)/modules/lib/llib-lprint.ln
+EMMESLLIB = $(EMHOME)/modules/lib/llib-lem_mes.ln
+INPLLIB = $(EMHOME)/modules/lib/llib-linput.ln
+ALLOCLLIB = $(EMHOME)/modules/lib/llib-lalloc.ln
+#LINTLIBS =
+LINTLIBS = $(EMMESLLIB) $(EMKLLIB) $(PRTLLIB) $(STRLLIB) $(ALLOCLLIB) $(SYSLLIB)
+CURRDIR = 
+
+COPTIONS =
+
+# What parser generator to use and how
+GEN = $(EMHOME)/bin/LLgen
+GENOPTIONS = -v
+
+# Special #defines during compilation
+PROF = #-pg
+CDEFS =        $(EM_INCLUDES) $(LIB_INCLUDES)
+CFLAGS = $(CDEFS) $(COPTIONS) $(PROF) #-O
+LDFLAGS = -i $(PROF)
+
+# Grammar files and their objects
+LSRC = tokenfile.g declar.g statement.g expression.g program.g ival.g
+LCSRC =        tokenfile.c declar.c statement.c expression.c program.c Lpars.c ival.c
+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 \
+       code.c dumpidf.c error.c field.c\
+       tokenname.c LLlex.c LLmessage.c \
+       input.c domacro.c replace.c init.c options.c \
+       skip.c stack.c type.c ch7mon.c label.c eval.c \
+       switch.c conversion.c util.c proto.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 \
+       code.o dumpidf.o error.o field.o\
+       tokenname.o LLlex.o LLmessage.o \
+       input.o domacro.o replace.o init.o options.o \
+       skip.o stack.o type.o ch7mon.o label.o eval.o \
+       switch.o conversion.o util.o proto.o \
+       pragma.o blocks.o dataflow.o Version.o \
+       l_lint.o l_states.o l_misc.o l_ev_ord.o l_outdef.o l_comment.o l_dummy.o
+
+# Objects of other generated C files
+GCSRC =        char.c symbol2str.c next.c
+GOBJ = char.o symbol2str.o next.o
+
+STRSRC = code.str declar.str decspecs.str def.str expr.str field.str \
+       estack.str util.str proto.str replace.str \
+       idf.str macro.str stack.str stmt.str struct.str switch.str type.str \
+       l_brace.str l_state.str l_outdef.str
+# generated source files
+GHSTRSRC = code.h declar.h decspecs.h def.h expr.h field.h \
+       estack.h util.h proto.h replace.h \
+       idf.h macro.h stack.h stmt.h struct.h switch.h type.h \
+       l_brace.h l_state.h l_outdef.h
+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 \
+       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
+
+HSRC = LLlex.h align.h arith.h assert.h atw.h class.h \
+        input.h label.h level.h mes.h sizes.h specials.h \
+        file_info.h tokenname.h l_lint.h
+
+HFILES = $(HSRC) $(GHSRC) $(GHSTRSRC)
+
+# generated files, for 'make clean' only
+GENERATED = tokenfile.g Lpars.h LLfiles LL.output lint.out \
+       print hfiles Cfiles $(GHSRC) $(GSRC) longnames $(LCSRC)
+
+# include files containing ALLOCDEF specifications
+OBJ =  $(COBJ) $(LOBJ) $(GOBJ)
+SRC =  $(CSRC) $(LCSRC) $(GCSRC)
+
+LINT = /usr/bin/lint
+LINTFLAGS =
+
+MYLINT = /usr/star/dick/bin/lint       #../lint
+MYLINTFLAGS = #-xh
+
+#EXCLEXCLEXCLEXCL
+
+.SUFFIXES: .str .h
+.str.h:
+       ./make.allocd <$*.str >$*.h
+
+Main:  Cfiles
+       sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) $(CURRDIR)main ; else EMHOME=$(EMHOME); export EMHOME; ./Resolve main ; fi'
+       @rm -f nmclash.o a.out
+
+Emain: Cfiles
+       sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) $(CURRDIR)emain ; else EMHOME=$(EMHOME); export EMHOME; ./Resolve emain ; fi'
+       @rm -f nmclash.o a.out
+
+Omain: Cfiles
+       rm -f *.o
+       sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) "COPTIONS="-DPEEPHOLE $(CURRDIR)omain ; else EMHOME=$(EMHOME); export EMHOME; ./Resolve omain ; fi'
+       @rm -f nmclash.o a.out
+       mv *.o PEEPHOLE
+
+CEmain:        Cfiles
+       rm -f *.o
+       sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) "COPTIONS="-DCODE_EXPANDER $(CURRDIR)cemain ; else EMHOME=$(EMHOME); export EMHOME; ./Resolve cemain ; fi'
+       @rm -f nmclash.o a.out
+       mv *.o CODE_EXPANDER
+
+Lnt:   Cfiles
+       sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then make "EMHOME="$(EMHOME) $(CURRDIR)lnt ; else EMHOME=$(EMHOME); export EMHOME; ./Resolve lnt ; fi'
+       make "EMHOME="$(EMHOME) $(CURRDIR)lnt
+       @rm -f nmclash.o a.out
+
+install:       Main
+       rm -f $(EMHOME)/lib/em_cemcom $(EMHOME)/man/em_cemcom.6
+       cp $(CURRDIR)main $(EMHOME)/lib/em_cemcom
+       cp $(CURRDIR)cemcom.1 $(EMHOME)/man/em_cemcom.6
+
+Oinstall:      Omain
+       cp $(CURRDIR)omain $(EMHOME)/lib/em_cemcomO
+
+cmp:   Main
+       -cmp $(CURRDIR)main $(EMHOME)/lib/em_cemcom
+       -cmp $(CURRDIR)cemcom.1 $(EMHOME)/man/em_cemcom.6
+
+pr:
+       @pr Makefile make.* char.tab Parameters $(HSRC) $(STRSRC) $(LSRC) $(CSRC)
+
+opr:
+       $(MAKE) pr | opr
+
+clean:
+       rm -f $(OBJ)
+       rm -f $(GENERATED) main
+       (cd .. ; rm -rf Xsrc)
+
+cflow: Cfiles
+       $(CFLOW) $(CDEFS) $(SRC)
+
+lint:  Cfiles
+       sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then $(MAKE) "EMHOME="$(EMHOME) Xlint ; else sh Resolve Xlint ; fi'
+       @rm -f nmclash.o a.out
+
+mylint:        Cfiles
+       sh -c 'if $(CC) nmclash.c > /dev/null 2>&1 ; then $(MAKE) "EMHOME="$(EMHOME) Xmylint ; else sh Resolve Xmylint ; fi'
+       @rm -f nmclash.o a.out
+
+longnames:     $(SRC) $(HFILES)
+       sh -c 'if test -f longnames ; then : ; else touch longnames ; fi ; $(PRID) -l7 longnames $? > Xlongnames ; mv Xlongnames longnames'
+
+# entry points not to be used directly
+
+Cfiles:        hfiles LLfiles $(GENCFILES) $(GSRC) $(GHSRC) Makefile
+       echo $(SRC) $(HFILES) > Cfiles
+
+hfiles: ./make.hfiles Parameters
+       ./make.hfiles Parameters
+       @touch hfiles
+
+LLfiles: $(LSRC)
+       $(GEN) $(GENOPTIONS) $(LSRC)
+       @touch LLfiles
+
+tokenfile.g:   tokenname.c make.tokfile
+       <tokenname.c ./make.tokfile >tokenfile.g
+
+symbol2str.c:  tokenname.c make.tokcase
+       <tokenname.c ./make.tokcase >symbol2str.c
+
+char.c:        char.tab
+       $(EMHOME)/bin/tabgen -fchar.tab >char.c
+
+next.c:        make.next $(STRSRC)
+       ./make.next $(STRSRC) >next.c
+
+code.h:                make.allocd
+declar.h:      make.allocd
+decspecs.h:    make.allocd
+def.h:         make.allocd
+expr.h:                make.allocd
+field.h:       make.allocd
+idf.h:         make.allocd
+macro.h:       make.allocd
+stack.h:       make.allocd
+stmt.h:                make.allocd
+struct.h:      make.allocd
+switch.h:      make.allocd
+type.h:                make.allocd
+estack.h:      make.allocd
+util.h:                make.allocd
+l_brace.h:     make.allocd
+l_state.h:     make.allocd
+l_outdef.h:    make.allocd
+
+depend:        Cfiles
+       sed '/^#AUTOAUTO/,$$d' Makefile >Makefile.new
+       echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >>Makefile.new
+       $(MKDEP) $(SRC) | sed 's/\.c:/.o:/' >>Makefile.new
+       mv Makefile Makefile.old
+       mv Makefile.new Makefile
+
+#INCLINCLINCLINCL
+
+$(CURRDIR)main:        $(OBJ) $(CURRDIR)Makefile
+       $(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(LIBS) -o $(CURRDIR)main 
+       size $(CURRDIR)main
+
+$(CURRDIR)emain:       $(OBJ) $(CURRDIR)Makefile
+       $(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(ELIBS) -o $(CURRDIR)emain 
+       size $(CURRDIR)emain
+
+$(CURRDIR)omain:       $(OBJ) $(CURRDIR)Makefile
+       $(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(OLIBS) -o $(CURRDIR)omain 
+       size $(CURRDIR)omain
+
+$(CURRDIR)cemain:      $(OBJ) $(CURRDIR)Makefile
+       $(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(CELIBS) -o $(CURRDIR)cemain 
+       size $(CURRDIR)cemain
+
+$(CURRDIR)lnt:         $(OBJ) $(CURRDIR)Makefile
+       $(CC) $(COPTIONS) $(LDFLAGS) $(OBJ) $(LLIBS) -o $(CURRDIR)lnt 
+       size $(CURRDIR)lnt
+
+Xlint: $(SRC)
+       $(LINT) $(CDEFS) $(LINTFLAGS) $(SRC)
+
+Xmylint:       $(SRC)
+       $(MYLINT) $(CDEFS) $(MYLINTFLAGS) $(SRC)
+
+#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
+main.o: LLlex.h
+main.o: Lpars.h
+main.o: align.h
+main.o: arith.h
+main.o: debug.h
+main.o: declar.h
+main.o: file_info.h
+main.o: idf.h
+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
+main.o: spec_arith.h
+main.o: specials.h
+main.o: target_sizes.h
+main.o: tokenname.h
+main.o: type.h
+main.o: use_tmp.h
+idf.o: LLlex.h
+idf.o: Lpars.h
+idf.o: align.h
+idf.o: arith.h
+idf.o: assert.h
+idf.o: botch_free.h
+idf.o: debug.h
+idf.o: declar.h
+idf.o: decspecs.h
+idf.o: def.h
+idf.o: file_info.h
+idf.o: idf.h
+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
+idf.o: sizes.h
+idf.o: spec_arith.h
+idf.o: specials.h
+idf.o: stack.h
+idf.o: struct.h
+idf.o: target_sizes.h
+idf.o: type.h
+declarator.o: Lpars.h
+declarator.o: arith.h
+declarator.o: botch_free.h
+declarator.o: debug.h
+declarator.o: declar.h
+declarator.o: def.h
+declarator.o: expr.h
+declarator.o: idf.h
+declarator.o: label.h
+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
+declarator.o: spec_arith.h
+declarator.o: target_sizes.h
+declarator.o: type.h
+decspecs.o: Lpars.h
+decspecs.o: arith.h
+decspecs.o: assert.h
+decspecs.o: debug.h
+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
+struct.o: Lpars.h
+struct.o: align.h
+struct.o: arith.h
+struct.o: assert.h
+struct.o: botch_free.h
+struct.o: debug.h
+struct.o: def.h
+struct.o: field.h
+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
+struct.o: spec_arith.h
+struct.o: stack.h
+struct.o: struct.h
+struct.o: target_sizes.h
+struct.o: type.h
+expr.o: LLlex.h
+expr.o: Lpars.h
+expr.o: arith.h
+expr.o: botch_free.h
+expr.o: declar.h
+expr.o: decspecs.h
+expr.o: def.h
+expr.o: expr.h
+expr.o: file_info.h
+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
+expr.o: target_sizes.h
+expr.o: type.h
+ch7.o: Lpars.h
+ch7.o: arith.h
+ch7.o: assert.h
+ch7.o: debug.h
+ch7.o: def.h
+ch7.o: expr.h
+ch7.o: file_info.h
+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
+ch7.o: struct.h
+ch7.o: type.h
+ch7bin.o: Lpars.h
+ch7bin.o: arith.h
+ch7bin.o: botch_free.h
+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
+ch7bin.o: type.h
+cstoper.o: Lpars.h
+cstoper.o: arith.h
+cstoper.o: assert.h
+cstoper.o: debug.h
+cstoper.o: expr.h
+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
+arith.o: Lpars.h
+arith.o: arith.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
+arith.o: spec_arith.h
+arith.o: target_sizes.h
+arith.o: type.h
+code.o: Lpars.h
+code.o: arith.h
+code.o: assert.h
+code.o: atw.h
+code.o: botch_free.h
+code.o: code.h
+code.o: dataflow.h
+code.o: debug.h
+code.o: declar.h
+code.o: decspecs.h
+code.o: def.h
+code.o: expr.h
+code.o: file_info.h
+code.o: idf.h
+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
+code.o: specials.h
+code.o: stack.h
+code.o: stmt.h
+code.o: target_sizes.h
+code.o: type.h
+code.o: use_tmp.h
+dumpidf.o: Lpars.h
+dumpidf.o: arith.h
+dumpidf.o: debug.h
+dumpidf.o: declar.h
+dumpidf.o: def.h
+dumpidf.o: expr.h
+dumpidf.o: field.h
+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
+dumpidf.o: stack.h
+dumpidf.o: static.h
+dumpidf.o: struct.h
+dumpidf.o: type.h
+error.o: LLlex.h
+error.o: arith.h
+error.o: debug.h
+error.o: def.h
+error.o: errout.h
+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
+field.o: Lpars.h
+field.o: align.h
+field.o: arith.h
+field.o: assert.h
+field.o: code.h
+field.o: debug.h
+field.o: expr.h
+field.o: field.h
+field.o: idf.h
+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
+field.o: target_sizes.h
+field.o: type.h
+tokenname.o: LLlex.h
+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
+LLlex.o: LLlex.h
+LLlex.o: Lpars.h
+LLlex.o: arith.h
+LLlex.o: assert.h
+LLlex.o: class.h
+LLlex.o: debug.h
+LLlex.o: def.h
+LLlex.o: file_info.h
+LLlex.o: idf.h
+LLlex.o: idfsize.h
+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
+LLlex.o: spec_arith.h
+LLlex.o: strsize.h
+LLlex.o: target_sizes.h
+LLmessage.o: LLlex.h
+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
+input.o: input.h
+input.o: inputtype.h
+input.o: nopp.h
+domacro.o: LLlex.h
+domacro.o: Lpars.h
+domacro.o: arith.h
+domacro.o: assert.h
+domacro.o: botch_free.h
+domacro.o: class.h
+domacro.o: debug.h
+domacro.o: file_info.h
+domacro.o: idf.h
+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
+domacro.o: spec_arith.h
+domacro.o: textsize.h
+replace.o: LLlex.h
+replace.o: argbuf.h
+replace.o: arith.h
+replace.o: assert.h
+replace.o: class.h
+replace.o: debug.h
+replace.o: file_info.h
+replace.o: idf.h
+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
+replace.o: pathlength.h
+replace.o: replace.h
+replace.o: spec_arith.h
+replace.o: static.h
+replace.o: strsize.h
+init.o: class.h
+init.o: idf.h
+init.o: macro.h
+init.o: nopp.h
+options.o: align.h
+options.o: arith.h
+options.o: botch_free.h
+options.o: class.h
+options.o: dataflow.h
+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
+options.o: target_sizes.h
+options.o: use_tmp.h
+skip.o: LLlex.h
+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
+stack.o: arith.h
+stack.o: botch_free.h
+stack.o: debug.h
+stack.o: def.h
+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
+stack.o: struct.h
+stack.o: type.h
+type.o: Lpars.h
+type.o: align.h
+type.o: arith.h
+type.o: botch_free.h
+type.o: decspecs.h
+type.o: def.h
+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
+type.o: spec_arith.h
+type.o: target_sizes.h
+type.o: type.h
+ch7mon.o: Lpars.h
+ch7mon.o: arith.h
+ch7mon.o: botch_free.h
+ch7mon.o: def.h
+ch7mon.o: expr.h
+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
+label.o: Lpars.h
+label.o: arith.h
+label.o: def.h
+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
+eval.o: Lpars.h
+eval.o: align.h
+eval.o: arith.h
+eval.o: assert.h
+eval.o: atw.h
+eval.o: code.h
+eval.o: dataflow.h
+eval.o: debug.h
+eval.o: def.h
+eval.o: expr.h
+eval.o: idf.h
+eval.o: label.h
+eval.o: level.h
+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
+eval.o: specials.h
+eval.o: stack.h
+eval.o: target_sizes.h
+eval.o: type.h
+switch.o: Lpars.h
+switch.o: arith.h
+switch.o: assert.h
+switch.o: botch_free.h
+switch.o: code.h
+switch.o: debug.h
+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: nopp.h
+switch.o: spec_arith.h
+switch.o: switch.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
+conversion.o: type.h
+util.o: Lpars.h
+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
+util.o: target_sizes.h
+util.o: use_tmp.h
+util.o: util.h
+proto.o: Lpars.h
+proto.o: align.h
+proto.o: arith.h
+proto.o: assert.h
+proto.o: botch_free.h
+proto.o: debug.h
+proto.o: declar.h
+proto.o: decspecs.h
+proto.o: def.h
+proto.o: expr.h
+proto.o: idf.h
+proto.o: idfsize.h
+proto.o: label.h
+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
+proto.o: spec_arith.h
+proto.o: stack.h
+proto.o: struct.h
+proto.o: target_sizes.h
+proto.o: type.h
+pragma.o: LLlex.h
+pragma.o: Lpars.h
+pragma.o: arith.h
+pragma.o: assert.h
+pragma.o: botch_free.h
+pragma.o: class.h
+pragma.o: debug.h
+pragma.o: file_info.h
+pragma.o: idf.h
+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
+pragma.o: spec_arith.h
+pragma.o: textsize.h
+blocks.o: Lpars.h
+blocks.o: align.h
+blocks.o: arith.h
+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
+blocks.o: target_sizes.h
+dataflow.o: dataflow.h
+l_lint.o: LLlex.h
+l_lint.o: Lpars.h
+l_lint.o: arith.h
+l_lint.o: assert.h
+l_lint.o: code.h
+l_lint.o: debug.h
+l_lint.o: def.h
+l_lint.o: expr.h
+l_lint.o: file_info.h
+l_lint.o: idf.h
+l_lint.o: interface.h
+l_lint.o: l_lint.h
+l_lint.o: l_outdef.h
+l_lint.o: l_state.h
+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
+l_lint.o: type.h
+l_states.o: LLlex.h
+l_states.o: Lpars.h
+l_states.o: arith.h
+l_states.o: assert.h
+l_states.o: code.h
+l_states.o: debug.h
+l_states.o: def.h
+l_states.o: expr.h
+l_states.o: file_info.h
+l_states.o: idf.h
+l_states.o: interface.h
+l_states.o: l_brace.h
+l_states.o: l_comment.h
+l_states.o: l_lint.h
+l_states.o: l_outdef.h
+l_states.o: l_state.h
+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
+l_states.o: type.h
+l_misc.o: LLlex.h
+l_misc.o: Lpars.h
+l_misc.o: arith.h
+l_misc.o: code.h
+l_misc.o: def.h
+l_misc.o: expr.h
+l_misc.o: file_info.h
+l_misc.o: idf.h
+l_misc.o: interface.h
+l_misc.o: l_state.h
+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
+l_misc.o: type.h
+l_ev_ord.o: LLlex.h
+l_ev_ord.o: Lpars.h
+l_ev_ord.o: arith.h
+l_ev_ord.o: assert.h
+l_ev_ord.o: code.h
+l_ev_ord.o: debug.h
+l_ev_ord.o: def.h
+l_ev_ord.o: expr.h
+l_ev_ord.o: file_info.h
+l_ev_ord.o: idf.h
+l_ev_ord.o: interface.h
+l_ev_ord.o: l_lint.h
+l_ev_ord.o: l_state.h
+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
+l_ev_ord.o: type.h
+l_outdef.o: LLlex.h
+l_outdef.o: Lpars.h
+l_outdef.o: arith.h
+l_outdef.o: assert.h
+l_outdef.o: code.h
+l_outdef.o: debug.h
+l_outdef.o: def.h
+l_outdef.o: expr.h
+l_outdef.o: field.h
+l_outdef.o: file_info.h
+l_outdef.o: idf.h
+l_outdef.o: interface.h
+l_outdef.o: l_class.h
+l_outdef.o: l_comment.h
+l_outdef.o: l_lint.h
+l_outdef.o: l_outdef.h
+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
+l_outdef.o: struct.h
+l_outdef.o: type.h
+l_comment.o: arith.h
+l_comment.o: interface.h
+l_comment.o: l_comment.h
+l_comment.o: l_state.h
+l_comment.o: lint.h
+l_comment.o: spec_arith.h
+l_dummy.o: arith.h
+l_dummy.o: label.h
+l_dummy.o: lint.h
+l_dummy.o: spec_arith.h
+tokenfile.o: Lpars.h
+declar.o: LLlex.h
+declar.o: Lpars.h
+declar.o: arith.h
+declar.o: code.h
+declar.o: debug.h
+declar.o: declar.h
+declar.o: decspecs.h
+declar.o: def.h
+declar.o: expr.h
+declar.o: field.h
+declar.o: file_info.h
+declar.o: idf.h
+declar.o: l_lint.h
+declar.o: l_state.h
+declar.o: label.h
+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
+declar.o: spec_arith.h
+declar.o: struct.h
+declar.o: target_sizes.h
+declar.o: type.h
+statement.o: LLlex.h
+statement.o: Lpars.h
+statement.o: arith.h
+statement.o: botch_free.h
+statement.o: code.h
+statement.o: debug.h
+statement.o: def.h
+statement.o: expr.h
+statement.o: file_info.h
+statement.o: idf.h
+statement.o: l_lint.h
+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
+statement.o: type.h
+expression.o: LLlex.h
+expression.o: Lpars.h
+expression.o: arith.h
+expression.o: code.h
+expression.o: expr.h
+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
+program.o: LLlex.h
+program.o: Lpars.h
+program.o: arith.h
+program.o: code.h
+program.o: declar.h
+program.o: decspecs.h
+program.o: def.h
+program.o: expr.h
+program.o: file_info.h
+program.o: idf.h
+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
+Lpars.o: Lpars.h
+ival.o: LLlex.h
+ival.o: Lpars.h
+ival.o: arith.h
+ival.o: assert.h
+ival.o: debug.h
+ival.o: def.h
+ival.o: estack.h
+ival.o: expr.h
+ival.o: field.h
+ival.o: file_info.h
+ival.o: idf.h
+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
+ival.o: spec_arith.h
+ival.o: struct.h
+ival.o: target_sizes.h
+ival.o: type.h
+char.o: class.h
+symbol2str.o: Lpars.h
diff --git a/lang/cem/cemcom.ansi/Makefile.erik b/lang/cem/cemcom.ansi/Makefile.erik
new file mode 100644 (file)
index 0000000..195e07f
--- /dev/null
@@ -0,0 +1,718 @@
+# $Header$
+#      M A K E F I L E   F O R   A C K   C - C O M P I L E R
+
+# Machine and environ dependent definitions
+EMHOME =       /usr/em#                        # ACK tree on this machine
+DESTINATION =  /user1/$$USER/bin#              # where to put the stuff
+MKDEP =                $(EMHOME)/bin/mkdep#            # dependency generator
+MAP =
+#MAP = -DInsertFile=ins_file -DInsertText=ins_text# bug in m68k2 back end
+SIM =          /user1/dick/bin/sim#            # Dicks sim program
+LINT =         /usr/new/lint
+
+# Libraries and EM interface definitions
+SYSLIB =       $(EMHOME)/modules/lib/libsystem.a
+EMKLIB =       $(EMHOME)/modules/lib/libemk.a
+EMELIB =       $(EMHOME)/modules/lib/libeme.a $(EMHOME)/lib/em_data.a
+STRLIB =       $(EMHOME)/modules/lib/libstring.a
+PRTLIB =       $(EMHOME)/modules/lib/libprint.a
+EMMESLIB =     $(EMHOME)/modules/lib/libem_mes.a
+INPLIB =       $(EMHOME)/modules/lib/libinput.a
+ALLOCLIB =     $(EMHOME)/modules/lib/liballoc.a
+MALLOC =       $(EMHOME)/modules/lib/malloc.o
+#CH3LIB =      $(EMHOME)/modules/lib/libch3.a
+CH3LIB =
+LIBS =         $(INPLIB) $(CH3LIB) $(EMMESLIB) $(EMKLIB) \
+               $(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB)
+ELIBS =                $(INPLIB) $(CH3LIB) $(EMMESLIB) $(EMELIB) \
+               $(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(SYSLIB)
+LIB_INCLUDES = -I$(EMHOME)/modules/h -I$(EMHOME)/modules/pkg
+EM_INCLUDES =  -I$(EMHOME)/h
+SYSLLIB =      $(EMHOME)/modules/lib/llib-lsys.ln
+EMKLLIB =      $(EMHOME)/modules/lib/llib-lemk.ln
+EMELLIB =      $(EMHOME)/modules/lib/llib-leme.ln
+STRLLIB =      $(EMHOME)/modules/lib/llib-lstr.ln
+PRTLLIB =      $(EMHOME)/modules/lib/llib-lprint.ln
+EMMESLLIB =    $(EMHOME)/modules/lib/llib-lmes.ln
+INPLLIB =      $(EMHOME)/modules/lib/llib-linput.ln
+CH3LLIB =      $(EMHOME)/modules/lib/llib-lch3.ln
+ALLOCLLIB =    $(EMHOME)/modules/lib/llib-alloc.ln
+LINTLIBS =
+#LINTLIBS =    $(CH3LLIB) $(INPLLIB) $(EMMESLLIB) $(EMKLLIB) \
+#              $(PRTLLIB) $(STRLLIB) $(SYSLLIB) $(ALLOCLLIB)
+
+# Where to install the compiler and its driver
+CEMCOM =       $(DESTINATION)/cemcom
+DRIVER =       $(DESTINATION)/cem
+
+# What C compiler to use and how
+# CC = $(ACK) -.c
+# CC = CC
+# CC = /bin/cc
+COPTIONS =
+
+# What parser generator to use and how
+GEN =          $(EMHOME)/bin/LLgen
+GENOPTIONS =   -vv
+
+# Special #defines during compilation
+CDEFS =                $(MAP) $(EM_INCLUDES) $(LIB_INCLUDES)
+CFLAGS =       $(CDEFS) $(COPTIONS) -O# we cannot pass the COPTIONS to lint!
+
+# Grammar files and their objects
+LSRC = tokenfile.g declar.g statement.g expression.g program.g ival.g
+GLCSRC = tokenfile.c declar.c statement.c expression.c program.c Lpars.c ival.c
+LOBJ = tokenfile.o declar.o statement.o expression.o program.o Lpars.o ival.o
+
+CSRC =  main.c idf.c declarator.c decspecs.c struct.c \
+        expr.c ch7.c ch7bin.c cstoper.c arith.c \
+        asm.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 \
+        scan.c skip.c stack.c type.c ch7mon.c label.c eval.c \
+        switch.c conversion.c util.c \
+        blocks.c dataflow.c Version.c
+# Objects of hand-written C files
+COBJ = main.o idf.o declarator.o decspecs.o struct.o \
+       expr.o ch7.o ch7bin.o cstoper.o arith.o \
+       asm.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 \
+       scan.o skip.o stack.o type.o ch7mon.o label.o eval.o \
+       switch.o conversion.o util.o \
+       blocks.o dataflow.o Version.o
+
+# Objects of other generated C files
+GCSRC = char.c symbol2str.c next.c
+GOBJ = char.o symbol2str.o next.o
+
+# generated source files
+GSRC = char.c symbol2str.c next.c \
+       code.h declar.h decspecs.h def.h expr.h field.h  estack.h \
+       idf.h macro.h stack.h stmt.h struct.h switch.h type.h util.h
+
+# .h files generated by `make hfiles'; PLEASE KEEP THIS UP-TO-DATE!
+GHSRC = botch_free.h dataflow.h debug.h density.h errout.h \
+       idfsize.h ifdepth.h inputtype.h inumlength.h lapbuf.h \
+       nobitfield.h nofloat.h nopp.h noRoption.h nocross.h \
+       nparams.h numsize.h parbufsize.h pathlength.h \
+       strsize.h target_sizes.h textsize.h use_tmp.h spec_arith.h static.h \
+       reg_count.h
+
+# Other generated files, for 'make clean' only
+GENERATED = tokenfile.g Lpars.h LLfiles LL.output lint.out \
+       print Xref lxref hfiles cfiles $(GLCSRC)
+
+# include files containing ALLOCDEF specifications
+NEXTFILES = code.str declar.str decspecs.str def.str expr.str field.str \
+       estack.str util.str \
+       idf.str macro.str stack.str stmt.str struct.str switch.str type.str
+
+.SUFFIXES: .str .h
+.str.h:
+       ./make.allocd <$*.str >$*.h
+
+all:   cc
+
+cc:
+       make "EMHOME="$(EMHOME) "CC=$(CC)" hfiles
+       make "EMHOME="$(EMHOME) "CC=$(CC)" LLfiles
+       make "EMHOME="$(EMHOME) "CC=$(CC)" main
+
+cem:   cem.c
+       $(CC) -O cem.c $(SYSLIB) -o cem
+
+lint.cem: cem.c
+       $(LINT) -bx cem.c
+
+hfiles: ./make.hfiles Parameters
+       ./make.hfiles Parameters
+       @touch hfiles
+
+LLfiles: $(LSRC)
+       $(GEN) $(GENOPTIONS) $(LSRC)
+       @touch LLfiles
+
+tokenfile.g:   tokenname.c make.tokfile
+       <tokenname.c ./make.tokfile >tokenfile.g
+
+symbol2str.c:  tokenname.c make.tokcase
+       <tokenname.c ./make.tokcase >symbol2str.c
+
+char.c:        char.tab
+       $(EMHOME)/bin/tabgen -fchar.tab >char.c
+
+next.c:        make.next $(NEXTFILES)
+       ./make.next $(NEXTFILES) >next.c
+
+code.h:                make.allocd
+declar.h:      make.allocd
+decspecs.h:    make.allocd
+def.h:         make.allocd
+estack.h:      make.allocd
+expr.h:                make.allocd
+field.h:       make.allocd
+idf.h:         make.allocd
+macro.h:       make.allocd
+stack.h:       make.allocd
+stmt.h:                make.allocd
+struct.h:      make.allocd
+switch.h:      make.allocd
+type.h:                make.allocd
+util.h:                make.allocd
+
+# Objects needed for 'main'
+OBJ =  $(COBJ) $(LOBJ) $(GOBJ)
+SRC =  $(CSRC) $(LCSRC) $(GCSRC)
+
+main:  $(OBJ) Makefile.erik
+       $(CC) $(COPTIONS) $(LFLAGS) $(OBJ) $(LIBS) -o main 
+       size main
+
+emain: $(OBJ) Makefile.erik
+       $(CC) $(COPTIONS) $(LFLAGS) $(OBJ) $(ELIBS) -o emain 
+       size emain
+
+cfiles: hfiles LLfiles $(GSRC)
+       @touch cfiles
+
+install: main cem
+       cp main $(CEMCOM)
+       cp cem $(DRIVER)
+
+print: files
+       pr `cat files` > print
+
+tags:  cfiles
+       ctags $(SRC)
+
+shar:  files
+       shar `cat files`
+
+listcfiles:
+       @echo $(SRC)
+
+listobjects:
+       @echo $(OBJ)
+
+depend:        cfiles
+       sed '/^#AUTOAUTO/,$$d' Makefile.erik >Makefile.erik.new
+       echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >>Makefile.erik.new
+       $(MKDEP) $(SRC) | sed 's/\.c:/.o:/' >>Makefile.erik.new
+       mv Makefile.erik Makefile.erik.old
+       mv Makefile.erik.new Makefile.erik
+       
+xref:
+       ctags -x `grep "\.[ch]" files`|sed "s/).*/)/">Xref
+       
+lxref:
+       lxref $(OBJ) -lc >lxref
+
+lint:  lint.main lint.cem
+
+lint.main: cfiles
+       $(LINT) -bx $(CDEFS) $(SRC) $(LINTLIBS) >lint.out
+
+cchk:
+       cchk $(SRC)
+
+clean:
+       rm -f $(LCSRC) $(OBJ) $(GENERATED) $(GSRC) $(GHSRC)
+
+sim:   cfiles
+       $(SIM) $(SIMFLAGS) $(CSRC) $(GSRC) $(LSRC)
+
+#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
+main.o: LLlex.h
+main.o: Lpars.h
+main.o: align.h
+main.o: arith.h
+main.o: debug.h
+main.o: declar.h
+main.o: file_info.h
+main.o: idf.h
+main.o: input.h
+main.o: inputtype.h
+main.o: level.h
+main.o: noRoption.h
+main.o: nobitfield.h
+main.o: nocross.h
+main.o: nofloat.h
+main.o: nopp.h
+main.o: sizes.h
+main.o: spec_arith.h
+main.o: specials.h
+main.o: target_sizes.h
+main.o: tokenname.h
+main.o: type.h
+main.o: use_tmp.h
+idf.o: LLlex.h
+idf.o: Lpars.h
+idf.o: align.h
+idf.o: arith.h
+idf.o: assert.h
+idf.o: botch_free.h
+idf.o: debug.h
+idf.o: declar.h
+idf.o: decspecs.h
+idf.o: def.h
+idf.o: file_info.h
+idf.o: idf.h
+idf.o: idfsize.h
+idf.o: label.h
+idf.o: level.h
+idf.o: noRoption.h
+idf.o: nobitfield.h
+idf.o: nocross.h
+idf.o: nofloat.h
+idf.o: nopp.h
+idf.o: sizes.h
+idf.o: spec_arith.h
+idf.o: specials.h
+idf.o: stack.h
+idf.o: struct.h
+idf.o: target_sizes.h
+idf.o: type.h
+declarator.o: Lpars.h
+declarator.o: arith.h
+declarator.o: botch_free.h
+declarator.o: declar.h
+declarator.o: expr.h
+declarator.o: idf.h
+declarator.o: label.h
+declarator.o: nobitfield.h
+declarator.o: nocross.h
+declarator.o: nofloat.h
+declarator.o: nopp.h
+declarator.o: sizes.h
+declarator.o: spec_arith.h
+declarator.o: target_sizes.h
+declarator.o: type.h
+decspecs.o: Lpars.h
+decspecs.o: arith.h
+decspecs.o: decspecs.h
+decspecs.o: def.h
+decspecs.o: level.h
+decspecs.o: noRoption.h
+decspecs.o: nobitfield.h
+decspecs.o: nofloat.h
+decspecs.o: spec_arith.h
+decspecs.o: type.h
+struct.o: LLlex.h
+struct.o: Lpars.h
+struct.o: align.h
+struct.o: arith.h
+struct.o: assert.h
+struct.o: botch_free.h
+struct.o: debug.h
+struct.o: def.h
+struct.o: field.h
+struct.o: file_info.h
+struct.o: idf.h
+struct.o: level.h
+struct.o: noRoption.h
+struct.o: nobitfield.h
+struct.o: nocross.h
+struct.o: nofloat.h
+struct.o: nopp.h
+struct.o: sizes.h
+struct.o: spec_arith.h
+struct.o: stack.h
+struct.o: struct.h
+struct.o: target_sizes.h
+struct.o: type.h
+expr.o: LLlex.h
+expr.o: Lpars.h
+expr.o: arith.h
+expr.o: botch_free.h
+expr.o: declar.h
+expr.o: decspecs.h
+expr.o: def.h
+expr.o: expr.h
+expr.o: file_info.h
+expr.o: idf.h
+expr.o: label.h
+expr.o: level.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
+expr.o: target_sizes.h
+expr.o: type.h
+ch7.o: Lpars.h
+ch7.o: arith.h
+ch7.o: assert.h
+ch7.o: debug.h
+ch7.o: def.h
+ch7.o: expr.h
+ch7.o: idf.h
+ch7.o: label.h
+ch7.o: nobitfield.h
+ch7.o: nofloat.h
+ch7.o: nopp.h
+ch7.o: spec_arith.h
+ch7.o: struct.h
+ch7.o: type.h
+ch7bin.o: Lpars.h
+ch7bin.o: arith.h
+ch7bin.o: botch_free.h
+ch7bin.o: expr.h
+ch7bin.o: idf.h
+ch7bin.o: label.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
+ch7bin.o: type.h
+cstoper.o: Lpars.h
+cstoper.o: arith.h
+cstoper.o: assert.h
+cstoper.o: debug.h
+cstoper.o: expr.h
+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
+arith.o: Lpars.h
+arith.o: arith.h
+arith.o: botch_free.h
+arith.o: expr.h
+arith.o: field.h
+arith.o: idf.h
+arith.o: label.h
+arith.o: mes.h
+arith.o: noRoption.h
+arith.o: nobitfield.h
+arith.o: nofloat.h
+arith.o: nopp.h
+arith.o: spec_arith.h
+arith.o: type.h
+code.o: Lpars.h
+code.o: arith.h
+code.o: assert.h
+code.o: atw.h
+code.o: botch_free.h
+code.o: code.h
+code.o: dataflow.h
+code.o: debug.h
+code.o: declar.h
+code.o: decspecs.h
+code.o: def.h
+code.o: expr.h
+code.o: file_info.h
+code.o: idf.h
+code.o: label.h
+code.o: level.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
+code.o: specials.h
+code.o: stack.h
+code.o: stmt.h
+code.o: target_sizes.h
+code.o: type.h
+code.o: use_tmp.h
+dumpidf.o: Lpars.h
+dumpidf.o: arith.h
+dumpidf.o: debug.h
+dumpidf.o: def.h
+dumpidf.o: expr.h
+dumpidf.o: field.h
+dumpidf.o: idf.h
+dumpidf.o: label.h
+dumpidf.o: nobitfield.h
+dumpidf.o: nofloat.h
+dumpidf.o: nopp.h
+dumpidf.o: spec_arith.h
+dumpidf.o: stack.h
+dumpidf.o: static.h
+dumpidf.o: struct.h
+dumpidf.o: type.h
+error.o: LLlex.h
+error.o: arith.h
+error.o: debug.h
+error.o: errout.h
+error.o: expr.h
+error.o: file_info.h
+error.o: label.h
+error.o: nofloat.h
+error.o: nopp.h
+error.o: spec_arith.h
+error.o: tokenname.h
+field.o: Lpars.h
+field.o: align.h
+field.o: arith.h
+field.o: assert.h
+field.o: code.h
+field.o: debug.h
+field.o: expr.h
+field.o: field.h
+field.o: idf.h
+field.o: label.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
+field.o: target_sizes.h
+field.o: type.h
+tokenname.o: LLlex.h
+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
+LLlex.o: LLlex.h
+LLlex.o: Lpars.h
+LLlex.o: arith.h
+LLlex.o: assert.h
+LLlex.o: class.h
+LLlex.o: debug.h
+LLlex.o: def.h
+LLlex.o: file_info.h
+LLlex.o: idf.h
+LLlex.o: idfsize.h
+LLlex.o: input.h
+LLlex.o: nocross.h
+LLlex.o: nofloat.h
+LLlex.o: nopp.h
+LLlex.o: numsize.h
+LLlex.o: sizes.h
+LLlex.o: spec_arith.h
+LLlex.o: strsize.h
+LLlex.o: target_sizes.h
+LLmessage.o: LLlex.h
+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
+input.o: input.h
+input.o: inputtype.h
+input.o: nopp.h
+domacro.o: LLlex.h
+domacro.o: Lpars.h
+domacro.o: arith.h
+domacro.o: assert.h
+domacro.o: botch_free.h
+domacro.o: class.h
+domacro.o: debug.h
+domacro.o: file_info.h
+domacro.o: idf.h
+domacro.o: idfsize.h
+domacro.o: ifdepth.h
+domacro.o: input.h
+domacro.o: interface.h
+domacro.o: macro.h
+domacro.o: nofloat.h
+domacro.o: nopp.h
+domacro.o: nparams.h
+domacro.o: parbufsize.h
+domacro.o: spec_arith.h
+domacro.o: textsize.h
+replace.o: LLlex.h
+replace.o: arith.h
+replace.o: assert.h
+replace.o: class.h
+replace.o: debug.h
+replace.o: file_info.h
+replace.o: idf.h
+replace.o: input.h
+replace.o: interface.h
+replace.o: macro.h
+replace.o: nofloat.h
+replace.o: nopp.h
+replace.o: pathlength.h
+replace.o: spec_arith.h
+replace.o: static.h
+replace.o: strsize.h
+init.o: class.h
+init.o: idf.h
+init.o: interface.h
+init.o: macro.h
+init.o: nopp.h
+options.o: align.h
+options.o: arith.h
+options.o: botch_free.h
+options.o: class.h
+options.o: dataflow.h
+options.o: idf.h
+options.o: idfsize.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
+options.o: target_sizes.h
+options.o: use_tmp.h
+scan.o: class.h
+scan.o: idf.h
+scan.o: input.h
+scan.o: interface.h
+scan.o: lapbuf.h
+scan.o: macro.h
+scan.o: nopp.h
+scan.o: nparams.h
+skip.o: LLlex.h
+skip.o: arith.h
+skip.o: class.h
+skip.o: file_info.h
+skip.o: input.h
+skip.o: interface.h
+skip.o: nofloat.h
+skip.o: nopp.h
+skip.o: spec_arith.h
+stack.o: Lpars.h
+stack.o: arith.h
+stack.o: botch_free.h
+stack.o: debug.h
+stack.o: def.h
+stack.o: idf.h
+stack.o: level.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
+stack.o: struct.h
+stack.o: type.h
+type.o: Lpars.h
+type.o: align.h
+type.o: arith.h
+type.o: botch_free.h
+type.o: def.h
+type.o: idf.h
+type.o: nobitfield.h
+type.o: nocross.h
+type.o: nofloat.h
+type.o: nopp.h
+type.o: sizes.h
+type.o: spec_arith.h
+type.o: target_sizes.h
+type.o: type.h
+ch7mon.o: Lpars.h
+ch7mon.o: arith.h
+ch7mon.o: botch_free.h
+ch7mon.o: def.h
+ch7mon.o: expr.h
+ch7mon.o: idf.h
+ch7mon.o: label.h
+ch7mon.o: nobitfield.h
+ch7mon.o: nofloat.h
+ch7mon.o: nopp.h
+ch7mon.o: spec_arith.h
+ch7mon.o: type.h
+label.o: Lpars.h
+label.o: arith.h
+label.o: def.h
+label.o: idf.h
+label.o: label.h
+label.o: level.h
+label.o: noRoption.h
+label.o: nobitfield.h
+label.o: nofloat.h
+label.o: nopp.h
+label.o: spec_arith.h
+label.o: type.h
+eval.o: Lpars.h
+eval.o: align.h
+eval.o: arith.h
+eval.o: assert.h
+eval.o: atw.h
+eval.o: code.h
+eval.o: dataflow.h
+eval.o: debug.h
+eval.o: def.h
+eval.o: expr.h
+eval.o: idf.h
+eval.o: label.h
+eval.o: level.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
+eval.o: specials.h
+eval.o: stack.h
+eval.o: target_sizes.h
+eval.o: type.h
+switch.o: Lpars.h
+switch.o: arith.h
+switch.o: assert.h
+switch.o: botch_free.h
+switch.o: code.h
+switch.o: debug.h
+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: nopp.h
+switch.o: spec_arith.h
+switch.o: switch.h
+switch.o: type.h
+conversion.o: Lpars.h
+conversion.o: arith.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
+conversion.o: type.h
+util.o: Lpars.h
+util.o: align.h
+util.o: def.h
+util.o: nocross.h
+util.o: nofloat.h
+util.o: regcount.h
+util.o: sizes.h
+util.o: stack.h
+util.o: target_sizes.h
+util.o: use_tmp.h
+util.o: util.h
+blocks.o: Lpars.h
+blocks.o: align.h
+blocks.o: arith.h
+blocks.o: atw.h
+blocks.o: label.h
+blocks.o: nocross.h
+blocks.o: nofloat.h
+blocks.o: sizes.h
+blocks.o: spec_arith.h
+blocks.o: stack.h
+blocks.o: target_sizes.h
+dataflow.o: dataflow.h
+char.o: class.h
+symbol2str.o: Lpars.h
diff --git a/lang/cem/cemcom.ansi/Resolve b/lang/cem/cemcom.ansi/Resolve
new file mode 100755 (executable)
index 0000000..5e15581
--- /dev/null
@@ -0,0 +1,67 @@
+: create a directory Xsrc with name clashes resolved
+: and run make in that directory
+: '$Header$'
+
+case $# in
+1)     
+       ;;
+*)     echo "$0: one argument expected" 1>&2
+       exit 1
+       ;;
+esac
+PW=`pwd`
+options=
+case $1 in
+main|emain|lnt)
+       target=$PW/$1
+       ;;
+omain)
+       target=$PW/$1
+       options=-DPEEPHOLE
+       ;;
+cemain)
+       target=$PW/$1
+       options=-DCODE_EXPANDER
+       ;;
+Xlint)
+       target=$1
+       ;;
+*)     echo "$0: $1: Illegal argument" 1>&2
+       exit 1
+       ;;
+esac
+if test -d ../Xsrc
+then
+       :
+else   mkdir ../Xsrc
+fi
+make EMHOME=$EMHOME longnames
+: remove code generating routines from the clashes list as they are defines.
+: code generating routine names start with C_
+sed '/^C_/d' < longnames > tmp$$
+cclash -c -l7 tmp$$ > ../Xsrc/Xclashes
+rm -f tmp$$
+cd ../Xsrc
+if cmp -s Xclashes clashes
+then
+       :
+else
+       mv Xclashes clashes
+fi
+rm -f Makefile
+for i in `cat $PW/Cfiles`
+do
+       cat >> Makefile <<EOF
+
+$i:    clashes $PW/$i
+       cid -Fclashes < $PW/$i > $i
+EOF
+done
+make EMHOME=$EMHOME `cat $PW/Cfiles`
+rm -f Makefile
+ed - $PW/Makefile <<'EOF'
+/^#EXCLEXCL/,/^#INCLINCL/d
+w Makefile
+q
+EOF
+make EMHOME=$EMHOME COPTIONS=$options CURRDIR=$PW/ $target
diff --git a/lang/cem/cemcom.ansi/SmallPars b/lang/cem/cemcom.ansi/SmallPars
new file mode 100644 (file)
index 0000000..fb0bf2a
--- /dev/null
@@ -0,0 +1,145 @@
+!File: lint.h
+#undef LINT            1       /* if defined, 'lint' is produced       */
+
+
+!File: pathlength.h
+#define PATHLENGTH     1024    /* max. length of path to file          */
+
+
+!File: errout.h
+#define        ERROUT          STDERR  /* file pointer for writing messages    */
+#define        MAXERR_LINE     5       /* maximum number of error messages given
+                                       on the same input line.         */
+
+
+!File: idfsize.h
+#define        IDFSIZE 64      /* maximum significant length of an identifier  */
+
+
+!File: numsize.h
+#define        NUMSIZE 256     /* maximum length of a numeric constant         */
+
+
+!File: nparams.h
+#define        NPARAMS 32      /* maximum number of parameters of macros       */
+
+
+!File: ifdepth.h
+#define        IFDEPTH 256     /* maximum number of nested if-constructions    */
+
+
+!File: density.h
+#define        DENSITY 2       /* see switch.[ch] for an explanation           */
+
+
+!File: lapbuf.h
+#define        LAPBUF  4096    /* size of macro actual parameter buffer        */
+
+
+!File: strsize.h
+#define ISTRSIZE       32      /* minimum number of bytes allocated for
+                                       storing a string                */
+#define RSTRSIZE       8       /* step size in enlarging the memory for
+                                       the storage of a string         */
+
+
+!File: target_sizes.h
+#define MAXSIZE                8       /* the maximum of the SZ_* constants    */
+
+/* target machine sizes        */
+#define        SZ_CHAR         (arith)1
+#define        SZ_SHORT        (arith)2
+#define SZ_WORD                (arith)4
+#define        SZ_INT          (arith)4
+#define        SZ_LONG         (arith)4
+#ifndef NOFLOAT
+#define        SZ_FLOAT        (arith)4
+#define        SZ_DOUBLE       (arith)8
+#endif NOFLOAT
+#define        SZ_POINTER      (arith)4
+
+/* target machine alignment requirements       */
+#define        AL_CHAR         1
+#define        AL_SHORT        SZ_SHORT
+#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
+
+
+!File: botch_free.h
+#undef BOTCH_FREE      1       /* when defined, botch freed memory, as a check */
+
+
+!File: dataflow.h
+#undef DATAFLOW        1       /* produce some compile-time xref       */
+
+
+!File: debug.h
+#undef DEBUG           1       /* perform various self-tests           */
+
+
+!File: use_tmp.h
+#undef PREPEND_SCOPES  1       /* collect exa, exp, ina and inp commands
+                                       and if USE_TMP is defined let them
+                                       precede the rest of the generated
+                                       compact code    */
+#undef USE_TMP         1       /* use C_insertpart, C_endpart mechanism
+                                       to generate EM-code in the order needed
+                                       for the code-generators. If not defined,
+                                       the old-style peephole optimizer is
+                                       needed. */
+
+
+!File: parbufsize.h
+#define PARBUFSIZE     1024
+
+
+!File: textsize.h
+#define ITEXTSIZE      8       /* 1st piece of memory for repl. text   */
+#define RTEXTSIZE      8       /* stepsize for enlarging repl.text     */
+
+
+!File: inputtype.h
+#undef INP_READ_IN_ONE 1       /* read input file in one       */
+
+
+!File: nopp.h
+#define NOPP           1       /* if NOT defined, use built-int preprocessor */
+
+
+!File: nobitfield.h
+#undef NOBITFIELD      1       /* if NOT defined, implement bitfields  */
+
+
+!File: spec_arith.h
+/* describes internal compiler arithmetics */
+#undef SPECIAL_ARITHMETICS     /* something different from native long */
+
+
+!File: static.h
+#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 */
+
+
+!File: regcount.h
+#undef REGCOUNT                1       /* count occurrences for register messages */
+
+
diff --git a/lang/cem/cemcom.ansi/Version.c b/lang/cem/cemcom.ansi/Version.c
new file mode 100644 (file)
index 0000000..c10d537
--- /dev/null
@@ -0,0 +1,8 @@
+/* $Header$ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#ifndef        lint
+static char Version[] = "ACK CEM compiler Version 3.1";
+#endif lint
diff --git a/lang/cem/cemcom.ansi/align.h b/lang/cem/cemcom.ansi/align.h
new file mode 100644 (file)
index 0000000..470c141
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*      A L I G N M E N T   D E F I N I T I O N S      */
+
+#include "nofloat.h"
+#include "nocross.h"
+#include "target_sizes.h"
+
+#ifndef NOCROSS
+extern int
+       short_align, word_align, int_align, long_align,
+#ifndef NOFLOAT
+       float_align, double_align, lngdbl_align,
+#endif NOFLOAT
+       pointer_align,
+       struct_align, union_align;
+#else NOCROSS
+#define short_align    ((int)AL_SHORT)
+#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)
+#endif NOCROSS
+
+extern arith align();
diff --git a/lang/cem/cemcom.ansi/arith.c b/lang/cem/cemcom.ansi/arith.c
new file mode 100644 (file)
index 0000000..470aa20
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     A R I T H M E T I C   C O N V E R S I O N S      */
+
+/*     This file contains the routines for the various conversions that
+       may befall operands in C. It is structurally a mess, but I haven't
+       decided yet whether I can't find the right structure or the
+       semantics of C is a mess.
+*/
+
+#include       <alloc.h>
+#include       "lint.h"
+#include       "nofloat.h"
+#include       "nobitfield.h"
+#include       "idf.h"
+#include       "arith.h"
+#include       "sizes.h"
+#include       "type.h"
+#include       "proto.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "Lpars.h"
+#include       "field.h"
+#include       "mes.h"
+#include       "noRoption.h"
+
+extern char *symbol2str();
+extern char options[];
+
+arithbalance(e1p, oper, e2p)   /* RM 6.6 */
+       register struct expr **e1p, **e2p;
+       int oper;
+{
+       /*      The expressions *e1p and *e2p are balanced to be operands
+               of the arithmetic operator oper.
+       */
+       register int t1, t2, u1, u2;
+
+       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.
+       */
+       if (t1 == LNGDBL) {
+               if (t2 != LNGDBL)
+                       int2float(e2p, lngdbl_type);
+               return;
+       } else if (t2 == LNGDBL) {
+               if (t1 != LNGDBL)
+                       int2float(e1p, lngdbl_type);
+               return;
+       }
+
+       /*      If any operand has the type double, the other operand
+               is converted to double.
+       */
+       if (t1 == DOUBLE) {
+               if (t2 != DOUBLE)
+                       int2float(e2p, double_type);
+               return;
+       } else if (t2 == DOUBLE) {
+               if (t1 != DOUBLE)
+                       int2float(e1p, double_type);
+               return;
+       }
+
+       /*      If any operand has the type float, the other operand
+               is converted to float.
+       */
+       if (t1 == FLOAT) {
+               if (t2 != FLOAT)
+                       int2float(e2p, float_type);
+               return;
+       } else if (t2 == FLOAT) {
+               if (t1 != FLOAT)
+                       int2float(e1p, float_type);
+               return;
+       }
+#endif NOFLOAT
+
+       /* Now they are INT or LONG */
+       u1 = (*e1p)->ex_type->tp_unsigned;
+       u2 = (*e2p)->ex_type->tp_unsigned;
+
+       /*      If either operand has type unsigned long int, the other
+               operand is converted to unsigned long int.
+       */
+       if (t1 == LONG && u1 && (t2 != LONG || !u2))
+               t2 = int2int(e2p, ulong_type);
+       else if (t2 == LONG && u2 && (t1 != LONG || !u1))
+               t1 = int2int(e1p, ulong_type);
+
+       /*      If one operand has type long int and the other has type unsigned
+               int, if a long int can represent all values of an unsigned int,
+               the operand of type unsigned int is converted to long int; if
+               a long int cannot represent all values of an unsigned int,
+               both operands are converted to unsigned long int.
+       */
+       if (t1 == LONG && t2 == INT && u2)
+               t2 = int2int(e2p, (int_size<long_size)? long_type : ulong_type);
+       else if (t2 == LONG && t1 == INT && u1)
+               t1 = int2int(e1p, (int_size<long_size)? long_type : ulong_type);
+       if (int_size > long_size) /* sanity check */
+               crash("size of int exceeds size of long");
+
+       /*      If either operand has type long int, the other operand is con-
+               verted to long int.
+       */
+       if (t1 == LONG && t2 != LONG)
+               t2 = int2int(e2p, long_type);
+       else
+       if (t2 == LONG && t1 != LONG)
+               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)
+               t2 = int2int(e2p, (t1 == LONG) ? ulong_type : uint_type);
+       else
+       if (!u1 && u2)
+               t1 = int2int(e1p, (t2 == LONG) ? ulong_type : uint_type);
+}
+
+relbalance(e1p, oper, e2p)
+       register struct expr **e1p, **e2p;
+{
+       /*      The expressions *e1p and *e2p are balanced to be operands
+               of the relational operator oper.
+       */
+       if ((*e1p)->ex_type->tp_fund == FUNCTION)
+               function2pointer(*e1p);
+       if ((*e2p)->ex_type->tp_fund == FUNCTION)
+               function2pointer(*e2p);
+       if ((*e1p)->ex_type->tp_fund == POINTER)
+               ch76pointer(e2p, oper, (*e1p)->ex_type);
+       else
+       if ((*e2p)->ex_type->tp_fund == POINTER)
+               ch76pointer(e1p, oper, (*e2p)->ex_type);
+       else
+       if (    (*e1p)->ex_type == (*e2p)->ex_type &&
+               (*e1p)->ex_type->tp_fund == ENUM
+       )
+               {}
+       else
+               arithbalance(e1p, oper, e2p);
+}
+
+ch76pointer(expp, oper, tp)
+       struct expr **expp;
+       register struct type *tp;
+{
+       /*      Checks whether *expp may be compared to tp using oper,
+               as described in chapter 7.6 and 7.7.
+               tp is known to be a pointer.
+       */
+       register struct expr *exp = *expp;
+
+       if (exp->ex_type->tp_fund == POINTER)   {
+               if (exp->ex_type != 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 */
+               ch7cast(expp, CAST, tp);
+       else    {
+               expr_error(exp, "%s on %s and pointer",
+                               symbol2str(oper),
+                               symbol2str(exp->ex_type->tp_fund)
+                       );
+               ch7cast(expp, oper, tp);
+       }
+}
+
+int
+any2arith(expp, oper)
+       register struct expr **expp;
+       register int oper;
+{
+       /*      Turns any expression into int_type, long_type or
+               double_type.
+       */
+       int fund;
+
+       switch (fund = (*expp)->ex_type->tp_fund)       {
+       case CHAR:
+       case SHORT:
+       case GENERIC:
+               int2int(expp,
+                       (*expp)->ex_type->tp_unsigned ? uint_type : 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:
+/*
+               float2float(expp, double_type);
+               break;
+*/
+       case DOUBLE:
+       case LNGDBL:
+               break;
+#endif NOFLOAT
+#ifndef NOBITFIELD
+       case FIELD:
+               field2arith(expp);
+               break;
+#endif NOBITFIELD
+       default:
+               expr_error(*expp, "operator %s on non-numerical operand (%s)",
+                       symbol2str(oper), symbol2str(fund));
+       case ERRONEOUS:
+               erroneous2int(expp);
+               break;
+       }
+
+       return (*expp)->ex_type->tp_fund;
+}
+
+erroneous2int(expp)
+       struct expr **expp;
+{
+       /*      the (erroneous) expression *expp is replaced by an
+               int expression
+       */
+       register struct expr *exp = *expp;
+       int flags = exp->ex_flags;
+       
+       free_expression(exp);
+       exp = intexpr((arith)0, INT);
+       exp->ex_flags = (flags | EX_ERROR);
+       *expp = exp;
+}
+
+struct expr *
+arith2arith(tp, oper, expr)
+       struct type *tp;
+       int oper;
+       register struct expr *expr;
+{
+       /*      arith2arith constructs a new expression containing a
+               run-time conversion between some arithmetic types.
+       */
+       register struct expr *new = new_expr();
+       
+       new->ex_file = expr->ex_file;
+       new->ex_line = expr->ex_line;
+       new->ex_type = tp;
+       new->ex_class = Type;
+       return new_oper(tp, new, oper, expr);
+}
+
+int
+int2int(expp, tp)
+       struct expr **expp;
+       register struct type *tp;
+{
+       /*      The expression *expp, which is of some integral type, is
+               converted to the integral type tp.
+       */
+       register struct expr *exp = *expp;
+       
+       if (is_cp_cst(exp))     {
+               register struct type *tp1 = exp->ex_type;
+
+               exp->ex_type = tp;
+               if (! tp1->tp_unsigned && tp->tp_unsigned) {
+                       /*      Avoid "unreal" overflow warnings, such as
+                               caused by f.i.:
+                                       unsigned int x = ~0;
+                                       unsigned int y = -1;
+                       */
+                       extern long full_mask[];
+                       long remainder = exp->VL_VALUE &
+                                               ~full_mask[(int)(tp->tp_size)];
+
+                       if (remainder == 0 ||
+                           remainder == ~full_mask[(int)(tp->tp_size)]) {
+                               exp->VL_VALUE &= ~remainder;
+                       }
+               }
+               cut_size(exp);
+       }
+       else    {
+               exp = arith2arith(tp, INT2INT, exp);
+       }
+       *expp = exp;
+       return exp->ex_type->tp_fund;
+}
+
+#ifndef NOFLOAT
+int2float(expp, tp)
+       register struct expr **expp;
+       struct type *tp;
+{
+       /*      The expression *expp, which is of some integral type, is
+               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;
+               exp->ex_type = tp;
+               exp->ex_class = Float;
+               exp->FL_VALUE = Salloc(buf, (unsigned)strlen(buf)+2) + 1;
+               exp->FL_DATLAB = 0;
+       }
+       else    *expp = arith2arith(tp, INT2FLOAT, *expp);
+}
+
+float2int(expp, tp)
+       struct expr **expp;
+       struct type *tp;
+{
+       /*      The expression *expp, which is of some floating type, is
+               converted to the integral type tp.
+       */
+       
+       fp_used = 1;
+       *expp = arith2arith(tp, FLOAT2INT, *expp);
+}
+
+float2float(expp, tp)
+       register struct expr **expp;
+       struct type *tp;
+{
+       /*      The expression *expp, which is of some floating type, is
+               converted to the floating type tp.
+               There is no need for an explicit conversion operator
+               if the expression is a constant.
+       */
+       
+       fp_used = 1;
+       if (is_fp_cst(*expp))
+               (*expp)->ex_type = tp;
+       else
+               *expp = arith2arith(tp, FLOAT2FLOAT, *expp);
+}
+#endif NOFLOAT
+
+array2pointer(exp)
+       register struct expr *exp;
+{
+       /*      The expression, which must be an array, is converted
+               to a pointer.
+       */
+       exp->ex_type = construct_type(POINTER, exp->ex_type->tp_up, 0,
+                                    (arith)0, NO_PROTO);
+}
+
+function2pointer(exp)
+       register struct expr *exp;
+{
+       /*      The expression, which must be a function, is converted
+               to a pointer to the function.
+       */
+       exp->ex_type = construct_type(POINTER, exp->ex_type, 0,
+                                    (arith)0, NO_PROTO);
+}
+
+string2pointer(ex)
+       register struct expr *ex;
+{
+       /*      The expression, which must be a string constant, is converted
+               to a pointer to the string-containing area.
+       */
+       label lbl = data_label();
+
+       code_string(ex->SG_VALUE, ex->SG_LEN, lbl);
+       ex->ex_class = Value;
+       ex->VL_CLASS = Label;
+       ex->VL_LBL = lbl;
+       ex->VL_VALUE = (arith)0;
+}
+
+opnd2integral(expp, oper)
+       register struct expr **expp;
+       int oper;
+{
+       register int fund = (*expp)->ex_type->tp_fund;
+
+       if (fund != INT && fund != LONG)        {
+               expr_error(*expp, "%s operand to %s",
+                               symbol2str(fund), symbol2str(oper));
+               erroneous2int(expp);
+               /* fund = INT; */
+       }
+}
+
+opnd2logical(expp, oper)
+       register struct expr **expp;
+       int oper;
+{
+       int fund = (*expp)->ex_type->tp_fund;
+
+       if (fund == FUNCTION || fund == ARRAY) {
+               expr_warning(*expp, "%s operand to %s",
+                       symbol2str(fund),
+                       symbol2str(oper));
+               if (fund == FUNCTION) {
+                       function2pointer(*expp);
+               }
+               else    array2pointer(*expp);
+       }
+#ifndef NOBITFIELD
+       else
+       if (fund == FIELD)
+               field2arith(expp);
+#endif NOBITFIELD
+       switch (fund = (*expp)->ex_type->tp_fund) {
+       case CHAR:
+       case SHORT:
+       case INT:
+       case LONG:
+       case ENUM:
+       case POINTER:
+#ifndef NOFLOAT
+       case FLOAT:
+       case DOUBLE:
+#endif NOFLOAT
+               break;
+       default:
+               expr_error(*expp, "%s operand to %s",
+                       symbol2str(fund), symbol2str(oper));
+       case ERRONEOUS:
+               erroneous2int(expp);
+               break;
+       }
+}
+
+opnd2test(expp, oper)
+       register struct expr **expp;
+{
+       opnd2logical(expp, oper);
+       if ((*expp)->ex_class == Oper && is_test_op((*expp)->OP_OPER))
+               { /* It is already a test */ }
+       else
+               ch7bin(expp, NOTEQUAL, intexpr((arith)0, INT));
+}
+
+int
+is_test_op(oper)
+{
+       switch (oper)   {
+       case '<':
+       case '>':
+       case LESSEQ:
+       case GREATEREQ:
+       case EQUAL:
+       case NOTEQUAL:
+       case '!':
+       case AND:
+       case OR:        /* && and || also impose a test */
+               return 1;
+       default:
+               return 0;
+       }
+       /*NOTREACHED*/
+}
+
+any2opnd(expp, oper)
+       register struct expr **expp;
+{
+       if (!*expp)
+               return;
+       switch ((*expp)->ex_type->tp_fund)      {       /* RM 7.1 */
+       case CHAR:
+       case SHORT:
+       case ENUM:
+#ifndef NOFLOAT
+       case FLOAT:
+#endif NOFLOAT
+               any2arith(expp, oper);
+               break;
+       case ARRAY:
+               array2pointer(*expp);
+               break;
+       case POINTER:
+               if ((*expp)->ex_class == String)
+                       string2pointer(*expp);
+               break;
+#ifndef NOBITFIELD
+       case FIELD:
+               field2arith(expp);
+               break;
+#endif NOBITFIELD
+       }
+}
+
+#ifndef NOBITFIELD
+field2arith(expp)
+       register struct expr **expp;
+{
+       /*      The expression to extract the bitfield value from the
+               memory word is put in the tree.
+       */
+       register struct type *tp = (*expp)->ex_type->tp_up;
+       register struct field *fd = (*expp)->ex_type->tp_field;
+       register struct type *atype = tp->tp_unsigned ? uword_type : word_type;
+
+       (*expp)->ex_type = atype;
+
+       if (atype->tp_unsigned) {       /* don't worry about the sign bit */
+               ch7bin(expp, RIGHT, intexpr((arith)fd->fd_shift, INT));
+               ch7bin(expp, '&', intexpr(fd->fd_mask, INT));
+       }
+       else    {       /* take care of the sign bit: sign extend if needed */
+               arith bits_in_type = atype->tp_size * 8;
+
+               ch7bin(expp, LEFT,
+                       intexpr(bits_in_type - fd->fd_width - fd->fd_shift,
+                                               INT)
+               );
+               ch7bin(expp, RIGHT, intexpr(bits_in_type - fd->fd_width, INT));
+       }
+       ch7cast(expp, CAST, tp);        /* restore its original type */
+}
+#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(expr)
+       register struct expr *expr;
+{
+       if (*(expr->FL_VALUE) == '-')
+               ++(expr->FL_VALUE);
+       else
+               --(expr->FL_VALUE);
+}
+#endif NOFLOAT
diff --git a/lang/cem/cemcom.ansi/arith.h b/lang/cem/cemcom.ansi/arith.h
new file mode 100644 (file)
index 0000000..5ffea6c
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* COMPILER ARITHMETIC */
+
+/*     Normally the compiler does its internal arithmetics in longs
+       native to the source machine, which is always good for local
+       compilations, and generally OK too for cross compilations
+       downwards and sidewards.  For upwards cross compilation and
+       to save storage on small machines, SPECIAL_ARITHMETICS will
+       be handy.
+*/
+
+#include       "spec_arith.h"
+
+#ifndef        SPECIAL_ARITHMETICS
+
+#include <em_arith.h>          /* obtain definition of "arith" */
+
+#else  SPECIAL_ARITHMETICS
+
+/*     All preprocessor arithmetic should be done in longs.
+*/
+#define        arith   long                            /* dummy */
+
+#endif SPECIAL_ARITHMETICS
diff --git a/lang/cem/cemcom.ansi/asm.c b/lang/cem/cemcom.ansi/asm.c
new file mode 100644 (file)
index 0000000..4900ea9
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*             A S M                   */
+
+/*ARGSUSED*/
+code_asm(s, l)
+       char *s;
+       int l;
+{
+       /*      'asm' '(' string ')' ';'
+       */
+       error("\"asm\" instruction not implemented");
+}
diff --git a/lang/cem/cemcom.ansi/assert.h b/lang/cem/cemcom.ansi/assert.h
new file mode 100644 (file)
index 0000000..8e3bc2e
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*      A S S E R T I O N    M A C R O   D E F I N I T I O N           */
+
+/*     At some points in the program, it must be sure that some condition
+       holds true, due to further, successful, processing.  As long as
+       there is no reasonable method to prove that a program is 100%
+       correct, these assertions are needed in some places.
+*/
+#include       "debug.h"       /* UF */
+
+#ifdef DEBUG
+/*     Note: this macro uses parameter substitution inside strings */
+#define        ASSERT(exp)     (exp || crash("in %s, %u: assertion %s failed", \
+                               __FILE__, __LINE__, "exp"))
+#define        NOTREACHED()    crash("in %s, %u: unreachable statement reached", \
+                               __FILE__, __LINE__)
+#else
+#define        ASSERT(exp)
+#define        NOTREACHED()
+#endif DEBUG
diff --git a/lang/cem/cemcom.ansi/atw.h b/lang/cem/cemcom.ansi/atw.h
new file mode 100644 (file)
index 0000000..ed2b2dc
--- /dev/null
@@ -0,0 +1,10 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* Align To Word boundary Definition   */
+
+#include "sizes.h"
+
+#define        ATW(arg)        ((((arg) + word_size - 1) / word_size) * word_size)
diff --git a/lang/cem/cemcom.ansi/blocks.c b/lang/cem/cemcom.ansi/blocks.c
new file mode 100644 (file)
index 0000000..1684995
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     B L O C K   S T O R I N G   A N D   L O A D I N G       */
+
+#include       "lint.h"
+#ifndef        LINT
+
+#include <em.h>
+#include <em_reg.h>
+#include "arith.h"
+#include "sizes.h"
+#include "atw.h"
+#include "align.h"
+#ifndef STB
+#include "label.h"
+#include "stack.h"
+#include "Lpars.h"
+extern arith NewLocal();
+#define LocalPtrVar()  NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
+#endif STB
+
+/*     Because EM does not support the loading and storing of
+       objects having other sizes than word fragment and multiple,
+       we need to have a way of transferring these objects, whereby
+       we simulate "loi" and "sti": the address of the source resp.
+       destination is located on top of stack and a call is done
+       to load_block() resp. store_block().
+       ===============================================================
+       # Loadblock() works on the stack as follows: ([ ] indicates the
+       # position of the stackpointer)
+       # lower address--->
+       # 1)    | &object
+       # 2)    | ... ATW(sz) bytes ... | sz | &stack_block | &object
+       # 3)    | ... ATW(sz) bytes ...
+       ===============================================================
+       Loadblock() pushes ATW(sz) bytes directly onto the stack!
+
+       Store_block() works on the stack as follows:
+       lower address--->
+       1)      | ... ATW(sz) bytes ... | &object
+       2)      | ... ATW(sz) bytes ... | &object | &stack_block | sz
+       3)      <empty>
+
+       If sz is a legal argument for "loi" or "sti", just one EM
+       instruction is generated.
+       In the other cases, the notion of alignment is taken into account:
+       we only push an object of the size accepted by EM onto the stack,
+       while we need a loop to store the stack block into a memory object.
+*/
+store_block(sz, al)
+       arith sz;
+       int al;
+{
+       if (
+               ((sz == al) && (word_align % al == 0)) ||
+               (
+                       (sz % word_size == 0 || word_size % sz == 0) &&
+                       (al % word_align == 0)
+               )
+       )       /* Lots of Irritating Stupid Parentheses */
+               C_sti(sz);
+       else {
+#ifndef STB
+               arith src, dst;
+
+               /* allocate two pointer temporaries */
+               src = LocalPtrVar();
+               dst = LocalPtrVar();
+
+               /* load the addresses */
+               StoreLocal(dst, pointer_size);
+               C_lor((arith)1);        /* push current sp */
+               StoreLocal(src, pointer_size);
+               copy_loop(sz, src, dst);
+               C_asp(ATW(sz));
+               FreeLocal(dst);
+               FreeLocal(src);
+#else STB
+               /*      address of destination lies on the stack        */
+
+               /*      push address of first byte of block on stack onto
+                       the stack by computing it from the current stack
+                       pointer position
+               */
+               C_lor((arith)1);        /* push current sp              */
+               C_adp(pointer_size);    /* set & to 1st byte of block   */
+               C_loc(sz);              /* number of bytes to transfer  */
+               C_cal("__stb");         /* call transfer routine        */
+               C_asp(pointer_size + pointer_size + int_size + ATW(sz));
+#endif STB
+       }
+}
+
+load_block(sz, al)
+       arith sz;
+       int al;
+{
+       arith esz = ATW(sz);    /* effective size == actual # pushed bytes */
+
+       if (
+               ((sz == al) && (word_align % al == 0)) ||
+               (
+                       (sz % word_size == 0 || word_size % sz == 0) &&
+                       (al % word_align == 0)
+               )
+       )       /* Lots of Irritating Stupid Parentheses */
+               C_loi(sz);
+       else {
+#ifndef STB
+               arith src, dst;
+
+               /* allocate two pointer temporaries */
+               src = LocalPtrVar();
+               dst = LocalPtrVar();
+
+               StoreLocal(src, pointer_size);
+               C_asp(-esz);            /* allocate stack block */
+               C_lor((arith)1);        /* push & of stack block as dst */
+               StoreLocal(dst, pointer_size);
+               copy_loop(sz, src, dst);
+               FreeLocal(dst);
+               FreeLocal(src);
+#else STB
+               C_asp(-(esz - pointer_size));   /* allocate stack block */
+               C_lor((arith)1);        /* push & of stack block as dst */
+               C_dup(pointer_size);            /* fetch source address */
+               C_adp(esz - pointer_size);
+               C_loi(pointer_size);
+               C_loc(sz);                      /* # bytes to copy      */
+               C_cal("__stb");                 /* library copy routine */
+               C_asp(int_size + pointer_size + pointer_size);
+#endif STB
+       }
+}
+
+#ifndef STB
+copy_loop(sz, src, dst)
+       arith sz, src, dst;
+{
+       /* generate inline byte-copy loop */
+       label l_cont = text_label(), l_stop = text_label();
+
+       C_loc(sz);              /* amount of bytes */
+       C_df_ilb(l_cont);
+       C_dup(word_size);
+       C_zle(l_stop);
+       C_dec();
+       LoadLocal(src, pointer_size);
+       C_dup(pointer_size);
+       C_adp((arith)1);
+       StoreLocal(src, pointer_size);
+       C_loi((arith)1);
+       LoadLocal(dst, pointer_size);
+       C_dup(pointer_size);
+       C_adp((arith)1);
+       StoreLocal(dst, pointer_size);
+       C_sti((arith)1);
+       C_bra(l_cont);
+       C_df_ilb(l_stop);
+       C_asp(word_size);
+}
+#endif STB
+
+#endif LINT
+
diff --git a/lang/cem/cemcom.ansi/cem.1 b/lang/cem/cemcom.ansi/cem.1
new file mode 100644 (file)
index 0000000..ea79f3a
--- /dev/null
@@ -0,0 +1,230 @@
+.TH CEM 1L 86/11/12
+.SH NAME
+cem \- ACK C compiler
+.SH SYNOPSIS
+.B cem
+[ option ] ... file ...
+.SH DESCRIPTION
+.I Cem
+is a
+.I cc (1)-like
+C compiler that uses the C front-end compiler
+.I cemcom (1)
+of the Amsterdam Compiler Kit.
+.I Cem
+interprets its arguments not starting with a '\-' as
+source files, to be compiled by the various parts of the compilation process,
+which are listed below.
+File arguments whose names end with \fB.\fP\fIcharacter\fP are interpreted as
+follows:
+.IP .[ao]
+object file.
+.IP .[ci]
+C source code
+.IP .e
+EM assembler source file.
+.IP .k
+compact EM file, not yet optimized by the EM peephole optimizer.
+.IP .m
+compact EM file, already optimized by the peephole optimizer.
+.IP .s
+assembler file.
+.LP
+The actions to be taken by
+.I cem
+are directed by the type of file argument and the various options that are
+presented to it.
+.PP
+The following set of options, which is a mixture of options interpreted by
+.I cc (1)
+and 
+.I ack (?)
+are interpreted by
+.I cem .
+(The options not specified here are passed to the loader.)
+.IP \fB\-B\fP\fIname\fP
+Use 
+.I name
+as front-end compiler instead of the default 
+.I cemcom (1).
+.br
+Same as "\fB\-Rcem=\fP\fIname\fP".
+.IP \fB\-C\fP
+Run C preprocessor 
+.I /lib/cpp
+only and prevent it from eliding comments.
+.IP \fB\-D\fP\fIname\fP\fB=\fP\fIdef\fP
+Define the 
+.I name
+to the preprocessor, as if by "#define".
+.IP \fB\-D\fP\fIname\fP
+.br
+Same as "\fB\-D\fP\fIname\fP\fB=1\fP".
+.IP \fB\-E\fP
+Run only the macro preprocessor on the named files and send the
+result to standard output.
+.IP \fB\-I\fP\fIdir\fP
+\&"#include" files whose names do not begin with '/' are always
+sought first in the directory of the \fIfile\fP argument, then in directories
+in \fB\-I\fP options, then in directories on a standard list (which in fact
+consists of "/usr/include").
+.IP \fB\-L\fP\fIdir\fP
+Use \fIdir\fP as library-containing directory instead of the default.
+.IP \fB\-N\fP\fIc\fP
+Only effective if ACK pipeline is used. 
+This option causes some default actions and options to be suppressed, according
+to
+.I c :
+.RS
+.IP \fBc\fP
+do not convert from EM a.out to local a.out format (i.e., skip the 
+.B cv
+pass.)
+.IP \fBl\fP
+do not pass the default loader flags to the
+.B ld
+pass.
+.RE
+.IP \fB\-P\fP
+Same as \fB\-E\fP, but sending the result of input file \fIfile\fP\fB.[ceis]\fP
+to \fIfile\fP\fB.i\fP.
+.IP \fB\-R\fP
+Passed to \fIcemcom\fP(1) in order to parse the named C programs according
+to the C language as described in [K&R] (also called \fIRestricted\fP C).
+.IP \fB\-R\fP\fIprog\fP\fB=\fP\fIname\fP
+.br
+Use \fIname\fP as program for phase \fIprog\fP of the compilation instead of
+the default.
+\&\fIProg\fP is one of the following names:
+.RS
+.IP \fBcpp\fP
+macro preprocessor
+.IP \fBcem\fP
+front\-end compiler
+.IP \fBopt\fP
+EM peephole optimizer
+.IP \fBdecode\fP
+EM compact to EM assembler translator
+.IP \fBencode\fP
+EM assembler to EM compact translator
+.IP \fBbe\fP
+EM compact code to target\-machine assembly code compiler
+.IP \fBcg\fP
+same as \fBbe\fP
+.IP \fBas\fP
+assembler
+.IP \fBld\fP
+linker/loader
+.IP \fBcv\fP
+a.out format converting program (only if ACK pipeline is used)
+.RE
+.IP \fB\-R\fP\fIprog\fP\fB\-\fP\fIoption\fP
+.br
+Pass \fB\-\fP\fIoption\fP to the compilation phase indicated by \fIprog\fP.
+.IP \fB\-S\fP
+Same as \fB\-c.s\fP.
+.IP \fB\-U\fP\fIname\fP
+.br
+Remove any initial definition of \fIname\fP.
+.IP \fB\-V\fP\fIcm\fP.\fIn\fP,\ \fB\-V\fIcm\fP.\fIncm\fP.\fIn\fP\ ...
+.br
+Set the size and alignment requirements of the C constructs of the named
+C input files.
+The letter \fIc\fP indicates the simple type, which is one of
+\fBs\fP(short), \fBi\fP(int), \fBl\fP(long), \fBf\fP(float), \fBd\fP(double) or
+\fBp\fP(pointer).
+The \fIm\fP parameter can be used to specify the length of the type (in bytes)
+and the \fIn\fP parameter for the alignment of that type.
+Absence of \fIm\fP or \fIn\fP causes the default value to be retained.
+To specify that the bitfields should be right adjusted instead of the
+default left adjustment, specify \fBr\fP as \fIc\fP parameter
+without parameters.
+.br
+This option is passed directly to \fIcemcom\fP(1).
+.IP \fB\-c\fP
+Same as \fB\-c.o\fP.
+.IP \fB\-c.e\fP
+Produce human-readable EM assembly code on \fIfile\fP\fB.e\fP for the
+named files \fIfile\fP\fB.[cikm]\fP 
+.IP \fB\-c.k\fP
+Compile C source \fIfile\fP\fB.[ci]\fP or
+encode human-readable EM assembly code from \fIfile\fP\fB.e\fP
+into non-optimized compact EM code and write the result on \fIfile\fP\fB.k\fP
+.IP \fB\-c.m\fP
+Compile C source \fIfile\fP\fB.[ci]\fP,
+translate non-optimized EM code from \fIfile\fP\fB.k\fP or
+encode EM assembly code from \fIfile\fP\fB.e\fP
+into optimized compact EM code and write the result on \fIfile\fP\fB.m\fP
+.IP \fB\-c.o\fP
+Suppress the loading phase of the compilation, and force an object file to
+be produced even if only one program is compiled
+.IP \fB\-c.s\fP
+Compile the named \fIfile\fP\fB.[ceikm]\fP input files, and leave the 
+assembly language output on corresponding files suffixed ".s".
+.IP \fB\-k\fP
+Same as \fB\-c.k\fP.
+.IP \fB\-l\fP\fIname\fP
+.br
+Append the library \fBlib\fP\fIname\fP\fB.a\fP to the list of files that
+should be loaded and linked into the final output file.
+The library is searched for in the library directory.
+.IP \fB\-m\fP
+Same as \fB\-c.m\fP.
+.IP \fB\-o\fP\ \fIoutput\fP
+.br
+Name the final output file \fIoutput\fP.
+If this option is used, the default "a.out" will be left undisturbed.
+.IP \fB\-p\fP
+Produce EM profiling code (\fBfil\fP and \fBlin\fP instructions to
+enable an interpreter to keep track of the current location in the
+source code)
+.IP \fB\-t\fP
+Keep the intermediate files, produced during the various phases of the 
+compilation.
+The produced files are named \fIfile\fP\fB.\fP\fIcharacter\fP where 
+\&\fIcharacter\fP indicates the type of the file as listed before.
+.IP \fB\-v\fP
+Verbose.
+Print the commands before they are executed.
+.IP \fB\-vn\fP
+Do not really execute (for debugging purposes only).
+.IP \fB\-vd\fP
+Print some additional information (for debugging purposes only).
+.IP \fB\-\-\fP\fIanything\fP
+.br
+Equivalent to \fB\-Rcem\-\-\fP\fIanything\fP.
+The options 
+.B \-\-C ,
+.B \-\-E
+and
+.B \-\-P
+all have the same effect as respectively
+.B \-C ,
+.B \-E
+and
+.B \-P
+except for the fact that the macro preprocessor is taken to be the
+built\-in preprocessor of the \fBcem\fP phase.
+Most "\-\-" options are used by
+.I cemcom (1)
+to set some internal debug switches.
+.LP
+.SH SEE ALSO
+cemcom(1), cc(1), ack(?), as(1), ld(1)
+.br
+.IP [K&R]
+B.W. Kernighan and D.M. Ritchie, \fIThe C Programming Language\fP,
+Prentice-Hall, 1978.
+.SH DIAGNOSTICS
+.I Cem
+reports any failure of its components.
+.SH BUGS
+.IP \(bu
+All intermediate files are placed in the current working directory which
+causes files with the same name as the intermediate files to be overwritten.
+.IP \(bu
+.B Cem
+only accepts a limited number of arguments to be passed to the components.
+(e.g., 256).
+.IP \(bu
+Please report suggestions and other bugs to erikb@vu44.uucp
diff --git a/lang/cem/cemcom.ansi/cem.c b/lang/cem/cemcom.ansi/cem.c
new file mode 100644 (file)
index 0000000..2209530
--- /dev/null
@@ -0,0 +1,764 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/*     $Header$        */
+/*
+       Driver for the CEMCOM compiler: works like /bin/cc and accepts
+       most of the options accepted by /bin/cc and /usr/em/bin/ack.
+       Date written: dec 4, 1985
+       Adapted for 68000 (Aug 19, 1986)
+       Merged the vax and mantra versions (Nov 10, 1986)
+       Author: Erik Baalbergen
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <signal.h>
+
+#define MAXARGC        256     /* maximum number of arguments allowed in a list */
+#define USTR_SIZE      1024    /* maximum length of string variable */
+
+struct arglist {
+       int al_argc;
+       char *al_argv[MAXARGC];
+};
+
+/* some system-dependent variables     */
+char *PP = "/lib/cpp";
+char *CEM = "/usr/em/lib/em_cemcom";
+char *ENCODE = "/usr/em/lib/em_encode";
+char *DECODE = "/usr/em/lib/em_decode";
+char *OPT = "/usr/em/lib/em_opt";
+char *SHELL = "/bin/sh";
+
+#ifndef MANTRA
+char *CG = "/usr/em/lib/vax4/cg";
+char *AS = "/bin/as";
+char *AS_FIX = "/user1/erikb/bin/mcomm";
+char *LD = "/bin/ld";
+char *LIBDIR = "/user1/cem/lib";
+char *V_FLAG = "-Vs2.2w4.4i4.4l4.4f4.4d8.4p4.4";
+#else MANTRA
+char *CG = "/usr/em/lib/m68k2/cg";
+char *AS = "/usr/em/lib/m68k2/as";
+char *LD = "/usr/em/lib/em_led";
+char *CV = "/usr/em/lib/m68k2/cv";
+char *LIBDIR = "/usr/em/lib/m68k2";
+char *V_FLAG = "-Vs2.2w2.2i2.2l4.2f4.2d8.2p4.2";
+#endif MANTRA
+
+struct arglist LD_HEAD = {
+       2,
+       {
+#ifndef MANTRA
+               "/usr/em/lib/vax4/head_em",
+               "/usr/em/lib/vax4/head_cc"
+#else MANTRA
+               "/usr/em/lib/m68k2/head_em",
+               "/usr/em/lib/m68k2/head_cc"
+#endif MANTRA
+       }
+};
+
+struct arglist LD_TAIL = {
+#ifndef MANTRA
+       4,
+       {
+               "/user1/cem/lib/libc.a",
+               "/user1/cem/lib/stb.o",
+               "/usr/em/lib/vax4/tail_mon",
+               "/usr/em/lib/vax4/tail_em"
+       }
+#else MANTRA
+       7,
+       {
+               "/usr/em/lib/m68k2/tail_cc.1s",
+               "/usr/em/lib/m68k2/tail_cc.2g",
+               "/usr/em/lib/m68k2/tail_cem",
+               "/usr/em/lib/m68k2/tail_fp.a",
+               "/usr/em/lib/m68k2/tail_em.rt",
+               "/usr/em/lib/m68k2/tail_mon",
+               "/usr/em/lib/m68k2/end_em"
+       }
+#endif MANTRA
+};
+
+char *o_FILE = "a.out";
+#ifdef MANTRA
+char *cv_FILE = "cv.out";
+#endif MANTRA
+
+#define remove(str)    (((FLAG(t) == 0) && unlink(str)), (str)[0] = '\0')
+#define cleanup(str)           (str && remove(str))
+#define mkname(dst, s1, s2)    mkstr(dst, (s1), (s2), 0)
+#define init(al)               (al)->al_argc = 1
+#define library(nm) \
+       mkstr(alloc((unsigned int)strlen(nm) + strlen(LIBDIR) + 7), \
+               LIBDIR, "/lib", nm, ".a", 0)
+
+struct arglist SRCFILES, LDFILES, GEN_LDFILES, PP_FLAGS, CEM_FLAGS,
+       OPT_FLAGS, DECODE_FLAGS, ENCODE_FLAGS, CG_FLAGS, AS_FLAGS,
+       O_FLAGS, DEBUG_FLAGS, CALL_VEC;
+
+#ifndef MANTRA
+struct arglist LD_FLAGS;
+#else MANTRA
+struct arglist LD_FLAGS = {
+       5,
+       {
+               "-b0:0x80000",
+               "-a0:2",
+               "-a1:2",
+               "-a2:2",
+               "-a3:2"
+       }
+};
+struct arglist CV_FLAGS;
+int Nc_flag = 0;
+#endif MANTRA
+
+/* option naming */
+#define NAME(chr)      chr
+#define FLAG(chr)      NAME(chr)_flag
+int E_flag, P_flag, S_flag, c_flag, e_flag, k_flag, 
+       m_flag, o_flag, t_flag, v_flag;
+
+/* various passes */
+struct prog {
+       char *p_name;
+       char **p_task;
+       struct arglist *p_flags;
+} ProgParts[] = {
+       { "cpp",        &PP,            &PP_FLAGS       },
+       { "cem",        &CEM,           &CEM_FLAGS      },
+       { "opt",        &OPT,           &OPT_FLAGS      },
+       { "decode",     &DECODE,        &DECODE_FLAGS   },
+       { "encode",     &ENCODE,        &ENCODE_FLAGS   },
+       { "be",         &CG,            &CG_FLAGS       },
+       { "cg",         &CG,            &CG_FLAGS       },
+       { "as",         &AS,            &AS_FLAGS       },
+       { "ld",         &LD,            &LD_FLAGS       },
+#ifdef MANTRA
+       { "cv",         &CV,            &CV_FLAGS       },
+#endif MANTRA
+       { 0,            0,              0               }
+};
+
+/* various forward declarations */
+int trap();
+char *mkstr();
+char *alloc();
+long sizeof_file();
+
+/* various globals */
+char *ProgCall = 0;
+int debug = 0;
+int exec = 1;
+int RET_CODE = 0;
+
+main(argc, argv)
+       char *argv[];
+{
+       char *str, **argvec, *file, *ldfile = 0;
+       int count, ext;
+       char Nfile[USTR_SIZE], kfile[USTR_SIZE], sfile[USTR_SIZE],
+               mfile[USTR_SIZE], ofile[USTR_SIZE], BASE[USTR_SIZE];
+       register struct arglist *call = &CALL_VEC;
+
+       set_traps(trap);
+       ProgCall = *argv++;
+       append(&CEM_FLAGS, "-L");
+       while (--argc > 0) {
+               if (*(str = *argv++) != '-') {
+                       append(&SRCFILES, str);
+                       continue;
+               }
+               switch (str[1]) {
+               case '-':
+                       switch (str[2]) {
+                       case 'C':
+                       case 'E':
+                       case 'P':
+                               FLAG(E) = 1;
+                               append(&PP_FLAGS, str);
+                               PP = CEM;
+                               FLAG(P) = (str[2] == 'P');
+                               break;
+                       default:
+                               append(&DEBUG_FLAGS, str);
+                               break;
+                       }
+                       break;
+               case 'B':
+                       PP = CEM = &str[2];
+                       break;
+               case 'C':
+               case 'E':
+               case 'P':
+                       FLAG(E) = 1;
+                       append(&PP_FLAGS, str);
+                       FLAG(P) = (str[1] == 'P');
+                       break;
+               case 'c':
+                       if (str[2] == '.') {
+                               switch (str[3]) {
+                               case 's':
+                                       FLAG(S) = 1;
+                                       break;
+                               case 'k':
+                                       FLAG(k) = 1;
+                                       break;
+                               case 'o':
+                                       FLAG(c) = 1;
+                                       break;
+                               case 'm':
+                                       FLAG(m) = 1;
+                                       break;
+                               case 'e':
+                                       FLAG(e) = 1;
+                                       break;
+                               default:
+                                       bad_option(str);
+                               }
+                       }
+                       else
+                       if (str[2] == '\0')
+                               FLAG(c) = 1;
+                       else
+                               bad_option(str);
+                       break;
+               case 'D':
+               case 'I':
+               case 'U':
+                       append(&PP_FLAGS, str);
+                       break;
+               case 'k':
+                       FLAG(k) = 1;
+                       break;
+               case 'l':
+                       if (str[2] == '\0')     /* no standard libraries */
+                               LD_HEAD.al_argc = LD_TAIL.al_argc = 0;
+                       else    /* use library from library directory */
+                               append(&SRCFILES, library(&str[2]));
+                       break;
+               case 'L':       /* change default library directory */
+                       LIBDIR = &str[2];
+                       break;
+               case 'm':
+                       FLAG(m) = 1;
+                       break;
+#ifdef MANTRA
+               case 'N':
+                       switch (str[2]) {
+                       case 'c': /* no a.out conversion */
+                               Nc_flag = 1;
+                               break;
+                       case 'l': /* no default options to led */
+                               LD_FLAGS.al_argc = 0;
+                               break;
+                       default:
+                               bad_option(str);
+                       }
+                       break;
+#endif MANTRA
+               case 'o':
+                       FLAG(o) = 1;
+                       if (argc-- < 0)
+                               bad_option(str);
+                       else
+                               o_FILE = *argv++;
+                       break;
+               case 'O':
+                       append(&O_FLAGS, "-O");
+                       break;
+               case 'R':
+                       if (str[2] == '\0')
+                               append(&CEM_FLAGS, str);
+                       else
+                               Roption(str);
+                       break;
+               case 'S':
+                       FLAG(S) = 1;
+                       break;
+               case 't':
+                       FLAG(t) = 1;
+                       break;
+               case 'v':       /* set debug switches */
+                       FLAG(v) = 1;
+                       switch (str[2]) {
+                       case 'd':
+                               debug = 1;
+                               break;
+                       case 'n':       /* no execute */
+                               exec = 0;
+                               break;
+                       case '\0':
+                               break;
+                       default:
+                               bad_option(str);
+                       }
+                       break;
+               case 'V':
+                       V_FLAG = str;
+                       break;
+               default:
+                       append(&LD_FLAGS, str);
+               }
+       }
+       if (debug) report("Note: debug output");
+       if (exec == 0)
+               report("Note: no execution");
+       count = SRCFILES.al_argc;
+       argvec = &(SRCFILES.al_argv[0]);
+       Nfile[0] = '\0';
+       while (count-- > 0) {
+               basename(file = *argvec++, BASE);
+               if (FLAG(E)) {
+                       char ifile[USTR_SIZE];
+
+                       init(call);
+                       append(call, PP);
+                       concat(call, &DEBUG_FLAGS);
+                       concat(call, &PP_FLAGS);
+                       append(call, file);
+                       runvec(call, FLAG(P) ? mkname(ifile, BASE, ".i") : 0);
+                       continue;
+               }
+               ext = extension(file);
+               /* .c to .k and .N      */
+               if (ext == 'c' || ext == 'i') {
+                       init(call);
+                       append(call, CEM);
+                       concat(call, &DEBUG_FLAGS);
+                       append(call, V_FLAG);
+                       concat(call, &CEM_FLAGS);
+                       concat(call, &PP_FLAGS);
+                       append(call, file);
+                       append(call, mkname(kfile, BASE, ".k"));
+                       append(call, mkname(Nfile, BASE, ".N"));
+                       if (runvec(call, (char *)0)) {
+                               file = kfile;
+                               ext = 'k';
+                               if (sizeof_file(Nfile) <= 0L)
+                                       remove(Nfile);
+                       }
+                       else {
+                               remove(kfile);
+                               remove(Nfile);
+                               continue;
+                       }
+               }
+               /* .e to .k */
+               if (ext == 'e') {
+                       init(call);
+                       append(call, ENCODE);
+                       concat(call, &ENCODE_FLAGS);
+                       append(call, file);
+                       append(call, mkname(kfile, BASE, ".k"));
+                       if (runvec(call, (char *)0) == 0)
+                               continue;
+                       file = kfile;
+                       ext = 'k';
+               }
+               if (FLAG(k))
+                       continue;
+               /* decode .k or .m */
+               if (FLAG(e) && (ext == 'k' || ext == 'm')) {
+                       char efile[USTR_SIZE];
+                       init(call);
+                       append(call, DECODE);
+                       concat(call, &DECODE_FLAGS);
+                       append(call, file);
+                       append(call, mkname(efile, BASE, ".e"));
+                       runvec(call, (char *)0);
+                       cleanup(kfile);
+                       continue;
+               }
+               /* .k to .m */
+               if (ext == 'k') {
+                       init(call);
+                       append(call, OPT);
+                       concat(call, &OPT_FLAGS);
+                       append(call, file);
+                       if (runvec(call, mkname(mfile, BASE, ".m")) == 0)
+                               continue;
+                       file = mfile;
+                       ext = 'm';
+                       cleanup(kfile);
+               }
+               if (FLAG(m))
+                       continue;
+               /* .m to .s */
+               if (ext == 'm') {
+                       init(call);
+                       append(call, CG);
+                       concat(call, &CG_FLAGS);
+                       append(call, file);
+                       append(call, mkname(sfile, BASE, ".s"));
+                       if (runvec(call, (char *)0) == 0)
+                               continue;
+                       if (Nfile[0] != '\0') {
+#ifndef MANTRA
+                               init(call);
+                               append(call, AS_FIX);
+                               append(call, Nfile);
+                               append(call, sfile);
+                               runvec(call, (char *)0);
+#endif MANTRA
+                               remove(Nfile);
+                       }
+                       cleanup(mfile);
+                       file = sfile;
+                       ext = 's';
+               }
+               if (FLAG(S))
+                       continue;
+               /* .s to .o */
+               if (ext == 's') {
+                       ldfile = FLAG(c) ?
+                               ofile :
+                               alloc((unsigned)strlen(BASE) + 3);
+                       init(call);
+                       append(call, AS);
+                       concat(call, &AS_FLAGS);
+#ifdef MANTRA
+                       append(call, "-");
+#endif MANTRA
+                       append(call, "-o");
+                       append(call, mkname(ldfile, BASE, ".o"));
+                       append(call, file);
+                       if (runvec(call, (char *)0) == 0)
+                               continue;
+                       file = ldfile;
+                       ext = 'o';
+                       cleanup(sfile);
+               }
+               if (FLAG(c))
+                       continue;
+               append(&LDFILES, file);
+               if (ldfile) {
+                       append(&GEN_LDFILES, ldfile);
+                       ldfile = 0;
+               }
+       }
+       /* *.o to a.out */
+       if (RET_CODE == 0 && LDFILES.al_argc > 0) {
+               init(call);
+               append(call, LD);
+               concat(call, &LD_FLAGS);
+               append(call, "-o");
+#ifndef MANTRA
+               append(call, o_FILE);
+#else MANTRA
+               append(call, Nc_flag ? o_FILE : cv_FILE);
+#endif MANTRA
+               concat(call, &LD_HEAD);
+               concat(call, &LDFILES);
+               concat(call, &LD_TAIL);
+               if (runvec(call, (char *)0)) {
+                       register i = GEN_LDFILES.al_argc;
+
+                       while (i-- > 0)
+                               remove(GEN_LDFILES.al_argv[i]);
+#ifdef MANTRA
+                       /* convert to local a.out format */
+                       if (Nc_flag == 0) {
+                               init(call);
+                               append(call, CV);
+                               concat(call, &CV_FLAGS);
+                               append(call, cv_FILE);
+                               append(call, o_FILE);
+                               if (runvec(call, (char *)0))
+                                       remove(cv_FILE);
+                       }
+#endif MANTRA
+               }
+       }
+       exit(RET_CODE);
+}
+
+#define BUFSIZE  (USTR_SIZE * MAXARGC)
+char alloc_buf[BUFSIZE];
+
+char *
+alloc(u)
+       unsigned u;
+{
+       static char *bufptr = &alloc_buf[0];
+       register char *p = bufptr;
+
+       if ((bufptr += u) >= &alloc_buf[BUFSIZE])
+               panic("no space");
+       return p;
+}
+
+append(al, arg)
+       register struct arglist *al;
+       char *arg;
+{
+       if (al->al_argc >= MAXARGC)
+               panic("argument list overflow");
+       al->al_argv[(al->al_argc)++] = arg;
+}
+
+concat(al1, al2)
+       struct arglist *al1, *al2;
+{
+       register int i = al2->al_argc;
+       register char **p = &(al1->al_argv[al1->al_argc]);
+       register char **q = &(al2->al_argv[0]);
+
+       if ((al1->al_argc += i) >= MAXARGC)
+               panic("argument list overflow");
+       while (i-- > 0)
+               *p++ = *q++;
+}
+
+/*     The next function is a dirty old one, taking a variable number of
+       arguments.
+       Take care that the last argument is a null-valued pointer!
+*/
+/*VARARGS1*/
+char *
+mkstr(dst, arg)
+       char *dst, *arg;
+{
+       char **vec = (char **) &arg;
+       register char *p;
+       register char *q = dst;
+
+       while (p = *vec++) {
+               while (*q++ = *p++);
+               q--;
+       }
+       return dst;
+}
+
+Roption(str)
+       char *str;      /* of the form "prog=/-arg"     */
+{
+       char *eq;
+       char *prog, *arg;
+       char bc;
+       char *cindex();
+
+       prog = &str[2];
+       if (eq = cindex(prog, '='))
+               bc = '=';
+       else
+       if (eq = cindex(prog, '-'))
+               bc = '-';
+       else {
+               bad_option(str);
+               return;
+       }
+       *eq++ = '\0';
+       if (arg = eq) {
+               char *opt = 0;
+               struct prog *pp = &ProgParts[0];
+
+               if (bc == '-')
+                       opt = mkstr(alloc((unsigned)strlen(arg) + 2),
+                                                               "-", arg, 0);
+               while (pp->p_name) {
+                       if (strcmp(prog, pp->p_name) == 0) {
+                               if (opt)
+                                       append(pp->p_flags, opt);
+                               else
+                                       *(pp->p_task) = arg;
+                               return;
+                       }
+                       pp++;
+               }
+       }
+       bad_option(str);
+}
+
+basename(str, dst)
+       char *str;
+       register char *dst;
+{
+       register char *p1 = str;
+       register char *p2 = p1;
+
+       while (*p1)
+               if (*p1++ == '/')
+                       p2 = p1;
+       p1--;
+       if (*--p1 == '.') {
+               *p1 = '\0';
+               while (*dst++ = *p2++) {}
+               *p1 = '.';
+       }
+       else
+               while (*dst++ = *p2++) {}
+}
+
+int
+extension(fn)
+       register char *fn;
+{
+       char c;
+
+       while (*fn++) {}
+       fn--;
+       c = *--fn;
+       return (*--fn == '.') ? c : 0;
+}
+
+long
+sizeof_file(nm)
+       char *nm;
+{
+       struct stat stbuf;
+
+       if (stat(nm, &stbuf) == 0)
+               return stbuf.st_size;
+       return -1;
+}
+
+char * sysmsg[]  = {
+       0,
+       "Hangup",
+       "Interrupt",
+       "Quit",
+       "Illegal instruction",
+       "Trace/BPT trap",
+       "IOT trap",
+       "EMT trap",
+       "Floating exception",
+       "Killed",
+       "Bus error",
+       "Memory fault",
+       "Bad system call",
+       "Broken pipe",
+       "Alarm call",
+       "Terminated",
+       "Signal 16"
+};
+
+runvec(vec, outp)
+       struct arglist *vec;
+       char *outp;
+{
+       int status, fd;
+       char *task = vec->al_argv[1];
+
+       vec->al_argv[vec->al_argc] = 0;
+       if (FLAG(v))
+               print_vec(vec);
+       if (exec == 0)
+               return 1;
+       if (fork() == 0) {      /* start up the process */
+               extern int errno;
+               if (outp) {     /* redirect standard output     */
+                       close(1);
+                       if ((fd = creat(outp, 0666)) < 0)
+                               panic("cannot create %s", outp);
+                       if (fd != 1)
+                               panic("illegal redirection");
+               }
+               if (debug) report("exec %s", task);
+               execv(task, &(vec->al_argv[1]));
+               /* not an a.out file, let's try it with the SHELL */
+               if (debug) report("try it with %s", SHELL);
+               if (errno == ENOEXEC) {
+                       vec->al_argv[0] = SHELL;
+                       execv(SHELL, &(vec->al_argv[0]));
+               }
+               /* failed, so ... */
+               panic("cannot execute %s", task);
+               exit(1);
+       }
+       else {
+               int loworder, highorder, sig;
+
+               wait(&status);
+               loworder = status & 0377;
+               highorder = (status >> 8) & 0377;
+               if (loworder == 0) {
+                       if (highorder)
+                               report("%s: exit status %d", task, highorder);
+                       return highorder ? ((RET_CODE = 1), 0) : 1;
+               }
+               else {
+                       sig = loworder & 0177;
+                       if (sig == 0177)
+                               report("%s: stopped by ptrace", task);
+                       else
+                       if (sysmsg[sig])
+                               report("%s: %s%s", task, sysmsg[sig],
+                                       (loworder & 0200)
+                                               ? " - core dumped"
+                                               : "");
+                       RET_CODE = 1;
+                       return 0;
+               }
+       }
+       /*NOTREACHED*/
+}
+
+bad_option(str)
+       char *str;
+{
+       report("bad option %s", str);
+}
+
+/*VARARGS1*/
+report(fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+       char *fmt;
+{
+       fprintf(stderr, "%s: ", ProgCall);
+       fprintf(stderr, fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+       fprintf(stderr, "\n");
+}
+
+/*VARARGS1*/
+panic(fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9)
+       char *fmt;
+{
+       fprintf(stderr, "%s: ", ProgCall);
+       fprintf(stderr, fmt, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9);
+       fprintf(stderr, "\n");
+       exit(1);
+}
+
+set_traps(f)
+       int (*f)();
+{
+       signal(SIGHUP, f);
+       signal(SIGINT, f);
+       signal(SIGQUIT, f);
+       signal(SIGALRM, f);
+       signal(SIGTERM, f);
+}
+
+/*ARGSUSED*/
+trap(sig)
+{
+       set_traps(SIG_IGN);
+       panic("Trapped");
+}
+
+print_vec(vec)
+       struct arglist *vec;
+{
+       register i;
+
+       for (i = 1; i < vec->al_argc; i++)
+               printf("%s ", vec->al_argv[i]);
+       printf("\n");
+}
+
+char *
+cindex(s, c)
+       char *s, c;
+{
+       while (*s)
+               if (*s++ == c)
+                       return s - 1;
+       return (char *) 0;
+}
diff --git a/lang/cem/cemcom.ansi/cemcom.1 b/lang/cem/cemcom.ansi/cemcom.1
new file mode 100644 (file)
index 0000000..03e9d4a
--- /dev/null
@@ -0,0 +1,79 @@
+.TH EM_CEMCOM 6ACK
+.ad
+.SH NAME
+em_cemcom \- C to EM compiler
+.SH SYNOPSIS
+\fB~/em/lib/em_cemcom\fP [\fIoptions\fP] \fIsource \fP[\fIdestination \fP[\fInamelist\fP]]
+.SH DESCRIPTION
+\fICemcom\fP is a compiler that translates C programs
+into EM compact code.
+The input is taken from \fIsource\fP, while the
+EM code is written on \fIdestination\fP.
+If either of these two names is "\fB-\fP", standard input or output respectively
+is taken.
+The file \fInamelist\fP, if supplied, will contain a list of the names
+of external, so-called \fBcommon\fP, variables.
+When the preprocessor is invoked to run stand-alone, \fIdestination\fP
+needs not be specified.
+.br
+\fIOptions\fP is a, possibly empty, sequence of the following combinations:
+.IP \fB\-D\fIname\fR=\fItext\fR
+.br
+define \fIname\fR as a macro with \fItext\fR as its replacement text.
+.IP \fB\-D\fIname\fR
+.br
+the same as \fB\-D\fIname\fR=1.
+.IP \fB\-I\fIdirname\fR
+.br
+insert \fIdirname\fR in the list of include directories.
+.IP \fB\-M\fP\fIn\fP
+set maximum identifier length to \fIn\fP.
+.IP \fB\-n\fR
+do not generate EM register messages.
+The user-declared variables are not stored into registers on the target
+machine.
+.IP \fB\-L\fR
+don't generate the EM \fBfil\fR and \fBlin\fR instructions 
+that usually are generated to enable
+an interpreter to keep track of the current location in the source code.
+.IP \fB\-p\fR
+generate code at each procedure entry to call the routine
+.BR procentry ,
+and at each return to call the routine
+.BE procexit .
+These routines are supplied with one parameter, a pointer to a
+string containing the name of the procedure.
+.IP \fB\-R\fR
+interpret the input as restricted C (according to the language as 
+described in \fIThe C programming language\fR by Kernighan and Ritchie.)
+.IP \fB\-U\fIname\fR
+.br
+get rid of the compiler-predefined macro \fIname\fR.
+.IP \fB\-V\fIcm\fR.\fIn\fR,\ \fB\-V\fIcm\fR.\fIncm\fR.\fIn\fR\ ...
+.br
+set the size and alignment requirements.
+The letter \fIc\fR indicates the simple type, which is one of
+\fBs\fR(short), \fBi\fR(int), \fBl\fR(long), \fBf\fR(float), \fBd\fR(double) or
+\fBp\fR(pointer).
+The \fIm\fR parameter can be used to specify the length of the type (in bytes)
+and the \fIn\fR parameter for the alignment of that type.
+Absence of \fIm\fR or \fIn\fR causes the default value to be retained.
+To specify that the bitfields should be right adjusted instead of the
+default left adjustment, specify \fBr\fR as \fIc\fR parameter.
+.IP \fB\-w\fR
+suppress warning messages
+.IP \fB\-\-\fItext\fR
+.br
+where \fItext\fR can be either of the above or
+a debug flag of the compiler (which is not useful for the common user.)
+This feature can be used in various shell scripts and surrounding programs
+to force a certain option to be handed over to \fBcemcom\fR.
+.LP
+.SH FILES
+.IR ~em/lib/em_cemcom :
+the compiler
+.SH DIAGNOSTICS
+All warning and error messages are written on standard error output.
+.SH REFERENCE
+Baalbergen, E.H., D. Grune, M. Waage ;"\fIThe CEM compiler\fR", 
+Informatica Manual IM-4
diff --git a/lang/cem/cemcom.ansi/ch7.c b/lang/cem/cemcom.ansi/ch7.c
new file mode 100644 (file)
index 0000000..cc664ff
--- /dev/null
@@ -0,0 +1,540 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * 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        */
+
+#include       "lint.h"
+#include       "nofloat.h"
+#include       "debug.h"
+#include       "nobitfield.h"
+#include       "idf.h"
+#include       "arith.h"
+#include       "proto.h"
+#include       "type.h"
+#include       "struct.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "def.h"
+#include       "Lpars.h"
+#include       "assert.h"
+#include       "file_info.h"
+
+extern char options[];
+extern char *symbol2str();
+
+/*     Most expression-handling routines have a pointer to a
+       (struct type *) as first parameter. The object under the pointer
+       gets updated in the process.
+*/
+
+ch7sel(expp, oper, idf)
+       struct expr **expp;
+       struct idf *idf;
+{
+       /*      The selector idf is applied to *expp; oper may be '.' or
+               ARROW.
+       */
+       register struct expr *exp;
+       register struct type *tp;
+       register struct sdef *sd;
+
+       any2opnd(expp, oper);
+       exp = *expp;
+       tp = exp->ex_type;
+       if (oper == ARROW)      {
+               if (tp->tp_fund == POINTER &&
+                   ( tp->tp_up->tp_fund == STRUCT ||
+                     tp->tp_up->tp_fund == UNION))     /* normal case */
+                       tp = tp->tp_up;
+               else {  /* constructions like "12->selector" and
+                               "char c; c->selector"
+                       */
+                       switch (tp->tp_fund)    {
+                       case INT:
+                       case LONG:
+                               /* Allowed by RM 14.1 */
+                               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));
+                       case ERRONEOUS:
+                               exp->ex_type = error_type;
+                               return;
+                       }
+               }
+       } /* oper == ARROW */
+       else { /* oper == '.' */
+               /* filter out illegal expressions "non_lvalue.sel" */
+               if (!exp->ex_lvalue) {
+                       expr_error(exp, "dot requires lvalue");
+                       return;
+               }
+       }
+       exp = *expp;
+       switch (tp->tp_fund)    {
+       case POINTER:   /* for int *p;  p->next = ...   */
+       case STRUCT:
+       case UNION:
+               break;
+       case INT:
+       case LONG:
+               /* warning will be given by idf2sdef() */
+               break;
+       default:
+               if (!is_anon_idf(idf))
+                       expr_error(exp, "selector %s applied to %s",
+                               idf->id_text, symbol2str(tp->tp_fund));
+       case ERRONEOUS:
+               exp->ex_type = error_type;
+               return;
+       }
+       sd = idf2sdef(idf, tp);
+       if (oper == '.')        {
+               /*      there are 3 cases in which the selection can be
+                       performed compile-time: 
+                       I:      n.sel (n either an identifier or a constant)
+                       II:     (e.s1).s2 (transformed into (e.(s1+s2)))
+                       III:    (e->s1).s2 (transformed into (e->(s1+s2)))
+                               The code performing these conversions is
+                               extremely obscure.
+               */
+               if (exp->ex_class == Value)     {
+                       /*      It is an object we know the address of; so
+                               we can calculate the address of the
+                               selected member 
+                       */
+                       exp->VL_VALUE += sd->sd_offset;
+                       exp->ex_type = sd->sd_type;
+                       if (exp->ex_type == error_type)
+                               exp->ex_flags |= EX_ERROR;
+               }
+               else
+               if (exp->ex_class == Oper)      {
+                       struct oper *op = &(exp->ex_object.ex_oper);
+                       
+                       if (op->op_oper == '.' || op->op_oper == ARROW) {
+                               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_flags |= EX_ERROR;
+                       }
+                       else
+                               exp = new_oper(sd->sd_type, exp, '.',
+                                               intexpr(sd->sd_offset, INT));
+               }
+       }
+       else /* oper == ARROW */
+               exp = new_oper(sd->sd_type,
+                       exp, oper, intexpr(sd->sd_offset, INT));
+       exp->ex_lvalue = (sd->sd_type->tp_fund != ARRAY);
+       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;
+       *expp = exp;
+}
+
+ch7incr(expp, oper)
+       struct expr **expp;
+{
+       /*      The monadic prefix/postfix incr/decr operator oper is
+               applied to *expp.
+       */
+       ch7asgn(expp, oper, intexpr((arith)1, INT));
+}
+
+ch7cast(expp, oper, tp)
+       register struct expr **expp;
+       register struct type *tp;
+{
+       /*      The expression *expp is cast to type tp; the cast is
+               caused by the operator oper.  If the cast has
+               to be passed on to run time, its left operand will be an
+               expression of class Type.
+       */
+       register struct type *oldtp;
+
+       if ((*expp)->ex_type->tp_fund == FUNCTION)
+               function2pointer(*expp);
+       if ((*expp)->ex_type->tp_fund == ARRAY)
+               array2pointer(*expp);
+       if ((*expp)->ex_class == String)
+               string2pointer(*expp);
+       oldtp = (*expp)->ex_type;
+
+#ifndef NOBITFIELD
+       if (oldtp->tp_fund == FIELD)    {
+               field2arith(expp);
+               ch7cast(expp, oper, tp);
+       }
+       else
+       if (tp->tp_fund == FIELD) {
+               ch7cast(expp, oper, tp->tp_up);
+       }
+       else
+#endif NOBITFIELD
+       if (equal_type(tp, oldtp)) {
+               /* life is easy */
+       }
+       else
+       if (tp->tp_fund == VOID) {
+               /* easy again */
+               (*expp)->ex_type = void_type;
+       }
+       else
+       if (is_arith_type(oldtp) && is_arith_type(tp))  {
+               int oldi = is_integral_type(oldtp);
+               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;
+                       else
+                               int2int(expp, tp);
+#else  LINT
+                       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;
+                       else
+                               int2float(expp, tp);
+#else  LINT
+                       int2float(expp, tp);
+#endif LINT
+               }
+               else
+               if (!oldi && i) {
+#ifdef LINT
+                       if (oper == CAST)
+                               (*expp)->ex_type = tp;
+                       else
+                               float2int(expp, tp);
+#else  LINT
+                       float2int(expp, tp);
+#endif LINT
+               }
+               else {
+                       /* !oldi && !i */
+#ifdef LINT
+                       if (oper == CAST)
+                               (*expp)->ex_type = tp;
+                       else
+                               float2float(expp, tp);
+#else  LINT
+                       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)        {
+               if (oper == CASTAB)
+                       expr_warning(*expp, "incompatible pointers");
+               else
+               if (oper != CAST)
+                       expr_warning(*expp, "incompatible pointers in %s",
+                                                       symbol2str(oper));
+#ifdef LINT
+               if (oper != CAST)
+                       lint_ptr_conv(oldtp->tp_up->tp_fund, tp->tp_up->tp_fund);
+#endif LINT
+               (*expp)->ex_type = tp;  /* free conversion */
+       }
+       else
+       if (oldtp->tp_fund == POINTER && is_integral_type(tp))  {
+               /* from pointer to integral */
+               if (oper != CAST)
+                       expr_warning(*expp,
+                               "illegal conversion of pointer to %s",
+                               symbol2str(tp->tp_fund));
+               if (oldtp->tp_size > tp->tp_size)
+                       expr_warning(*expp,
+                               "conversion of pointer to %s loses accuracy",
+                               symbol2str(tp->tp_fund));
+               if (oldtp->tp_size != tp->tp_size)
+                       int2int(expp, tp);
+               else
+                       (*expp)->ex_type = tp;
+       }
+       else
+       if (tp->tp_fund == POINTER && is_integral_type(oldtp))  {
+               /* from integral to pointer */
+               switch (oper)   {
+               case CAST:
+                       break;
+               case CASTAB:
+               case EQUAL:
+               case NOTEQUAL:
+               case '=':
+               case RETURN:
+                       if (is_cp_cst(*expp) && (*expp)->VL_VALUE == (arith)0)
+                               break;
+               default:
+                       expr_warning(*expp,
+                               "illegal conversion of %s to pointer",
+                               symbol2str(oldtp->tp_fund));
+                       break;
+               }
+               if (oldtp->tp_size > tp->tp_size)
+                       expr_warning(*expp,
+                               "conversion of %s to pointer loses accuracy",
+                               symbol2str(oldtp->tp_fund));
+               if (oldtp->tp_size != tp->tp_size)
+                       int2int(expp, tp);
+               else
+                       (*expp)->ex_type = tp;
+       }
+       else
+       if (oldtp->tp_fund == ERRONEOUS) {
+               /* we just won't look */
+               (*expp)->ex_type = tp;  /* brute force */
+       }
+       else
+       if (oldtp->tp_size == tp->tp_size && oper == CAST)      {
+               expr_warning(*expp, "dubious conversion based on equal size");
+               (*expp)->ex_type = tp;          /* brute force */
+       }
+       else    {
+               if (oldtp->tp_fund != ERRONEOUS && tp->tp_fund != ERRONEOUS)
+                       expr_error(*expp, "cannot convert %s to %s",
+                               symbol2str(oldtp->tp_fund),
+                               symbol2str(tp->tp_fund)
+                       );
+               (*expp)->ex_type = tp;          /* brute force */
+       }
+}
+
+/*     Determine whether two types are equal.
+*/
+equal_type(tp, otp)
+       register struct type *tp, *otp;
+{
+       if (tp == otp)
+               return 1;
+       if (!tp || !otp)
+               return 0;
+
+       if (tp->tp_fund != otp->tp_fund)
+               return 0;
+       if (tp->tp_unsigned != otp->tp_unsigned)
+               return 0;
+       if (tp->tp_align != otp->tp_align)
+               return 0;
+       if (tp->tp_fund != ARRAY)
+               if (tp->tp_size != otp->tp_size)
+                       return 0;
+
+       switch (tp->tp_fund) {
+
+       case FUNCTION:
+               /*      If both types have parameter type lists, the type of
+                       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;
+               return equal_type(tp->tp_up, otp->tp_up);
+
+       case ARRAY:
+               /*      If one type is an array of known size, the composite
+                       type is an array of that size
+               */
+               if (tp->tp_size != otp->tp_size &&
+                    (tp->tp_size != -1 && otp->tp_size != -1))
+                       return 0;
+               return equal_type(tp->tp_up, otp->tp_up);
+
+       case POINTER:
+       case FIELD:
+               return equal_type(tp->tp_up, otp->tp_up);
+
+       case STRUCT:
+       case UNION:
+       case ENUM:
+               return tp->tp_idf == otp->tp_idf && tp->tp_sdef == otp->tp_sdef;
+
+       default:
+               return 1;
+       }
+}
+
+equal_proto(pl, opl)
+       register struct proto *pl, *opl;
+{
+       if (pl == opl)
+               return 1;
+
+       /*      If only one type is a function type with a parameter type list
+               (a function prototype), the composite type is a function
+               prototype with parameter type list.
+       */
+       if (pl == 0 || opl == 0) return 0;
+
+       if (pl->pl_flag != opl->pl_flag)
+               return 0;
+
+       if (!equal_type(pl->pl_type, opl->pl_type))
+               return 0;
+
+       return equal_proto(pl->next, opl->next);
+}
+
+ch7asgn(expp, oper, expr)
+       struct expr **expp;
+       struct expr *expr;
+{
+       /*      The assignment operators.
+               "f op= e" should be interpreted as
+               "f = (typeof f)((typeof (f op e))f op (typeof (f op e))e)"
+               and not as "f = f op (typeof f)e".
+               Consider, for example, (i == 10) i *= 0.9; (i == 9), where
+               typeof i == int.
+               The resulting expression tree becomes:
+                               op=
+                               / \
+                              /   \
+                             f     (typeof (f op e))e
+               EVAL should however take care of evaluating (typeof (f op e))f
+       */
+       register struct expr *exp = *expp;
+       int fund = exp->ex_type->tp_fund;
+       int vol = 0;
+       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_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
+               wants this information.
+       vol = (exp->ex_flags & EX_VOLATILE) || (expr->ex_flags & EX_VOLATILE);
+       */
+
+       if (oper == '=') {
+               ch7cast(&expr, oper, exp->ex_type);
+               tp = expr->ex_type;
+       }
+       else {  /* turn e into e' where typeof(e') = typeof (f op e) */
+               struct expr *extmp = intexpr((arith)0, INT);
+
+               /* this is really $#@&*%$# ! */
+               /* if you correct this, please correct lint_new_oper() too */
+               extmp->ex_lvalue = 1;
+               extmp->ex_type = exp->ex_type;
+               ch7bin(&extmp, oper, expr);
+               /* Note that ch7bin creates a tree of the expression
+                       ((typeof (f op e))f op (typeof (f op e))e),
+                  where f ~ extmp and e ~ expr.
+                  We want to use (typeof (f op e))e.
+                  Ch7bin does not create a tree if both operands
+                  were illegal or constants!
+               */
+               tp = extmp->ex_type;    /* perform the arithmetic in type tp */
+               if (extmp->ex_class == Oper) {
+                       expr = extmp->OP_RIGHT;
+                       extmp->OP_RIGHT = NILEXPR;
+                       free_expression(extmp);
+               }
+               else
+                       expr = extmp;
+       }
+#ifndef NOBITFIELD
+       if (fund == FIELD)
+               exp = new_oper(exp->ex_type->tp_up, exp, oper, expr);
+       else
+               exp = new_oper(exp->ex_type, exp, oper, expr);
+#else NOBITFIELD
+       exp = new_oper(exp->ex_type, exp, oper, expr);
+#endif NOBITFIELD
+       exp->OP_TYPE = tp;      /* for EVAL() */
+       exp->ex_flags |= vol ? (EX_SIDEEFFECTS|EX_VOLATILE) : EX_SIDEEFFECTS;
+       *expp = exp;
+}
+
+/*     Some interesting (?) questions answered.
+*/
+int
+is_integral_type(tp)
+       register struct type *tp;
+{
+       switch (tp->tp_fund)    {
+       case GENERIC:
+       case CHAR:
+       case SHORT:
+       case INT:
+       case LONG:
+       case ENUM:
+               return 1;
+#ifndef NOBITFIELD
+       case FIELD:
+               return is_integral_type(tp->tp_up);
+#endif NOBITFIELD
+       default:
+               return 0;
+       }
+}
+
+int
+is_arith_type(tp)
+       register struct type *tp;
+{
+       switch (tp->tp_fund)    {
+       case GENERIC:
+       case CHAR:
+       case SHORT:
+       case INT:
+       case LONG:
+       case ENUM:
+#ifndef NOFLOAT
+       case FLOAT:
+       case DOUBLE:
+       case LNGDBL:
+#endif NOFLOAT
+               return 1;
+#ifndef NOBITFIELD
+       case FIELD:
+               return is_arith_type(tp->tp_up);
+#endif NOBITFIELD
+       default:
+               return 0;
+       }
+}
diff --git a/lang/cem/cemcom.ansi/ch7bin.c b/lang/cem/cemcom.ansi/ch7bin.c
new file mode 100644 (file)
index 0000000..e43f159
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* SEMANTIC ANALYSIS (CHAPTER 7RM)  --  BINARY OPERATORS */
+
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "nofloat.h"
+#include       "lint.h"
+#include       "idf.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();
+
+/*     This chapter asks for the repeated application of code to handle
+       an operation that may be executed at compile time or at run time,
+       depending on the constancy of the operands.
+*/
+
+#define commutative_binop(expp, oper, expr)    mk_binop(expp, oper, expr, 1)
+#define non_commutative_binop(expp, oper, expr)        mk_binop(expp, oper, expr, 0)
+
+ch7bin(expp, oper, expr)
+       register struct expr **expp;
+       struct expr *expr;
+{
+       /*      apply binary operator oper between *expp and expr.
+               NB: don't swap operands if op is one of the op= operators!!!
+       */
+
+       any2opnd(expp, oper);
+       any2opnd(&expr, oper);
+       switch (oper)   {
+       case '[':                               /* RM 7.1 */
+               /* RM 14.3 states that indexing follows the commutative laws */
+               switch ((*expp)->ex_type->tp_fund)      {
+               case POINTER:
+               case ARRAY:
+                       break;
+               case ERRONEOUS:
+                       return;
+               default:                /* unindexable */
+                       switch (expr->ex_type->tp_fund) {
+                       case POINTER:
+                       case ARRAY:
+                               break;
+                       case ERRONEOUS:
+                               return;
+                       default:
+                               expr_error(*expp,
+                                       "indexing an object of type %s",
+                                       symbol2str((*expp)->ex_type->tp_fund));
+                               return;
+                       }
+                       break;
+               }
+               ch7bin(expp, '+', expr);
+               ch7mon('*', expp);
+               break;
+
+       case '(':                               /* RM 7.1 */
+               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)      {
+                       expr_error(*expp, "call of non-function (%s)",
+                               symbol2str((*expp)->ex_type->tp_fund));
+                       /* leave the expression; it may still serve */
+                       free_expression(expr);  /* there go the parameters */
+               }
+               else
+                       *expp = new_oper((*expp)->ex_type->tp_up,
+                                       *expp, '(', expr);
+               (*expp)->ex_flags |= EX_SIDEEFFECTS;
+               break;
+
+       case PARCOMMA:                          /* RM 7.1 */
+               if ((*expp)->ex_type->tp_fund == FUNCTION)
+                       function2pointer(*expp);
+               *expp = new_oper(expr->ex_type, *expp, PARCOMMA, expr);
+               break;
+
+       case '%':
+       case MODAB:
+       case ANDAB:
+       case XORAB:
+       case ORAB:
+               opnd2integral(expp, oper);
+               opnd2integral(&expr, oper);
+               /* Fall through */
+       case '/':
+       case DIVAB:
+       case TIMESAB:
+               arithbalance(expp, oper, &expr);
+               non_commutative_binop(expp, oper, expr);
+               break;
+
+       case '&':
+       case '^':
+       case '|':
+               opnd2integral(expp, oper);
+               opnd2integral(&expr, oper);
+               /* Fall through */
+       case '*':
+               arithbalance(expp, oper, &expr);
+               commutative_binop(expp, oper, expr);
+               break;
+
+       case '+':
+               if (expr->ex_type->tp_fund == POINTER)  { /* swap operands */
+                       struct expr *etmp = expr;
+                       expr = *expp;
+                       *expp = etmp;
+               }
+               /*FALLTHROUGH*/
+       case PLUSAB:
+       case POSTINCR:
+       case PLUSPLUS:
+               if ((*expp)->ex_type->tp_fund == POINTER)       {
+                       pointer_arithmetic(expp, oper, &expr);
+                       if (expr->ex_type->tp_size != (*expp)->ex_type->tp_size)
+                               ch7cast(&expr, CAST, (*expp)->ex_type);
+                       pointer_binary(expp, oper, expr);
+               }
+               else    {
+                       arithbalance(expp, oper, &expr);
+                       if (oper == '+')
+                               commutative_binop(expp, oper, expr);
+                       else
+                               non_commutative_binop(expp, oper, expr);
+               }
+               break;
+
+       case '-':
+       case MINAB:
+       case POSTDECR:
+       case MINMIN:
+               if ((*expp)->ex_type->tp_fund == POINTER)       {
+                       if (expr->ex_type->tp_fund == POINTER)
+                               pntminuspnt(expp, oper, expr);
+                       else {
+                               pointer_arithmetic(expp, oper, &expr);
+                               pointer_binary(expp, oper, expr);
+                       }
+               }
+               else    {
+                       arithbalance(expp, oper, &expr);
+                       non_commutative_binop(expp, oper, expr);
+               }
+               break;
+
+       case LEFT:
+       case RIGHT:
+       case LEFTAB:
+       case RIGHTAB:
+               opnd2integral(expp, oper);
+               opnd2integral(&expr, oper);
+               arithbalance(expp, oper, &expr); /* ch. 7.5 */
+               ch7cast(&expr, oper, int_type); /* cvt. rightop to int */
+               non_commutative_binop(expp, oper, expr);
+               break;
+
+       case '<':
+       case '>':
+       case LESSEQ:
+       case GREATEREQ:
+       case EQUAL:
+       case NOTEQUAL:
+               relbalance(expp, oper, &expr);
+               non_commutative_binop(expp, oper, expr);
+               (*expp)->ex_type = int_type;
+               break;
+
+       case AND:
+       case OR:
+               opnd2test(expp, oper);
+               opnd2test(&expr, oper);
+               if (is_cp_cst(*expp))   {
+                       register struct expr *ex = *expp;
+
+                       /* the following condition is a short-hand for
+                               ((oper == AND) && o1) || ((oper == OR) && !o1)
+                               where o1 == (*expp)->VL_VALUE;
+                               and ((oper == AND) || (oper == OR))
+                       */
+                       if ((oper == AND) == (ex->VL_VALUE != (arith)0))
+                               *expp = expr;
+                       else {
+                               ex->ex_flags |= expr->ex_flags;
+                               free_expression(expr);
+                               *expp = intexpr((arith)((oper == AND) ? 0 : 1),
+                                               INT);
+                       }
+                       (*expp)->ex_flags |= ex->ex_flags;
+                       free_expression(ex);
+               }
+               else
+               if (is_cp_cst(expr))    {
+                       /* Note!!!: the following condition is a short-hand for
+                               ((oper == AND) && o2) || ((oper == OR) && !o2)
+                               where o2 == expr->VL_VALUE
+                               and ((oper == AND) || (oper == OR))
+                       */
+                       if ((oper == AND) == (expr->VL_VALUE != (arith)0)) {
+                               (*expp)->ex_flags |= expr->ex_flags;
+                               free_expression(expr);
+                       }
+                       else {
+                               if (oper == OR)
+                                       expr->VL_VALUE = (arith)1;
+                               ch7bin(expp, ',', expr);
+                       }
+               }
+               else
+                       *expp = new_oper(int_type, *expp, oper, expr);
+               (*expp)->ex_flags |= EX_LOGICAL;
+               break;
+
+       case ':':
+               if (    is_struct_or_union((*expp)->ex_type->tp_fund)
+               ||      is_struct_or_union(expr->ex_type->tp_fund)
+               )       {
+                       if (!equal_type((*expp)->ex_type, expr->ex_type))
+                               expr_error(*expp, "illegal balance");
+               }
+               else
+                       relbalance(expp, oper, &expr);
+#ifdef LINT
+               if (    (is_cp_cst(*expp) && is_cp_cst(expr))
+               &&      (*expp)->VL_VALUE == expr->VL_VALUE
+               ) {
+                       hwarning("operands of : are constant and equal");
+               }
+#endif LINT
+               *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
+               break;
+
+       case '?':
+               opnd2logical(expp, oper);
+               if (is_cp_cst(*expp)) {
+#ifdef LINT
+                       hwarning("condition in ?: expression is constant");
+#endif LINT
+                       *expp = (*expp)->VL_VALUE ?
+                               expr->OP_LEFT : expr->OP_RIGHT;
+               }
+               else {
+                       *expp = new_oper(expr->ex_type, *expp, oper, expr);
+               }
+               break;
+
+       case ',':
+               if (is_cp_cst(*expp))
+                       *expp = expr;
+               else
+                       *expp = new_oper(expr->ex_type, *expp, oper, expr);
+               (*expp)->ex_flags |= EX_COMMA;
+               break;
+       }
+}
+
+pntminuspnt(expp, oper, expr)
+       register struct expr **expp, *expr;
+{
+       /*      Subtracting two pointers is so complicated it merits a
+               routine of its own.
+       */
+       struct type *up_type = (*expp)->ex_type->tp_up;
+
+       if (!equal_type(up_type, expr->ex_type->tp_up)) {
+               expr_error(*expp, "subtracting incompatible pointers");
+               free_expression(expr);
+               erroneous2int(expp);
+               return;
+       }
+       /*      we hope the optimizer will eliminate the load-time
+               pointer subtraction
+       */
+       *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
+       ch7cast(expp, CAST, pa_type);   /* ptr-ptr: result has pa_type  */
+       ch7bin(expp, '/',
+               intexpr(size_of_type(up_type, "object"), pa_type->tp_fund));
+       ch7cast(expp, CAST, int_type);  /* result will be an integer expr */
+}
+
+mk_binop(expp, oper, expr, commutative)
+       struct expr **expp;
+       register struct expr *expr;
+{
+       /*      Constructs in *expp the operation indicated by the operands.
+               "commutative" indicates whether "oper" is a commutative
+               operator.
+       */
+       register struct expr *ex = *expp;
+
+       if (is_cp_cst(expr) && is_cp_cst(ex))
+               cstbin(expp, oper, expr);
+       else    {
+               *expp = (commutative && expr->ex_depth >= ex->ex_depth) ?
+                               new_oper(ex->ex_type, expr, oper, ex) :
+                               new_oper(ex->ex_type, ex, oper, expr);
+       }
+}
+
+pointer_arithmetic(expp1, oper, expp2)
+       register struct expr **expp1, **expp2;
+{
+       /*      prepares the integral expression expp2 in order to
+               apply it to the pointer expression expp1
+       */
+#ifndef NOFLOAT
+       if (any2arith(expp2, oper) == DOUBLE)   {
+               expr_error(*expp2,
+                       "illegal combination of float and pointer");
+               erroneous2int(expp2);
+       }
+#endif NOFLOAT
+       ch7bin( expp2, '*',
+               intexpr(size_of_type((*expp1)->ex_type->tp_up, "object"),
+                       pa_type->tp_fund)
+       );
+}
+
+pointer_binary(expp, oper, expr)
+       register struct expr **expp, *expr;
+{
+       /*      constructs the pointer arithmetic expression out of
+               a pointer expression, a binary operator and an integral
+               expression.
+       */
+       if (is_ld_cst(expr) && is_ld_cst(*expp))
+               cstbin(expp, oper, expr);
+       else
+               *expp = new_oper((*expp)->ex_type, *expp, oper, expr);
+}
diff --git a/lang/cem/cemcom.ansi/ch7mon.c b/lang/cem/cemcom.ansi/ch7mon.c
new file mode 100644 (file)
index 0000000..9e1be20
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* SEMANTIC ANALYSIS (CHAPTER 7RM) -- MONADIC OPERATORS */
+
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "nofloat.h"
+#include       "nobitfield.h"
+#include       "Lpars.h"
+#include       "arith.h"
+#include       "type.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "idf.h"
+#include       "def.h"
+
+extern char options[];
+extern long full_mask[/*MAXSIZE*/];    /* cstoper.c */
+char *symbol2str();
+
+ch7mon(oper, expp)
+       register struct expr **expp;
+{
+       /*      The monadic prefix operator oper is applied to *expp.
+       */
+       register struct expr *expr;
+
+       switch (oper)   {
+       case '*':                       /* RM 7.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 {
+                       expr = *expp;
+                       if (expr->ex_lvalue == 0 && expr->ex_class != String)
+                               /* dereference in administration only */
+                               expr->ex_type = expr->ex_type->tp_up;
+                       else    /* runtime code */
+                               *expp = new_oper(expr->ex_type->tp_up, NILEXPR,
+                                                       '*', expr);
+                       (*expp)->ex_lvalue = (
+                               (*expp)->ex_type->tp_fund != ARRAY &&
+                               (*expp)->ex_type->tp_fund != FUNCTION
+                               );
+                       if ((*expp)->ex_type->tp_typequal & TQ_CONST)
+                               (*expp)->ex_flags |= EX_READONLY;
+                       if ((*expp)->ex_type->tp_typequal & TQ_VOLATILE)
+                               (*expp)->ex_flags |= EX_VOLATILE;
+               }
+               break;
+       case '&':
+               if ((*expp)->ex_type->tp_fund == ARRAY) {
+                       warning("& before array ignored");
+                       array2pointer(*expp);
+               }
+               else
+               if ((*expp)->ex_type->tp_fund == FUNCTION) {
+                       warning("& before function ignored");
+                       function2pointer(*expp);
+               }
+               else
+#ifndef NOBITFIELD
+               if ((*expp)->ex_type->tp_fund == FIELD)
+                       expr_error(*expp, "& applied to field variable");
+               else
+#endif NOBITFIELD
+               if (!(*expp)->ex_lvalue)
+                       expr_error(*expp, "& applied to non-lvalue");
+               else {
+                       /* assume that enums are already filtered out   */
+                       if (ISNAME(*expp)) {
+                               register struct def *def =
+                                       (*expp)->VL_IDF->id_def;
+
+                               /*      &<var> indicates that <var>
+                                       cannot be used as register
+                                       anymore
+                               */
+                               if (def->df_sc == REGISTER) {
+                                       expr_error(*expp,
+                                       "& on register variable not allowed");
+                                       break;  /* break case '&' */
+                               }
+                       }
+                       (*expp)->ex_type = pointer_to((*expp)->ex_type);
+                       (*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)
+                       );
+                       erroneous2int(expp);
+                       break;
+               }
+               /* FALLTHROUGH */
+       }
+#endif NOFLOAT
+       case '-':
+               any2arith(expp, oper);
+               if (is_cp_cst(*expp))   {
+                       arith o1 = (*expp)->VL_VALUE;
+
+                       (*expp)->VL_VALUE = (oper == '-') ? -o1 :
+                         ((*expp)->ex_type->tp_unsigned ?
+                               (~o1) & full_mask[(*expp)->ex_type->tp_size] :
+                               ~o1
+                         );
+               }
+               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;
+       case '!':
+               if ((*expp)->ex_type->tp_fund == FUNCTION)
+                       function2pointer(*expp);
+               if ((*expp)->ex_type->tp_fund != POINTER)
+                       any2arith(expp, oper);
+               opnd2test(expp, '!');
+               if (is_cp_cst(*expp))   {
+                       (*expp)->VL_VALUE = !((*expp)->VL_VALUE);
+                       (*expp)->ex_type = int_type;    /* a cast ???(EB) */
+               }
+               else
+                       *expp = new_oper(int_type, NILEXPR, oper, *expp);
+               (*expp)->ex_flags |= EX_LOGICAL;
+               break;
+       case PLUSPLUS:
+       case MINMIN:
+               ch7incr(expp, oper);
+               break;
+       case SIZEOF:
+               if (ISNAME(*expp) && (*expp)->VL_IDF->id_def->df_formal_array)
+                       warning("sizeof formal array %s is sizeof pointer!",
+                               (*expp)->VL_IDF->id_text);
+               expr = intexpr((*expp)->ex_class == String ?
+                                  (arith)((*expp)->SG_LEN) :
+                                  size_of_type((*expp)->ex_type, "object"),
+                               INT);
+               expr->ex_flags |= EX_SIZEOF;
+               free_expression(*expp);
+               *expp = expr;
+               break;
+       }
+}
diff --git a/lang/cem/cemcom.ansi/char.tab b/lang/cem/cemcom.ansi/char.tab
new file mode 100644 (file)
index 0000000..682d10a
--- /dev/null
@@ -0,0 +1,74 @@
+%
+%      CHARACTER CLASSES
+%
+% some general settings:
+%S129
+%F     %s,
+%
+%      START OF TOKEN
+%
+%iSTGARB
+STSKIP:\r \t\013\f
+STNL:\n
+STCOMP:-!&+<=>|
+STSIMP:%()*,/:;?[]^{}~
+STCHAR:'
+STIDF:a-zA-KM-Z_
+STELL:L
+STNUM:.0-9
+STSTR:"
+STEOI:\200
+%T/* character classes */
+%T#include "class.h"
+%Tchar tkclass[] = {
+%p
+%T};
+%
+%      INIDF
+%
+%C
+1:a-zA-Z_0-9
+%Tchar inidf[] = {
+%F     %s,
+%p
+%T};
+%
+%      ISDIG
+%
+%C
+1:0-9
+%Tchar isdig[] = {
+%p
+%T};
+%
+%      ISHEX
+%
+%C
+1:a-fA-F
+%Tchar ishex[] = {
+%p
+%T};
+%
+%      ISOCT
+%
+%C
+1:0-7
+%Tchar isoct[] = {
+%p
+%T};
+%
+%      ISSUF
+%
+%C
+1:lLuU
+%Tchar issuf[] = {
+%p
+%T};
+%
+%      ISWSP
+%
+%C
+1: \t\n
+%Tchar iswsp[] = {
+%p
+%T};
diff --git a/lang/cem/cemcom.ansi/class.h b/lang/cem/cemcom.ansi/class.h
new file mode 100644 (file)
index 0000000..d57ce26
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*             U S E   O F   C H A R A C T E R   C L A S S E S         */
+
+/*     As a starter, chars are divided into classes, according to which
+       token they can be the start of.
+       At present such a class number is supposed to fit in 4 bits.
+*/
+
+#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
+       packed in 4 bits.
+*/
+
+#define        STSKIP  0       /* spaces and so on: skipped characters         */
+#define        STNL    1       /* newline character(s): update linenumber etc. */
+#define        STGARB  2       /* garbage ascii character: not allowed in C    */
+#define        STSIMP  3       /* this character can occur as token in C       */
+#define        STCOMP  4       /* this one can start a compound token in C     */
+#define        STELL   5       /* possible start of wide char stuff or idf     */
+#define        STIDF   6       /* being the initial character of an identifier */
+#define        STCHAR  7       /* the starter of a character constant          */
+#define        STSTR   8       /* the starter of a string                      */
+#define        STNUM   9       /* the starter of a numeric constant            */
+#define        STEOI   10      /* End-Of-Information mark                      */
+
+/*     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
+       the decision whether a character has a special meaning.
+*/
+#define        in_idf(ch)      (inidf[ch])
+#define        is_oct(ch)      (isoct[ch])
+#define        is_dig(ch)      (isdig[ch])
+#define        is_hex(ch)      (ishex[ch])
+#define        is_suf(ch)      (issuf[ch])
+#define        is_wsp(ch)      (iswsp[ch])
+
+extern char tkclass[];
+extern char inidf[], isoct[], isdig[], ishex[], issuf[], iswsp[];
diff --git a/lang/cem/cemcom.ansi/code.c b/lang/cem/cemcom.ansi/code.c
new file mode 100644 (file)
index 0000000..5717399
--- /dev/null
@@ -0,0 +1,657 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     C O D E - G E N E R A T I N G   R O U T I N E S         */
+
+#include       "lint.h"
+#include       <em.h>
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "dataflow.h"
+#include       "use_tmp.h"
+#include       "arith.h"
+#include       "type.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "code.h"
+#include       "stmt.h"
+#include       "def.h"
+#include       "expr.h"
+#include       "sizes.h"
+#include       "stack.h"
+#include       "level.h"
+#include       "decspecs.h"
+#include       "declar.h"
+#include       "Lpars.h"
+#include       "specials.h"
+#include       "atw.h"
+#include       "assert.h"
+#include       "noRoption.h"
+#include       "file_info.h"
+#ifdef LINT
+#include       "l_lint.h"
+#endif LINT
+
+label lab_count = 1;
+label datlab_count = 1;
+
+#ifndef NOFLOAT
+int fp_used;
+#endif NOFLOAT
+
+/* global function info */
+char *func_name;
+struct type *func_type;
+int func_notypegiven;
+
+#ifdef USE_TMP
+static int     tmp_id;
+static int     pro_id;
+#endif USE_TMP
+
+extern char options[];
+extern char *symbol2str();
+
+#ifndef        LINT
+init_code(dst_file)
+       char *dst_file;
+{
+       /*      init_code() initialises the output file on which the
+               compact EM code is written
+       */
+       C_init(word_size, pointer_size); /* initialise EM module */
+       if (C_open(dst_file) == 0)
+               fatal("cannot write to %s\n", dst_file);
+       C_magic();
+       C_ms_emx(word_size, pointer_size);
+#ifdef USE_TMP
+#ifdef PREPEND_SCOPES
+       C_insertpart(tmp_id = C_getid());
+#endif USE_TMP
+#endif PREPEND_SCOPES
+}
+#endif LINT
+
+struct string_cst *str_list = 0;
+
+code_string(val, len, dlb)
+       char *val;
+       int len;
+       label dlb;
+{
+       register struct string_cst *sc = new_string_cst();
+
+       C_ina_dlb(dlb);
+       sc->next = str_list;
+       str_list = sc;
+       sc->sc_value = val;
+       sc->sc_len = len;
+       sc->sc_dlb = dlb;
+}
+
+def_strings(sc)
+       register struct string_cst *sc;
+{
+       while (sc) {
+               struct string_cst *sc1 = sc;
+
+               C_df_dlb(sc->sc_dlb);
+               str_cst(sc->sc_value, sc->sc_len);
+               sc = sc->next;
+               free_string_cst(sc1);
+       }
+}
+
+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);
+       C_close();
+}
+
+#ifdef PREPEND_SCOPES
+prepend_scopes()
+{
+       /*      prepend_scopes() runs down the list of global idf's
+               and generates those exa's, exp's, ina's and inp's
+               that superior hindsight has provided.
+       */
+       register struct stack_entry *se = local_level->sl_entry;
+
+#ifdef USE_TMP
+       C_beginpart(tmp_id);
+#endif USE_TMP
+       while (se != 0) {
+               register struct idf *id = se->se_idf;
+               register struct def *df = id->id_def;
+               
+               if (df && (df->df_initialized || df->df_used || df->df_alloc))
+                       code_scope(id->id_text, df);
+               se = se->next;
+       }
+#ifdef USE_TMP
+       C_endpart(tmp_id);
+#endif USE_TMP
+}
+#endif PREPEND_SCOPES
+
+code_scope(text, def)
+       char *text;
+       register struct def *def;
+{
+       /*      generates code for one name, text, of the storage class
+               as given by def, if meaningful.
+       */
+       int fund = def->df_type->tp_fund;
+       
+       switch (def->df_sc)     {
+       case EXTERN:
+       case GLOBAL:
+       case IMPLICIT:
+               if (fund == FUNCTION)
+                       C_exp(text);
+               else
+                       C_exa_dnam(text);
+               break;
+       case STATIC:
+               if (fund == FUNCTION)
+                       C_inp(text);
+               else
+                       C_ina_dnam(text);
+               break;
+       }
+}
+
+static label return_label, return2_label;
+static char return_expr_occurred;
+static arith func_size;
+static label func_res_label;
+static char *last_fn_given = "";
+static label file_name_label;
+
+begin_proc(ds, idf)            /* to be called when entering a procedure */
+       struct decspecs *ds;
+       struct idf *idf;
+{
+       /*      begin_proc() is called at the entrance of a new function
+               and performs the necessary code generation:
+               -       a scope indicator (if needed) exp/inp
+               -       the procedure entry pro $name
+               -       reserves some space if the result of the function
+                       does not fit in the return area
+               -       a fil pseudo instruction
+       */
+       register char *name = idf->id_text;
+       register struct def *def = idf->id_def;
+
+#ifndef PREPEND_SCOPES
+       code_scope(name, def);
+#endif PREPEND_SCOPES
+#ifdef DATAFLOW
+       if (options['d'])
+               DfaStartFunction(name);
+#endif DATAFLOW
+
+       /* set global function info */
+       func_name = name;
+       if (def->df_type->tp_fund != FUNCTION) {
+               error("making function body for non-function");
+               func_type = error_type;
+       }
+       else {
+               func_type = def->df_type->tp_up;
+       }
+       func_notypegiven = ds->ds_notypegiven;
+       func_size = ATW(func_type->tp_size);
+
+#ifndef USE_TMP
+       C_pro_narg(name);
+#else
+       C_insertpart(pro_id = C_getid());
+#endif
+       if (is_struct_or_union(func_type->tp_fund))     {
+               C_df_dlb(func_res_label = data_label());
+               C_bss_cst(func_size, (arith)0, 1);
+       }
+       else
+               func_res_label = 0;
+       /*      Special arrangements if the function result doesn't fit in
+               the function return area of the EM machine.  The size of
+               the function return area is implementation dependent.
+       */
+       lab_count = (label) 1;
+       return_label = text_label();
+       return2_label = text_label();
+       return_expr_occurred = 0;
+       LocalInit();
+       prc_entry(name);
+       if (! options['L'])     {       /* profiling */
+               if (strcmp(last_fn_given, FileName) != 0)       {
+                       /* previous function came from other file */
+                       C_df_dlb(file_name_label = data_label());
+                       C_con_scon(last_fn_given = FileName,
+                               (arith)(strlen(FileName) + 1));
+               }
+               /* enable debug trace of EM source */
+               C_fil_dlb(file_name_label, (arith)0);
+               C_lin((arith)LineNumber);
+       }
+}
+
+end_proc(fbytes)
+       arith fbytes;
+{
+       /*      end_proc() deals with the code to be generated at the end of
+               a function, as there is:
+               -       the EM ret instruction: "ret 0"
+               -       loading of the function result in the function
+                       result area if there has been a return <expr>
+                       in the function body (see do_return_expr())
+               -       indication of the use of floating points
+               -       indication of the number of bytes used for
+                       formal parameters
+               -       use of special identifiers such as "setjmp"
+               -       "end" + number of bytes used for local variables
+       */
+       arith nbytes;
+       char optionsn = options['n'];
+
+#ifdef DATAFLOW
+       if (options['d'])
+               DfaEndFunction();
+#endif DATAFLOW
+       C_df_ilb(return2_label);
+       if (return_expr_occurred) C_asp(-func_size);
+       C_df_ilb(return_label);
+       prc_exit();
+#ifndef        LINT
+       if (return_expr_occurred) {
+               if (func_res_label != 0)        {
+                       C_lae_dlb(func_res_label, (arith)0);
+                       store_block(func_size, func_type->tp_align);
+                       C_lae_dlb(func_res_label, (arith)0);
+                       C_ret(pointer_size);
+               }
+               else
+                       C_ret(func_size);
+       }
+       else    C_ret((arith) 0);
+#endif LINT
+
+       /* getting the number of "local" bytes is posponed until here,
+          because copying the function result in "func_res_label" may
+          need temporaries! However, local_level is now L_FORMAL2, because
+          L_LOCAL is already unstacked. Therefore, "unstack_level" must
+          also pass "sl_max_block" to the level above L_LOCAL.
+       */
+       nbytes = ATW(- local_level->sl_max_block);
+#ifdef USE_TMP
+       C_beginpart(pro_id);
+       C_pro(func_name, nbytes);
+#endif
+       if (fbytes > max_int) {
+               error("%s has more than %ld parameter bytes",
+                       func_name, (long) max_int);
+       }
+       C_ms_par(fbytes);               /* # bytes for formals          */
+       if (sp_occurred[SP_SETJMP]) {   /* indicate use of "setjmp"     */
+               options['n'] = 1;
+               C_ms_gto();
+               sp_occurred[SP_SETJMP] = 0;
+       }
+#ifdef USE_TMP
+       C_endpart(pro_id);
+#endif
+       LocalFinish();
+       C_end(nbytes);
+       if (nbytes > max_int) {
+               error("%s has more than %ld bytes of local variables",
+                       func_name, (long) max_int);
+       }
+       options['n'] = optionsn;
+}
+
+do_return()
+{
+       /*      do_return handles the case of a return without expression.
+               This version branches to the return label, which is
+               probably smarter than generating a direct return.
+               Return sequences may be expensive.
+       */
+       C_bra(return2_label);
+}
+
+do_return_expr(expr)
+       struct expr *expr;
+{
+       /*      do_return_expr() generates the expression and the jump for
+               a return statement with an expression.
+       */
+       ch7cast(&expr, RETURN, func_type);
+       code_expr(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
+       C_bra(return_label);
+       return_expr_occurred = 1;
+}
+
+code_declaration(idf, expr, lvl, sc)
+       register struct idf *idf;       /* idf to be declared   */
+       struct expr *expr;      /* initialisation; NULL if absent       */
+       int lvl;                /* declaration level    */
+       int sc;                 /* storage class, as in the declaration */
+{
+       /*      code_declaration() does the actual declaration of the
+               variable indicated by "idf" on declaration level "lvl".
+               If the variable is initialised, the expression is given
+               in "expr", but for global and static initialisations it
+               is just non-zero, as the expression is not parsed yet.
+               There are some cases to be considered:
+               -       filter out typedefs, they don't correspond to code;
+               -       global variables, coded only if initialized;
+               -       local static variables;
+               -       local automatic variables;
+               Since the expression may be modified in the process,
+               code_declaration() frees it after use, as the caller can
+               no longer do so.
+               
+               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;
+       */
+       register struct def *def = idf->id_def;
+       register arith size = def->df_type->tp_size;
+       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) {
+               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
+                       && size >= 0
+               )
+                       def->df_alloc = ALLOC_SEEN;
+               if (expr) {     /* code only if initialized */
+#ifndef PREPEND_SCOPES
+                       code_scope(idf->id_text, def);
+#endif PREPEND_SCOPES
+                       def->df_alloc = ALLOC_DONE;
+                       C_df_dnam(idf->id_text);
+               }
+       }
+       else
+       if (lvl >= L_LOCAL)     {       /* local variable       */
+               /* STATIC, EXTERN, GLOBAL, IMPLICIT, AUTO or REGISTER */
+               switch (def_sc) {
+               case STATIC:
+                       if (def->df_type->tp_fund == FUNCTION) {
+                               /* should produce "inp $function" ??? */
+                               break;
+                       }
+                       /*      they are handled on the spot and get an
+                               integer label in EM.
+                       */
+                       C_df_dlb((label)def->df_address);
+                       if (expr) { /* there is an initialisation */
+                       }
+                       else {  /* produce blank space */
+                               if (size <= 0) {
+                                       error("size of %s unknown", idf->id_text);
+                                       size = (arith)0;
+                               }
+                               C_bss_cst(ATW(size), (arith)0, 1);
+                       }
+                       break;
+               case EXTERN:
+               case GLOBAL:
+               case IMPLICIT:
+                       /* we are sure there is no expression */
+#ifndef        PREPEND_SCOPES
+                       code_scope(idf->id_text, def);
+#endif PREPEND_SCOPES
+                       break;
+               case AUTO:
+               case REGISTER:
+                       if (expr)
+                               loc_init(expr, idf);
+                       break;
+               default:
+                       crash("bad local storage class");
+                       /*NOTREACHED*/
+               }
+       }
+}
+
+loc_init(expr, id)
+       struct expr *expr;
+       register struct idf *id;
+{
+       /*      loc_init() generates code for the assignment of
+               expression expr to the local variable described by id.
+               It frees the expression afterwards.
+       */
+       register struct expr *e = expr;
+       register struct type *tp = id->id_def->df_type;
+       
+       ASSERT(id->id_def->df_sc != STATIC);
+       switch (tp->tp_fund)    {
+       case ARRAY:
+       case STRUCT:
+       case UNION:
+               error("automatic %s cannot be initialized in declaration",
+                       symbol2str(tp->tp_fund));
+               free_expression(e);
+               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;
+               }
+       }
+       else    {       /* not embraced */
+               ch7cast(&expr, '=', tp);        /* may modify expr */
+#ifndef        LINT
+               {
+                       struct value vl;
+
+                       EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
+                       vl.vl_class = Name;
+                       vl.vl_data.vl_idf = id;
+                       vl.vl_value = (arith)0;
+                       store_val(&vl, tp);
+               }
+#else  LINT
+               id->id_def->df_set = 1;
+#endif LINT
+               free_expression(expr);
+       }
+}
+
+bss(idf)
+       register struct idf *idf;
+{
+       /*      bss() allocates bss space for the global idf.
+       */
+       arith size = idf->id_def->df_type->tp_size;
+       
+#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)
+       register struct def *df;
+{
+       /*      formal_cvt() converts a formal parameter of type char or
+               short from int to that type.
+       */
+       register struct type *tp = df->df_type;
+
+       if (tp->tp_size != int_size &&
+               (tp->tp_fund == CHAR || tp->tp_fund == SHORT)
+       ) {
+               LoadLocal(df->df_address, int_size);
+               /* conversion(int_type, df->df_type); ???
+                  No, you can't do this on the stack! (CJ)
+               */
+               StoreLocal(df->df_address, tp->tp_size);
+       }
+}
+
+#ifdef LINT
+/*ARGSUSED*/
+#endif LINT
+code_expr(expr, val, code, tlbl, flbl)
+       struct expr *expr;
+       label tlbl, flbl;
+{
+       /*      code_expr() is the parser's interface to the expression code
+               generator.  If line number trace is wanted, it generates a
+               lin instruction.  EVAL() is called directly.
+       */
+#ifndef        LINT
+       if (! options['L'])     /* profiling    */
+               C_lin((arith)(expr->ex_line));
+
+       /*      HERE WE SHOULD GENERATE A MESSAGE:
+               if (expr->ex_flags & EX_VOLATILE)
+                       HANDS_OFF
+       */
+       EVAL(expr, val, code, tlbl, flbl);
+#else  LINT
+       lint_expr(expr, code ? USED : IGNORED);
+#endif LINT
+}
+
+/*     The FOR/WHILE/DO/SWITCH stacking mechanism:
+       stack_stmt() has to be called at the entrance of a
+       for, while, do or switch statement to indicate the
+       EM labels where a subsequent break or continue causes
+       the program to jump to.
+*/
+static struct stmt_block *stmt_stack;  /* top of statement stack */
+
+/*     code_break() generates EM code needed at the occurrence of "break":
+       it generates a branch instruction to the break label of the
+       innermost statement in which break has a meaning.
+       As "break" is legal in any of 'while', 'do', 'for' or 'switch',
+       which are the only ones that are stacked, only the top of
+       the stack is interesting.
+*/
+code_break()
+{
+       register struct stmt_block *stmt_block = stmt_stack;
+
+       if (stmt_block)
+               C_bra(stmt_block->st_break);
+       else
+               error("break not inside for, while, do or switch");
+}
+
+/*     code_continue() generates EM code needed at the occurrence of
+       "continue":
+       it generates a branch instruction to the continue label of the
+       innermost statement in which continue has a meaning.
+*/
+code_continue()
+{
+       register struct stmt_block *stmt_block = stmt_stack;
+
+       while (stmt_block)      {
+               if (stmt_block->st_continue)    {
+                       C_bra(stmt_block->st_continue);
+                       return;
+               }
+               stmt_block = stmt_block->next;
+       }
+       error("continue not inside for, while or do");
+}
+
+stack_stmt(break_label, cont_label)
+       label break_label, cont_label;
+{
+       register struct stmt_block *stmt_block = new_stmt_block();
+
+       stmt_block->next = stmt_stack;
+       stmt_block->st_break = break_label;
+       stmt_block->st_continue = cont_label;
+       stmt_stack = stmt_block;
+}
+
+unstack_stmt()
+{
+       /*      unstack_stmt() unstacks the data of a statement
+               which may contain break or continue
+       */
+       register struct stmt_block *sbp = stmt_stack;
+       stmt_stack = sbp->next;
+       free_stmt_block(sbp);
+}
+
+static label prc_name;
+
+prc_entry(name)
+       char *name;
+{
+       if (options['p']) {
+               C_df_dlb(prc_name = data_label());
+               C_rom_scon(name, (arith) (strlen(name) + 1));
+               C_lae_dlb(prc_name, (arith) 0);
+               C_cal("procentry");
+               C_asp(pointer_size);
+       }
+}
+
+prc_exit()
+{
+       if (options['p']) {
+               C_lae_dlb(prc_name, (arith) 0);
+               C_cal("procexit");
+               C_asp(pointer_size);
+       }
+}
diff --git a/lang/cem/cemcom.ansi/code.str b/lang/cem/cemcom.ansi/code.str
new file mode 100644 (file)
index 0000000..6fa088c
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     C O D E - G E N E R A T O R   D E F I N I T I O N S     */
+
+struct string_cst      {       /* storing string constants */
+       struct string_cst *next;
+       char *sc_value;
+       int sc_len;
+       label sc_dlb;
+};
+
+extern struct string_cst *str_list;
+
+/* ALLOCDEF "string_cst" 10 */
+
+#define        LVAL    0
+#define        RVAL    1
+#define        FALSE   0
+#define        TRUE    1
diff --git a/lang/cem/cemcom.ansi/conversion.c b/lang/cem/cemcom.ansi/conversion.c
new file mode 100644 (file)
index 0000000..536d887
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     C O N V E R S I O N - C O D E  G E N E R A T O R        */
+
+#include       "lint.h"
+#ifndef        LINT
+
+#include       "nofloat.h"
+#include       <em.h>
+#include       "arith.h"
+#include       "type.h"
+#include       "sizes.h"
+#include       "Lpars.h"
+
+#define        T_SIGNED                1
+#define        T_UNSIGNED              2
+#ifndef NOFLOAT
+#define        T_FLOATING              3
+#endif NOFLOAT
+
+/*     conversion() generates the EM code for a conversion between
+       the types char, short, int, long, float, double and pointer.
+       There are three conversion types: signed, unsigned and floating.
+       The EM code to obtain this conversion looks like:
+               LOC sizeof(from_type)
+               LOC sizeof(to_type)
+               C??
+*/
+
+static int convtype();
+
+conversion(from_type, to_type)
+       register struct type *from_type, *to_type;
+{
+       register arith from_size = from_type->tp_size;
+       register arith to_size = to_type->tp_size;
+       int from_cnvtype = convtype(from_type);
+       int to_cnvtype = convtype(to_type);
+
+       if ((int)to_size < (int)word_size) to_size = word_size;
+       if ((int)from_size == (int)to_size && from_cnvtype == to_cnvtype)
+               return;
+       switch (from_cnvtype)   {
+       case T_SIGNED:
+               switch (to_cnvtype)     {
+               case T_SIGNED:
+                       C_loc(from_size);
+                       C_loc(to_size);
+                       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);
+                               C_cii();
+                               from_size = word_size;
+                       }
+                       C_loc(from_size);
+                       C_loc(to_size);
+                       if (to_cnvtype == T_UNSIGNED) C_ciu();
+                       else C_cif();
+                       break;
+               }
+               break;
+       case T_UNSIGNED:
+               if ((int)from_size < (int)word_size) from_size = word_size;
+               C_loc(from_size);
+               C_loc(to_size);
+               switch (to_cnvtype)     {
+               case T_SIGNED:
+                       C_cui();
+                       break;
+               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);
+               switch (to_cnvtype)     {
+               case T_SIGNED:
+                       C_cfi();
+                       break;
+               case T_UNSIGNED:
+                       C_cfu();
+                       break;
+               case T_FLOATING:
+                       C_cff();
+                       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[];
+
+               if (to_cnvtype == T_SIGNED) {
+                       C_loc(to_type->tp_size);
+                       C_loc(word_size);
+                       C_cii();
+               }
+               else {
+                       C_loc((arith) full_mask[(int)(to_type->tp_size)]);
+                       C_and(word_size);
+               }
+       }
+}
+
+/*     convtype() returns in which category a given type falls:
+       signed, unsigned or floating
+*/
+static int
+convtype(tp)
+       register struct type *tp;
+{
+       switch (tp->tp_fund)    {
+       case GENERIC:
+       case CHAR:
+       case SHORT:
+       case INT:
+       case ERRONEOUS:
+       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;
+       }
+       return 0;
+}
+
+#endif LINT
+
diff --git a/lang/cem/cemcom.ansi/cstoper.c b/lang/cem/cemcom.ansi/cstoper.c
new file mode 100644 (file)
index 0000000..d613edb
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     C O N S T A N T   E X P R E S S I O N   H A N D L I N G         */
+
+#include       "target_sizes.h"
+#include       "idf.h"
+#include       "arith.h"
+#include       "type.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "sizes.h"
+#include       "Lpars.h"
+#include       "assert.h"
+
+long mach_long_sign;   /* sign bit of the machine long */
+int mach_long_size;    /* size of long on this machine == sizeof(long) */
+long full_mask[MAXSIZE];/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
+arith max_int;         /* maximum integer on target machine    */
+arith max_unsigned;    /* maximum unsigned on target machine   */
+
+cstbin(expp, oper, expr)
+       register struct expr **expp, *expr;
+{
+       /*      The operation oper is performed on the constant
+               expressions *expp(ld) and expr(ct), and the result restored in
+               *expp.
+       */
+       register arith o1 = (*expp)->VL_VALUE;
+       register arith o2 = expr->VL_VALUE;
+       int uns = (*expp)->ex_type->tp_unsigned;
+
+       ASSERT(is_ld_cst(*expp) && is_cp_cst(expr));
+       switch (oper)   {
+       case '*':
+               o1 *= o2;
+               break;
+       case '/':
+               if (o2 == 0)    {
+                       expr_error(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.
+                       */
+                       if (o2 & mach_long_sign)        {/* o2 > max_long */
+                               o1 = ! (o1 >= 0 || o1 < o2);
+                               /*      this is the unsigned test
+                                       o1 < o2 for o2 > max_long
+                               */
+                       }
+                       else    {               /* o2 <= max_long */
+                               long half, bit, hdiv, hrem, rem;
+
+                               half = (o1 >> 1) & ~mach_long_sign;
+                               bit = o1 & 01;
+                               /*      now o1 == 2 * half + bit
+                                       and half <= max_long
+                                       and bit <= max_long
+                               */
+                               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
+                               */
+                       }
+               }
+               else
+                       o1 /= o2;
+               break;
+       case '%':
+               if (o2 == 0)    {
+                       expr_error(expr, "modulo by 0");
+                       break;
+               }
+               if (uns)        {
+                       if (o2 & mach_long_sign)        {/* o2 > max_long */
+                               o1 = (o1 >= 0 || o1 < o2) ? o1 : o1 - o2;
+                               /*      this is the unsigned test
+                                       o1 < o2 for o2 > max_long
+                               */
+                       }
+                       else    {               /* o2 <= max_long */
+                               long half, bit, hrem, rem;
+
+                               half = (o1 >> 1) & ~mach_long_sign;
+                               bit = o1 & 01;
+                               /*      now o1 == 2 * half + bit
+                                       and half <= max_long
+                                       and bit <= max_long
+                               */
+                               hrem = half % o2;
+                               rem = 2 * hrem + bit;
+                               o1 = (rem < 0 || rem >= o2) ? rem - o2 : rem;
+                       }
+               }
+               else
+                       o1 %= o2;
+               break;
+       case '+':
+               o1 += o2;
+               break;
+       case '-':
+               o1 -= o2;
+               break;
+       case LEFT:
+               o1 <<= o2;
+               break;
+       case RIGHT:
+               if (o2 == 0)
+                       break;
+               if (uns)        {
+                       o1 >>= 1;
+                       o1 &= ~mach_long_sign;
+                       o1 >>= (o2-1);
+               }
+               else
+                       o1 >>= o2;
+               break;
+       case '<':
+               {
+                       arith tmp = o1;
+
+                       o1 = o2;
+                       o2 = tmp;
+               }
+               /* Fall through */
+       case '>':
+               if (uns)        {
+                       o1 = (o1 & mach_long_sign ?
+                               (o2 & mach_long_sign ? o1 > o2 : 1) :
+                               (o2 & mach_long_sign ? 0 : o1 > o2)
+                       );
+               }
+               else
+                       o1 = o1 > o2;
+               break;
+       case LESSEQ:
+               {
+                       arith tmp = o1;
+
+                       o1 = o2;
+                       o2 = tmp;
+               }
+               /* 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)
+                       );
+               }
+               else
+                       o1 = o1 >= o2;
+               break;
+       case EQUAL:
+               o1 = o1 == o2;
+               break;
+       case NOTEQUAL:
+               o1 = o1 != o2;
+               break;
+       case '&':
+               o1 &= o2;
+               break;
+       case '|':
+               o1 |= o2;
+               break;
+       case '^':
+               o1 ^= o2;
+               break;
+       }
+       (*expp)->VL_VALUE = o1;
+       cut_size(*expp);
+       (*expp)->ex_flags |= expr->ex_flags;
+       (*expp)->ex_flags &= ~EX_PARENS;
+       free_expression(expr);
+}
+
+cut_size(expr)
+       register struct expr *expr;
+{
+       /*      The constant value of the expression expr is made to
+               conform to the size of the type of the expression.
+       */
+       register arith o1 = expr->VL_VALUE;
+       int uns = expr->ex_type->tp_unsigned;
+       int size = (int) expr->ex_type->tp_size;
+
+       ASSERT(expr->ex_class == Value);
+       if (expr->ex_type->tp_fund == POINTER) {
+               /* why warn on "ptr-3" ?
+                  This quick hack fixes it
+               */
+               uns = 0;
+       }
+       if (uns) {
+               if (o1 & ~full_mask[size])
+                       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];
+
+               if (remainder != 0 && remainder != ~full_mask[size])
+                       expr_warning(expr, "overflow in constant expression");
+               o1 <<= nbits;           /* ??? */
+               o1 >>= nbits;
+       }
+       expr->VL_VALUE = o1;
+}
+
+init_cst()
+{
+       register int i = 0;
+       register arith bt = (arith)0;
+
+       while (!(bt < 0))       {
+               bt = (bt << 8) + 0377, i++;
+               if (i == MAXSIZE)
+                       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");
+       max_int = full_mask[(int)int_size] & ~(1L << ((int)int_size * 8 - 1));
+       max_unsigned = full_mask[(int)int_size];
+}
diff --git a/lang/cem/cemcom.ansi/dataflow.c b/lang/cem/cemcom.ansi/dataflow.c
new file mode 100644 (file)
index 0000000..0056121
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     DATAFLOW ANALYSIS ON C PROGRAMS */
+
+/*     Compile the C compiler with flag DATAFLOW.
+       Use the compiler option --d.
+*/
+
+#include       "dataflow.h"    /* UF */
+
+#ifdef DATAFLOW
+char *CurrentFunction = 0;
+int NumberOfCalls;
+
+DfaStartFunction(nm)
+       char *nm;
+{
+       CurrentFunction = nm;
+       NumberOfCalls = 0;
+}
+
+DfaEndFunction()
+{
+       if (NumberOfCalls == 0)
+               print("DFA: %s: --none--\n", CurrentFunction);
+}
+
+DfaCallFunction(s)
+       char *s;
+{
+       print("DFA: %s: %s\n", CurrentFunction, s);
+       ++NumberOfCalls;
+}
+#endif DATAFLOW
diff --git a/lang/cem/cemcom.ansi/declar.g b/lang/cem/cemcom.ansi/declar.g
new file mode 100644 (file)
index 0000000..9af9c95
--- /dev/null
@@ -0,0 +1,696 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     DECLARATION SYNTAX PARSER       */
+
+{
+#include       "lint.h"
+#include       <alloc.h>
+#include       "nobitfield.h"
+#include       "debug.h"
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "label.h"
+#include       "code.h"
+#include       "idf.h"
+#include       "type.h"
+#include       "proto.h"
+#include       "struct.h"
+#include       "field.h"
+#include       "decspecs.h"
+#include       "def.h"
+#include       "declar.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "sizes.h"
+#include       "level.h"
+#ifdef LINT
+#include       "l_lint.h"
+#include       "l_state.h"
+#endif LINT
+}
+
+/* 8 */
+declaration
+       {struct decspecs Ds;}
+:
+       {Ds = null_decspecs;}
+       decl_specifiers(&Ds)
+       init_declarator_list(&Ds)?
+       ';'
+;
+
+/*     A `decl_specifiers' describes a sequence of a storage_class_specifier,
+       an unsigned_specifier, a size_specifier and a simple type_specifier,
+       which may occur in arbitrary order and each of which may be absent;
+       at least one of them must be present, however, since the totally
+       empty case has already be dealt with in `external_definition'.
+       This means that something like:
+               unsigned extern int short xx;
+       is perfectly good 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).
+       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
+       occurrence of the type_specifier in the grammar (we have no choice),
+       collecting all data in a `struct decspecs' and turning that data
+       structure into what we want.
+       
+       The existence of declarations like
+               short typedef yepp;
+       makes all hope of writing a specific grammar for typedefs illusory.
+*/
+
+decl_specifiers        /* non-empty */ (register struct decspecs *ds;)
+       /*      Reads a non-empty decl_specifiers and fills the struct
+               decspecs *ds.
+       */
+:
+[
+       other_specifier(ds)+
+       [%if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
+               /* the thin ice in R.M. 11.1 */
+               single_type_specifier(ds) other_specifier(ds)*
+       |
+               empty
+       ]
+|
+       single_type_specifier(ds) other_specifier(ds)*
+]
+       {do_decspecs(ds);}
+;
+
+/* 8.1 */
+other_specifier(register struct decspecs *ds;)
+:
+       [ AUTO | STATIC | EXTERN | TYPEDEF | REGISTER ]
+       {       if (ds->ds_sc_given)
+                       error("repeated storage class specifier");
+               ds->ds_sc_given = 1;
+               ds->ds_sc = DOT;
+       }
+|
+       [ SHORT | LONG ]
+       {       if (ds->ds_size)
+                       error("repeated size specifier");
+               ds->ds_size = DOT;
+       }
+|
+       [ SIGNED | UNSIGNED ]
+       {       if (ds->ds_unsigned != 0)
+                       error("repeated sign specifier");
+               ds->ds_unsigned = DOT;
+       }
+|
+       /*      This qualifier applies to the top type.
+               E.g. const float * is a pointer to const float.
+       */
+       [ VOLATILE | CONST ]
+       {       if (DOT == VOLATILE) {
+                       if (ds->ds_typequal & TQ_VOLATILE)
+                               error("repeated type qualifier");
+                       ds->ds_typequal |= TQ_VOLATILE;
+               }
+               if (DOT == CONST) {
+                       if (ds->ds_typequal & TQ_CONST)
+                               error("repeated type qualifier");
+                       ds->ds_typequal |= TQ_CONST;
+               }
+       }
+;
+
+/* 8.2 */
+type_specifier(struct type **tpp;)
+       /*      Used in struct/union declarations and in casts; only the
+               type is relevant.
+       */
+       {struct decspecs Ds; Ds = null_decspecs;}
+:
+       decl_specifiers(&Ds)
+       {
+               if (Ds.ds_sc_given)
+                       error("storage class ignored");
+               if (Ds.ds_sc == REGISTER)
+                       error("register ignored");
+       }
+       {*tpp = Ds.ds_type;}
+;
+
+single_type_specifier(register struct decspecs *ds;):
+       %default TYPE_IDENTIFIER        /* this includes INT, CHAR, etc. */
+       {idf2type(dot.tk_idf, &ds->ds_type);}
+|
+       IDENTIFIER
+       {
+               error("%s is not a type identifier", dot.tk_idf->id_text);
+               ds->ds_type = error_type;
+               if (dot.tk_idf->id_def) {
+                       dot.tk_idf->id_def->df_type = error_type;
+                       dot.tk_idf->id_def->df_sc = TYPEDEF;
+               }
+       }
+|
+       struct_or_union_specifier(&ds->ds_type)
+|
+       enum_specifier(&ds->ds_type)
+;
+
+/* 8.3 */
+init_declarator_list(struct decspecs *ds;):
+       init_declarator(ds)
+       [ ',' init_declarator(ds) ]*
+;
+
+init_declarator(register struct decspecs *ds;)
+       {
+               struct declarator Dc;
+       }
+:
+       {
+               Dc = null_declarator;
+       }
+[
+       declarator(&Dc)
+       {
+               reject_params(&Dc);
+               declare_idf(ds, &Dc, level);
+#ifdef LINT
+               lint_declare_idf(Dc.dc_idf, ds->ds_sc);
+#endif LINT
+       }
+       [
+               initializer(Dc.dc_idf, ds->ds_sc)
+       |
+               { code_declaration(Dc.dc_idf, (struct expr *) 0, level, ds->ds_sc); }
+       ]
+]
+       {
+#ifdef LINT
+               add_auto(Dc.dc_idf);
+#endif LINT
+               remove_declarator(&Dc);
+       }
+;
+
+/* 8.6: initializer */
+initializer(struct idf *idf; int sc;)
+       {
+               struct expr *expr = (struct expr *) 0;
+               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;
+               }
+       }
+       '='
+       {
+#ifdef LINT
+               lint_statement();
+#endif LINT
+               if (globalflag) {
+                       struct expr ex;
+                       code_declaration(idf, &ex, level, sc);
+               }
+       }
+       initial_value(globalflag ? &(idf->id_def->df_type) : (struct type **)0,
+                       &expr)
+       {       if (! globalflag) {
+                       if (idf->id_def->df_type->tp_fund == FUNCTION)  {
+                               free_expression(expr);
+                               expr = 0;
+                       }
+#ifdef DEBUG
+                       print_expr("initializer-expression", expr);
+#endif DEBUG
+#ifdef LINT
+                       change_state(idf, SET);
+#endif LINT
+                       code_declaration(idf, expr, level, sc);
+               }
+               init_idf(idf);
+       }
+;
+
+/*
+       Functions yielding pointers to functions must be declared as, e.g.,
+               int (*hehe(par1, par2))() char *par1, *par2;    {}
+       Since the function heading is read as a normal declarator,
+       we just include the (formal) parameter list in the declarator
+       description list dc.
+*/
+declarator(register struct declarator *dc;)
+       {       struct formal *fm = NO_PARAMS;
+               struct proto *pl = NO_PROTO;
+               arith count;
+               int qual;
+       }
+:
+       primary_declarator(dc)
+       [/*%while(1)*/
+               '('
+               [ %if (DOT != IDENTIFIER && DOT != ')')
+                       parameter_type_list(&pl)
+               |
+                       formal_list(&fm)
+               |
+                       empty
+               ]
+               ')'
+               {       add_decl_unary(dc, FUNCTION, 0, (arith)0, fm, pl);
+                       fm = NO_PARAMS;
+               }
+       |
+               arrayer(&count)
+               {add_decl_unary(dc, ARRAY, 0, count, NO_PARAMS, NO_PROTO);}
+       ]*
+|
+       pointer(&qual) declarator(dc)
+       {add_decl_unary(dc, POINTER, qual, (arith)0, NO_PARAMS, NO_PROTO);}
+;
+
+primary_declarator(register struct declarator *dc;) :
+       identifier(&dc->dc_idf)
+|
+       '(' declarator(dc) ')'
+;
+
+arrayer(arith *sizep;)
+       { struct expr *expr; }
+:
+       '['
+               [
+                       constant_expression(&expr)
+                       {
+                               check_array_subscript(expr);
+                               *sizep = expr->VL_VALUE;
+                               free_expression(expr);
+                       }
+               |
+                       empty
+                       { *sizep = (arith)-1; }
+               ]
+       ']'
+;
+
+formal_list (struct formal **fmp;)
+:
+       formal(fmp) [ ',' formal(fmp) ]*
+;
+
+formal(struct formal **fmp;)
+       {struct idf *idf;       }
+:
+       identifier(&idf)
+       {
+               register struct formal *new = new_formal();
+               
+               new->fm_idf = idf;
+               new->next = *fmp;
+               *fmp = new;
+       }
+;
+
+/* Change 2 */
+enum_specifier(register struct type **tpp;)
+       {
+               struct idf *idf;
+               arith l = (arith)0;
+       }
+:
+       ENUM
+       [
+               {declare_struct(ENUM, (struct idf *) 0, tpp);}
+               enumerator_pack(*tpp, &l)
+       |
+               identifier(&idf)
+               [
+                       {declare_struct(ENUM, idf, tpp);}
+                       enumerator_pack(*tpp, &l)
+               |
+                       {apply_struct(ENUM, idf, tpp);}
+                       empty
+               ]
+       ]
+;
+
+enumerator_pack(register struct type *tp; arith *lp;) :
+       '{'
+       enumerator(tp, lp)
+       [%while (AHEAD != '}')
+               ','
+               enumerator(tp, lp)
+       ]*
+       [
+               ','     {warning("unexpected trailing comma in enumerator pack");}
+       ]?
+       '}'
+       {tp->tp_size = int_size;}
+       /*      fancy implementations that put small enums in 1 byte
+               or so should start here.
+       */
+;
+
+enumerator(struct type *tp; arith *lp;)
+       {
+               struct idf *idf;
+               struct expr *expr;
+       }
+:
+       identifier(&idf)
+       [
+               '='
+               constant_expression(&expr)
+               {
+                       *lp = expr->VL_VALUE;
+                       free_expression(expr);
+               }
+       ]?
+       {declare_enum(tp, idf, (*lp)++);}
+;
+
+/* 8.5 */
+struct_or_union_specifier(register struct type **tpp;)
+       {
+               int fund;
+               struct idf *idfX;
+               register struct idf *idf;
+       }
+:
+       [ STRUCT | UNION ]
+       {fund = DOT;}
+       [
+               {
+                       declare_struct(fund, (struct idf *)0, tpp);
+               }
+               struct_declaration_pack(*tpp)
+       |
+               identifier(&idfX)       { idf = idfX; }
+               [
+                       {
+                               declare_struct(fund, idf, tpp);
+                               (idf->id_struct->tg_busy)++;
+                       }
+                       struct_declaration_pack(*tpp)
+                       {
+                               (idf->id_struct->tg_busy)--;
+                       }
+               |
+                       {apply_struct(fund, idf, tpp);}
+                       empty
+               ]
+       ]
+;
+
+struct_declaration_pack(register struct type *stp;)
+       {
+               struct sdef **sdefp = &stp->tp_sdef;
+               arith size = (arith)0;
+       }
+:
+       /*      The size is only filled in after the whole struct has
+               been read, to prevent recursive definitions.
+       */
+       '{'
+       struct_declaration(stp, &sdefp, &size)+
+       '}'
+       {stp->tp_size = align(size, stp->tp_align);}
+;
+
+struct_declaration(struct type *stp; struct sdef ***sdefpp; arith *szp;)
+       {struct type *tp;}
+:
+       type_specifier(&tp) struct_declarator_list(tp, stp, sdefpp, szp) ';'
+;
+
+struct_declarator_list(struct type *tp, *stp;
+                       struct sdef ***sdefpp; arith *szp;)
+:
+       struct_declarator(tp, stp, sdefpp, szp)
+       [ ',' struct_declarator(tp, stp, sdefpp, szp) ]*
+;
+
+struct_declarator(struct type *tp; struct type *stp;
+                       struct sdef ***sdefpp; arith *szp;)
+       {
+               struct declarator Dc;
+               struct field *fd = 0;
+       }
+:
+       {
+               Dc = null_declarator;
+       }
+[
+       declarator(&Dc)
+       {reject_params(&Dc);}
+       bit_expression(&fd)?
+|
+       {Dc.dc_idf = gen_idf();}
+       bit_expression(&fd)
+]
+       {add_sel(stp, declare_type(tp, &Dc), Dc.dc_idf, sdefpp, szp, fd);}
+       {remove_declarator(&Dc);}
+;
+
+bit_expression(struct field **fd;)
+       { struct expr *expr; }
+:
+       {
+               *fd = new_field();
+       }
+       ':'
+       constant_expression(&expr)
+       {
+               (*fd)->fd_width = expr->VL_VALUE;
+               free_expression(expr);
+#ifdef NOBITFIELD
+               error("bitfields are not implemented");
+#endif NOBITFIELD
+       }
+;
+
+/* 8.7 */
+cast(struct type **tpp;)
+       {struct declarator Dc;}
+:
+       {Dc = null_declarator;}
+       '('
+       type_specifier(tpp)
+       abstract_declarator(&Dc)
+       ')'
+       {*tpp = declare_type(*tpp, &Dc);}
+       {remove_declarator(&Dc);}
+;
+
+/*     This code is an abject copy of that of 'declarator', for lack of
+       a two-level grammar.
+*/
+abstract_declarator(register struct declarator *dc;)
+       {       struct proto *pl = NO_PROTO;
+               arith count;
+               int qual;
+       }
+:
+       primary_abstract_declarator(dc)
+       [
+               '('
+               [
+                       parameter_type_list(&pl)
+               |
+                       empty
+               ]
+               ')'
+               {add_decl_unary(dc, FUNCTION, 0, (arith)0, NO_PARAMS, pl);}
+       |
+               arrayer(&count)
+               {add_decl_unary(dc, ARRAY, 0, count, NO_PARAMS, NO_PROTO);}
+       ]*
+|
+       pointer(&qual) abstract_declarator(dc)
+       {add_decl_unary(dc, POINTER, qual, (arith)0, NO_PARAMS, NO_PROTO);}
+;
+
+primary_abstract_declarator(struct declarator *dc;)
+:
+[%if (AHEAD == ')')
+       empty
+|
+       '(' abstract_declarator(dc) ')'
+]
+;
+
+parameter_type_list(struct proto **plp;)
+       {       int save_level; }
+:
+       {       if (level > L_PROTO) {
+                       save_level = level;
+                       level = L_PROTO;
+               } else level--;
+       }
+       parameter_decl_list(plp)
+       [
+               ',' ELLIPSIS
+               {       register struct proto *new = new_proto();
+
+                       new->next = *plp;
+                       new->pl_flag = ELLIPSIS;
+                       *plp = new;
+               }
+
+       ]?
+       {       if (level == L_PROTO)
+                       level = save_level;
+               else level++;
+       }
+;
+
+parameter_decl_list(struct proto **plp;)
+:
+       parameter_decl(plp)
+       [ %while (AHEAD != ELLIPSIS)
+               ',' parameter_decl(plp)
+       ]*
+;
+
+parameter_decl(struct proto **plp;)
+       {       register struct proto *new = new_proto();
+               struct declarator Dc;
+               struct decspecs Ds;
+       }
+:
+       {       Dc = null_declarator;
+               Ds = null_decspecs;
+       }
+       decl_specifiers(&Ds)
+       parameter_declarator(&Dc)
+       {       add_proto(new, &Ds, &Dc, level);
+               new->next = *plp;
+               *plp = new;
+       }
+;
+
+/*     This is weird. Due to the LR structure of the ANSI C grammar
+       we have to duplicate the actions of 'declarator' and
+       'abstract_declarator'. Calling these separate, as in
+
+       parameter_decl:
+               decl_specifiers
+               [
+                       declarator
+               |
+                       abstract_declarator
+               ]
+
+
+       gives us a conflict on the terminals '(' and '*'. E.i. on
+       some input, it is impossible to decide which rule we take.
+       Combining the two declarators into one common declarator
+       is out of the question, since this results in an empty
+       string for the non-terminal 'declarator'.
+       So we combine the two only for the use of parameter_decl,
+       since this is the only place where they don't give
+       conflicts. However, this makes the grammar messy.
+*/
+parameter_declarator(register struct declarator *dc;)
+       {       struct formal *fm = NO_PARAMS;
+               struct proto *pl = NO_PROTO;
+               arith count;
+               int qual;
+       }
+:
+       primary_parameter_declarator(dc)
+       [
+               '('
+               [ %if(DOT != IDENTIFIER && DOT != ')')
+                       parameter_type_list(&pl)
+               |
+                       formal_list(&fm)
+               |
+                       empty
+               ]
+               ')'
+               {add_decl_unary(dc, FUNCTION, 0, (arith)0, fm, pl);}
+       |
+               arrayer(&count)
+               {add_decl_unary(dc, ARRAY, 0, count, NO_PARAMS, NO_PROTO);}
+       ]*
+|
+       pointer(&qual) parameter_declarator(dc)
+       {add_decl_unary(dc, POINTER, qual, (arith)0, NO_PARAMS, NO_PROTO);}
+;
+
+primary_parameter_declarator(register struct declarator *dc;)
+:
+[ %if(AHEAD == ')')
+       empty
+|
+       identifier(&dc->dc_idf)
+|
+       '(' parameter_declarator(dc) ')'
+]
+;
+
+pointer(int *qual;)
+:
+       '*' type_qualifier_list(qual)
+;
+
+
+/*     Type qualifiers may come in three flavours:
+       volatile, const, const volatile.
+       These all have different semantic properties:
+
+       volatile:
+               means that the object can be modified
+               without prior knowledge of the implementation.
+
+       const:
+               means that the object can not be modified; thus
+               it's illegal to use this as a l-value.
+
+       const volatile:
+               means  that the object can be modified without
+               prior knowledge of the implementation, but may
+               not be used as a l-value.
+*/
+type_qualifier_list(int *qual;)
+:
+[
+       [ VOLATILE | CONST ]
+       { *qual = (DOT == VOLATILE) ? TQ_VOLATILE : TQ_CONST; }
+
+       [
+               [ VOLATILE | CONST ]
+               {       if (DOT == VOLATILE) {
+                               if (*qual & TQ_VOLATILE)
+                                       error("repeated type qualifier");
+                               *qual |= TQ_VOLATILE;
+                       }
+                       if (DOT == CONST) {
+                               if (*qual & TQ_CONST)
+                                       error("repeated type qualifier");
+                               *qual |= TQ_CONST;
+                       }
+               }
+                                       
+       ]*
+|
+       empty
+       { *qual = 0; }
+]
+;
+
+
+empty:
+;
+
+/* 8.8 */
+/* included in the IDENTIFIER/TYPE_IDENTIFIER mechanism */
diff --git a/lang/cem/cemcom.ansi/declar.str b/lang/cem/cemcom.ansi/declar.str
new file mode 100644 (file)
index 0000000..640fc3a
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* DEFINITION OF DECLARATOR DESCRIPTORS */
+
+/*     A 'declarator' consists of an idf and a linked list of
+       language-defined unary operations: *, [] and (), called
+       decl_unary's.
+*/
+
+struct declarator      {
+       struct declarator *next;
+       struct idf *dc_idf;
+       struct decl_unary *dc_decl_unary;
+       struct formal *dc_formal;       /* params for function  */
+};
+
+/* ALLOCDEF "declarator" 50 */
+
+
+struct formal  {                       /* list of formals */
+       struct formal *next;
+       struct idf *fm_idf;
+};
+
+/* ALLOCDEF "formal" 5 */
+
+
+#define        NO_PARAMS ((struct formal *) 0)
+
+struct decl_unary      {
+       struct decl_unary *next;
+       int du_fund;                    /* POINTER, ARRAY or FUNCTION   */
+       int du_typequal;                /* CONST, VOLATILE, or 0 */
+       arith du_count;                 /* for ARRAYs only      */
+       struct proto *du_proto;         /* params for function or prototype */
+};
+
+/* ALLOCDEF "decl_unary" 10 */
+
+extern struct type *declare_type();
+extern struct declarator null_declarator;
diff --git a/lang/cem/cemcom.ansi/declarator.c b/lang/cem/cemcom.ansi/declarator.c
new file mode 100644 (file)
index 0000000..d899235
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     D E C L A R A T O R   M A N I P U L A T I O N           */
+
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "arith.h"
+#include       "type.h"
+#include       "proto.h"
+#include       "Lpars.h"
+#include       "declar.h"
+#include       "def.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "sizes.h"
+#include       "debug.h"
+#include       "level.h"
+
+extern char options[];
+struct declarator null_declarator;
+
+struct type *
+declare_type(tp, dc)
+       struct type *tp;
+       struct declarator *dc;
+{
+       /*      Applies the decl_unary list starting at dc->dc_decl_unary
+               to the type tp and returns the result.
+               Functions that are declared within a parameter type list
+               are purely prototypes. Simply add the type list to the
+               function node.
+       */
+       register struct decl_unary *du = dc->dc_decl_unary;
+
+       while (du)      {
+               tp = construct_type(du->du_fund, tp, du->du_typequal,
+                                   du->du_count, du->du_proto);
+               du = du->next;
+       }
+       return tp;
+}
+
+add_decl_unary(dc, fund, qual,  count, fm, pl)
+       register struct declarator *dc;
+       int qual;
+       arith count;
+       struct formal *fm;
+       struct proto *pl;
+{
+       /*      A decl_unary describing a constructor with fundamental
+               type fund and with size count is inserted in front of the
+               declarator dc.
+       */
+       register struct decl_unary *new = new_decl_unary();
+
+       new->next = dc->dc_decl_unary;
+       new->du_fund = fund;
+       new->du_count = count;
+       new->du_typequal = qual;
+       new->du_proto = pl;
+       if (fm) {
+               if (dc->dc_decl_unary)  {
+                       /* parameters only allowed at first decl_unary  */
+                       error("formal parameters list discarded");
+               }
+               else    {
+                       /* register the proto   */
+                       dc->dc_formal = fm;
+               }
+       }
+
+       dc->dc_decl_unary = new;
+}
+
+remove_declarator(dc)
+       struct declarator *dc;
+{
+       /*      The decl_unary list starting at dc->dc_decl_unary is
+               removed.
+       */
+       register struct decl_unary *du = dc->dc_decl_unary;
+
+       while (du)      {
+               struct decl_unary *old_du = du;
+
+               du = du->next;
+               free_decl_unary(old_du);
+       }
+}
+
+reject_params(dc)
+       register struct declarator *dc;
+{
+       /*      The declarator is checked to have no parameters, if it
+               is a function.
+       */
+       if (dc->dc_formal)      {
+               error("non_empty formal parameter pack");
+               free_formals(dc->dc_formal);
+               dc->dc_formal = 0;
+       }
+}
+
+check_array_subscript(expr)
+       register struct expr *expr;
+{
+       arith size = expr->VL_VALUE;
+
+       if (size < 0)   {
+               error("array size is negative");
+               expr->VL_VALUE = (arith)1;
+       }
+       else
+       if (size == 0) {
+               warning("array size is 0");
+       }
+       else
+       if (size & ~max_unsigned) {     /* absolutely ridiculous */
+               expr_error(expr, "overflow in array size");
+               expr->VL_VALUE = (arith)1;
+       }
+}
diff --git a/lang/cem/cemcom.ansi/decspecs.c b/lang/cem/cemcom.ansi/decspecs.c
new file mode 100644 (file)
index 0000000..c01b661
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     D E C L A R A T I O N   S P E C I F I E R   C H E C K I N G     */
+
+#include       "nofloat.h"
+#include       "assert.h"
+#include       "Lpars.h"
+#include       "decspecs.h"
+#include       "arith.h"
+#include       "type.h"
+#include       "level.h"
+#include       "def.h"
+#include       "noRoption.h"
+
+extern char options[];
+extern int level;
+extern char *symbol2str();
+extern char *type2str();
+extern char *qual2str();
+extern struct type *qualifier_type();
+
+struct decspecs null_decspecs;
+
+do_decspecs(ds)
+       register struct decspecs *ds;
+{
+       /*      The provisional decspecs ds as obtained from the program
+               is turned into a legal consistent decspecs.
+       */
+       register struct type *tp = ds->ds_type;
+       
+       ASSERT(level != L_FORMAL1);
+       
+       /*
+       if (ds->ds_notypegiven && !ds->ds_sc_given)
+               strict("data definition lacking type or storage class");
+       */
+
+       if (    level == L_GLOBAL &&
+               (ds->ds_sc == AUTO || ds->ds_sc == REGISTER)
+       )       {
+               warning("no global %s variable allowed",
+                       symbol2str(ds->ds_sc));
+               ds->ds_sc = GLOBAL;
+       }
+
+       if (level == L_FORMAL2) {
+               if (ds->ds_sc_given &&
+                   ds->ds_sc != REGISTER){
+                       error("%s formal illegal", symbol2str(ds->ds_sc));
+                       ds->ds_sc = FORMAL;
+               }
+       }
+
+       /*      Since type qualifiers may be associated with types by means
+               of typedefs, we have to perform same basic tests down here.
+       */
+       if (tp != (struct type *)0) {
+               if ((ds->ds_typequal & TQ_VOLATILE) && (tp->tp_typequal & TQ_VOLATILE))
+                       error("indirect repeated type qualifier");
+               if ((ds->ds_typequal & TQ_CONST) && (tp->tp_typequal & TQ_CONST))
+                       error("indirect repeated type qualifier");
+               ds->ds_typequal |= tp->tp_typequal;
+       }
+
+       /*      The tests concerning types require a full knowledge of the
+               type and will have to be postponed to declare_idf.
+       */
+
+       /* some adjustments as described in RM 8.2 */
+       if (tp == 0) {
+               ds->ds_notypegiven = 1;
+               tp = int_type;
+       }
+       switch (ds->ds_size)    {
+       case SHORT:
+               if (tp == int_type)
+                       tp = short_type;
+               else
+                       error("short with illegal type");
+               break;
+       case LONG:
+               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:
+                       error("unsigned with illegal type");
+                       break;
+               }
+       }
+       if (ds->ds_unsigned == SIGNED) {
+               switch (tp->tp_fund) {
+               case CHAR:
+                       tp = char_type;
+                       break;
+               case SHORT:
+                       tp = short_type;
+                       break;
+               case INT:
+                       tp = int_type;
+                       break;
+               case LONG:
+                       tp = long_type;
+                       break;
+               default:
+                       error("signed with illegal type");
+                       break;
+               }
+       }
+
+       ds->ds_type = qualifier_type(tp, ds->ds_typequal);
+}
+
+/*     Make tp into a qualified type. This is not as trivial as it
+       may seem. If tp is a fundamental type the qualified type is
+       either existent or will be generated.
+       In case of a complex type the top of the type list will be
+       replaced by a qualified version.
+*/
+struct type *
+qualifier_type(tp, typequal)
+       register struct type *tp;
+       int typequal;
+{
+       register struct type *dtp = tp;
+       register int fund = tp->tp_fund;
+
+       while (dtp && dtp->tp_typequal != typequal)
+               dtp = dtp->next;
+
+       if (!dtp) {
+               dtp = create_type(fund);
+               dtp->tp_unsigned = tp->tp_unsigned;
+               dtp->tp_align = tp->tp_align;
+               dtp->tp_typequal = typequal;
+               dtp->tp_size = tp->tp_size;
+               switch (fund) {
+               case POINTER:
+               case ARRAY:
+               case FUNCTION:
+               case STRUCT:
+               case UNION:
+               case ENUM:
+                       dtp->tp_idf = tp->tp_idf;
+                       dtp->tp_sdef = tp->tp_sdef;
+                       dtp->tp_up = tp->tp_up;
+                       dtp->tp_field = tp->tp_field;
+                       dtp->tp_pointer = tp->tp_pointer;
+                       dtp->tp_array = tp->tp_array;
+                       dtp->tp_function = tp->tp_function;
+                       break;
+               default:
+                       break;
+               }
+               dtp->next = tp->next; /* don't know head or tail */
+               tp->next = dtp;
+       }
+       return(dtp);
+}
+
diff --git a/lang/cem/cemcom.ansi/decspecs.str b/lang/cem/cemcom.ansi/decspecs.str
new file mode 100644 (file)
index 0000000..59bc24f
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* DECLARATION SPECIFIER DEFINITION */
+
+struct decspecs        {
+       struct decspecs *next;
+       struct type *ds_type;   /* single type */
+       int ds_notypegiven;     /* set if type not given explicitly */
+       int ds_sc_given;        /* 1 if the st. class is explicitly given */
+       int ds_sc;              /* storage class, given or implied */
+       int ds_size;            /* LONG, SHORT or 0 */
+       int ds_unsigned;        /* SIGNED, UNSIGNED or 0 */
+       int ds_typequal;        /* type qualifiers - see type.str */
+};
+
+extern struct type *qualifier_type();
+extern struct decspecs null_decspecs;
diff --git a/lang/cem/cemcom.ansi/def.str b/lang/cem/cemcom.ansi/def.str
new file mode 100644 (file)
index 0000000..8d719f2
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* IDENTIFIER DEFINITION DESCRIPTOR */
+
+#include       "lint.h"
+
+struct def     {               /* for ordinary tags */
+       struct def *next;
+       int df_level;
+       struct type *df_type;
+       int df_sc;              /*      may be:
+                                       GLOBAL, STATIC, EXTERN, IMPLICIT,
+                                       TYPEDEF,
+                                       FORMAL, AUTO,
+                                       ENUM, LABEL
+                               */
+       char df_initialized;    /* an initialization has been generated */
+       char df_alloc;          /* 0, ALLOC_SEEN or ALLOC_DONE */
+       char df_used;           /* set if idf is used */
+       char *df_file;          /* file containing the definition */
+       unsigned int df_line;   /* line number of the definition */
+#ifdef LINT
+       char df_set;
+       int df_firstbrace;      /* brace number of its first occurrence */
+       int df_minlevel;        /* the lowest level needed for this def */
+#endif LINT
+       char df_formal_array;   /* to warn if sizeof is taken */
+       arith df_address;
+};
+
+#define        ALLOC_SEEN      1       /* an allocating declaration has been seen */
+#define        ALLOC_DONE      2       /* the allocating declaration has been done */
+
+#define REG_DEFAULT    0       /* register candidate, not declared as such */
+#define REG_BONUS      10      /* register candidate, declared as such */
+
+/* ALLOCDEF "def" 50 */
diff --git a/lang/cem/cemcom.ansi/domacro.c b/lang/cem/cemcom.ansi/domacro.c
new file mode 100644 (file)
index 0000000..33be293
--- /dev/null
@@ -0,0 +1,688 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* PREPROCESSOR: CONTROLLINE INTERPRETER */
+
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "debug.h"
+#include       "idf.h"
+#include       "input.h"
+#include       "nopp.h"
+
+#ifndef NOPP
+#include       "ifdepth.h"     
+#include       "botch_free.h"  
+#include       "nparams.h"     
+#include       "parbufsize.h"  
+#include       "textsize.h"    
+#include       "idfsize.h"     
+#include       "assert.h"
+#include       <alloc.h>
+#include       "class.h"
+#include       "macro.h"
+
+extern char **inctable;        /* list of include directories          */
+extern char *getwdir();
+char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
+                               /* 1 if a corresponding ELSE has been   */
+                               /* encountered.                         */
+
+int    nestlevel = -1;
+
+struct idf *
+GetIdentifier()
+{
+       /*      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.
+               The substitution of macros is disabled.
+       */
+       int tok;
+       struct token tk;
+
+       ReplaceMacros = 0;
+       tok = GetToken(&tk);
+       ReplaceMacros = 1;
+       return tok == IDENTIFIER ? tk.tk_idf : (struct idf *)0;
+}
+
+/*     domacro() is the control line interpreter. The '#' has already
+       been read by the lexical analyzer by which domacro() is called.
+       The token appearing directly after the '#' is obtained by calling
+       the basic lexical analyzing function GetToken() and is interpreted
+       to perform the action belonging to that token.
+       An error message is produced when the token is not recognized,
+       i.e. it is not one of "define" .. "undef" , integer or newline.
+*/
+domacro()
+{
+       struct token tk;        /* the token itself                     */
+
+       EoiForNewline = 1;
+       switch(GetToken(&tk)) {         /* select control line action   */
+       case IDENTIFIER:                /* is it a macro keyword?       */
+               switch (tk.tk_idf->id_resmac) {
+               case K_DEFINE:                          /* "define"     */
+                       do_define();
+                       break;
+               case K_ELIF:                            /* "elif"       */
+                       do_elif();
+                       break;
+               case K_ELSE:                            /* "else"       */
+                       do_else();
+                       break;
+               case K_ENDIF:                           /* "endif"      */
+                       do_endif();
+                       break;
+               case K_IF:                              /* "if"         */
+                       do_if();
+                       break;
+               case K_IFDEF:                           /* "ifdef"      */
+                       do_ifdef(1);
+                       break;
+               case K_IFNDEF:                          /* "ifndef"     */
+                       do_ifdef(0);
+                       break;
+               case K_INCLUDE:                         /* "include"    */
+                       do_include();
+                       break;
+               case K_LINE:                            /* "line"       */
+                       /*      set LineNumber and FileName according to
+                               the arguments.
+                       */
+                       if (GetToken(&tk) != INTEGER) {
+                               lexerror("#line without linenumber");
+                               SkipToNewLine(0);
+                       }
+                       else
+                               do_line((unsigned int)tk.tk_ival);
+                       break;
+               case K_ERROR:                           /* "error"      */
+                       do_error();
+                       break;
+               case K_PRAGMA:                          /* "pragma"     */
+                       do_pragma();
+                       break;
+               case K_UNDEF:                           /* "undef"      */
+                       do_undef();
+                       break;
+               default:
+                       /* invalid word seen after the '#'      */
+                       lexerror("%s: unknown control", tk.tk_idf->id_text);
+                       SkipToNewLine(0);
+               }
+               break;
+       case INTEGER:           /* # <integer> [<filespecifier>]?       */
+               do_line((unsigned int)tk.tk_ival);
+               break;
+       case EOI:       /* only `#' on this line: do nothing, ignore    */
+               break;
+       default:        /* invalid token following '#'          */
+               lexerror("illegal # line");
+               SkipToNewLine(0);
+       }
+       EoiForNewline = 0;
+}
+
+
+skip_block()
+{
+       /*      skip_block() skips the input from
+               1)      a false #if, #ifdef, #ifndef or #elif until the
+                       corresponding #elif (resulting in true), #else or
+                       #endif is read.
+               2)      a #else corresponding to a true #if, #ifdef,
+                       #ifndef or #elif until the corresponding #endif is
+                       seen.
+       */
+       register int ch;
+       register int skiplevel = nestlevel; /* current nesting level    */
+       struct token tk;
+
+       NoUnstack++;
+       for (;;) {
+               ch = GetChar(); /* read first character after newline   */
+               while (class(ch) == STSKIP)
+                       ch = GetChar();
+               if (ch != '#') {
+                       if (ch == EOI) {
+                               NoUnstack--;
+                               return;
+                       }
+                       SkipToNewLine(0);
+                       continue;
+               }
+               if (GetToken(&tk) != IDENTIFIER) {
+                       SkipToNewLine(0);
+                       continue;
+               }
+               /*      an IDENTIFIER: look for #if, #ifdef and #ifndef
+                       without interpreting them.
+                       Interpret #else, #elif and #endif if they occur
+                       on the same level.
+               */
+               switch(tk.tk_idf->id_resmac) {
+               case K_IF:
+               case K_IFDEF:
+               case K_IFNDEF:
+                       push_if();
+                       break;
+               case K_ELIF:
+                       if (nestlevel == skiplevel) {
+                               nestlevel--;
+                               push_if();
+                               if (ifexpr()) {
+                                       NoUnstack--;
+                                       return;
+                               }
+                       }
+                       break;
+               case K_ELSE:
+                       ++(ifstack[nestlevel]);
+                       if (nestlevel == skiplevel) {
+                               if (SkipToNewLine(1))
+                                       strict("garbage following #endif");
+                               NoUnstack--;
+                               return;
+                       }
+                       break;
+               case K_ENDIF:
+                       ASSERT(nestlevel > nestlow);
+                       if (nestlevel == skiplevel) {
+                               if (SkipToNewLine(1))
+                                       strict("garbage following #endif");
+                               nestlevel--;
+                               NoUnstack--;
+                               return;
+                       }
+                       nestlevel--;
+                       break;
+               }
+       }
+}
+
+
+ifexpr()
+{
+       /*      ifexpr() returns whether the restricted constant
+               expression following #if or #elif evaluates to true.  This
+               is done by calling the LLgen generated subparser for
+               constant expressions.  The result of this expression will
+               be given in the extern long variable "ifval".
+       */
+       extern arith ifval;
+       int errors = err_occurred;
+
+       ifval = (arith)0;
+       AccDefined = 1;
+       UnknownIdIsZero = 1;
+       PushLex();      /* NEW parser */
+       If_expr();      /* invoke constant expression parser    */
+       PopLex();       /* OLD parser */
+       AccDefined = 0;
+       UnknownIdIsZero = 0;
+       return (errors == err_occurred) && (ifval != (arith)0);
+}
+
+do_include()
+{
+       /*      do_include() performs the inclusion of a file.
+       */
+       char *filenm;
+       char *result;
+       int tok;
+       struct token tk;
+
+       AccFileSpecifier = 1;
+       if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
+               filenm = tk.tk_bts;
+       else {
+               lexerror("bad include syntax");
+               filenm = (char *)0;
+       }
+       AccFileSpecifier = 0;
+       SkipToNewLine(0);
+       inctable[0] = WorkingDir;
+       if (filenm) {
+               if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
+                       fatal("cannot open include file \"%s\"", filenm);
+               }
+               else {
+                       WorkingDir = getwdir(result);
+                       File_Inserted = 1;
+                       FileName = result;
+                       LineNumber = 0;
+                       nestlow = nestlevel;
+               }
+       }
+}
+
+do_define()
+{
+       /*      do_define() interprets a #define control line.
+       */
+       struct idf *id;         /* the #defined identifier's descriptor */
+       int nformals = -1;      /* keep track of the number of formals  */
+       char *formals[NPARAMS]; /* pointers to the names of the formals */
+       char parbuf[PARBUFSIZE];                /* names of formals     */
+       char *repl_text;        /* start of the replacement text        */
+       int length;             /* length of the replacement text       */
+       register ch;
+       char *get_text();
+
+       /* read the #defined macro's name       */
+       if (!(id = GetIdentifier())) {
+               lexerror("#define: illegal macro name");
+               SkipToNewLine(0);
+               return;
+       }
+       /*      there is a formal parameter list if the identifier is
+               followed immediately by a '('. 
+       */
+       ch = GetChar();
+       if (ch == '(') {
+               if ((nformals = getparams(formals, parbuf)) == -1) {
+                       SkipToNewLine(0);
+                       return; /* an error occurred    */
+               }
+               ch = GetChar();
+       }
+       /* read the replacement text if there is any                    */
+       ch = skipspaces(ch,0);  /* find first character of the text     */
+       ASSERT(ch != EOI);
+       if (class(ch) == STNL) {
+               /*      Treat `#define something' as `#define something ""'
+               */
+               repl_text = "";
+               length = 0;
+       }
+       else {
+               UnGetChar();
+               repl_text = get_text((nformals > 0) ? formals : 0, &length);
+       }
+       macro_def(id, repl_text, nformals, length, NOFLAG);
+       LineNumber++;
+}
+
+push_if()
+{
+       if (nestlevel >= IFDEPTH)
+               fatal("too many nested #if/#ifdef/#ifndef");
+       else
+               ifstack[++nestlevel] = 0;
+}
+
+do_elif()
+{
+       if (nestlevel <= nestlow || (ifstack[nestlevel])) {
+               lexerror("#elif without corresponding #if");
+               SkipToNewLine(0);
+       }
+       else { /* restart at this level as if a #if is detected.  */
+               nestlevel--;
+               push_if();
+               skip_block();
+       }
+}
+
+do_else()
+{
+       struct token tok;
+
+       if (SkipToNewLine(1))
+               strict("garbage following #else");
+       if (nestlevel <= nestlow || (ifstack[nestlevel]))
+               lexerror("#else without corresponding #if");
+       else {  /* mark this level as else-d */
+               ++(ifstack[nestlevel]);
+               skip_block();
+       }
+}
+
+do_endif()
+{
+       struct token tok;
+
+       if (SkipToNewLine(1))
+               strict("garbage following #endif");
+       if (nestlevel <= nestlow)       {
+               lexerror("#endif without corresponding #if");
+       }
+       else    nestlevel--;
+}
+
+do_if()
+{
+       push_if();
+       if (!ifexpr())  /* a false #if/#elif expression */
+               skip_block();
+}
+
+do_ifdef(how)
+{
+       register struct idf *id;
+
+       /*      how == 1 : ifdef; how == 0 : ifndef
+       */
+       push_if();
+       if (!(id = GetIdentifier()))
+               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
+               SkipToNewLine(0);
+}
+
+do_undef()
+{
+       register struct idf *id;
+
+       /* Forget a macro definition.   */
+       if (id = GetIdentifier()) {
+               if (id->id_macro) { /* forget the macro */
+                       free_macro(id->id_macro);
+                       id->id_macro = (struct macro *) 0;
+               } /* else: don't complain */
+       }
+       else
+               lexerror("illegal #undef construction");
+       SkipToNewLine(0);
+}
+
+do_error()
+{
+       static char errbuf[512];
+       register char *bp = errbuf;
+       register int ch;
+
+       while ((ch = GetChar()) != '\n')
+               *bp++ = ch;
+       *bp = '\0';
+       UnGetChar();
+       lexerror("user error: %s", errbuf);
+}
+
+int
+getparams(buf, parbuf)
+       char *buf[];
+       char parbuf[];
+{
+       /*      getparams() reads the formal parameter list of a macro
+               definition.
+               The number of parameters is returned.
+               As a formal parameter list is expected when calling this
+               routine, -1 is returned if an error is detected, for
+               example:
+                       #define one(1), where 1 is not an identifier.
+               Note that the '(' has already been eaten.
+               The names of the formal parameters are stored into parbuf.
+       */
+       register char **pbuf = &buf[0];
+       register int c;
+       register char *ptr = &parbuf[0];
+       register char **pbuf2;
+
+       c = GetChar();
+       c = skipspaces(c,0);
+       if (c == ')') {         /* no parameters: #define name()        */
+               *pbuf = (char *) 0;
+               return 0;
+       }
+       for (;;) {              /* eat the formal parameter list        */
+               if (class(c) != STIDF && class(c) != STELL) {
+                       lexerror("#define: bad formal parameter");
+                       return -1;
+               }
+               *pbuf = ptr;    /* name of the formal   */
+               *ptr++ = c;
+               if (ptr >= &parbuf[PARBUFSIZE])
+                       fatal("formal parameter buffer overflow");
+               do {                    /* eat the identifier name      */
+                       c = GetChar();
+                       *ptr++ = c;
+                       if (ptr >= &parbuf[PARBUFSIZE])
+                               fatal("formal parameter buffer overflow");
+               } while (in_idf(c));
+               *(ptr - 1) = '\0';      /* mark end of the name         */
+
+               /*      Check if this formal parameter is already used.
+                       Usually, macros do not have many parameters, so ...
+               */
+               for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
+                       if (!strcmp(*pbuf2, *pbuf)) {
+                               warning("formal parameter \"%s\" already used",
+                                       *pbuf);
+                       }
+               }
+
+               pbuf++;
+               c = skipspaces(c,0);
+               if (c == ')') { /* end of the formal parameter list     */
+                       *pbuf = (char *) 0;
+                       return pbuf - buf;
+               }
+               if (c != ',') {
+                       lexerror("#define: bad formal parameter list");
+                       return -1;
+               }
+               c = GetChar();
+               c = skipspaces(c,0);
+       }
+       /*NOTREACHED*/
+}
+
+macro_def(id, text, nformals, length, flags)
+       register struct idf *id;
+       char *text;
+{
+       register struct macro *newdef = id->id_macro;
+
+       /*      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.
+       */
+       if (newdef) {           /* is there a redefinition?     */
+               if (macroeq(newdef->mc_text, text))
+                       return;
+               lexwarning("redefine \"%s\"", id->id_text);
+       }
+       else
+               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 */
+       newdef->mc_flag = flags;        /* special flags        */
+       newdef->mc_count = 0;
+}
+
+int
+find_name(nm, index)
+       char *nm, *index[];
+{
+       /*      find_name() returns the index of "nm" in the namelist
+               "index" if it can be found there.  0 is returned if it is
+               not there.
+       */
+       register char **ip = &index[0];
+
+       while (*ip)
+               if (strcmp(nm, *ip++) == 0)
+                       return ip - &index[0];
+       /* arrived here, nm is not in the name list.    */
+       return 0;
+}
+
+char *
+get_text(formals, length)
+       char *formals[];
+       int *length;
+{
+       /*      get_text() copies the replacement text of a macro
+               definition with zero, one or more parameters, thereby
+               substituting each formal parameter by a special character
+               (non-ascii: 0200 & (order-number in the formal parameter
+               list)) in order to substitute this character later by the
+               actual parameter.  The replacement text is copied into
+               itself because the copied text will contain fewer or the
+               same amount of characters.  The length of the replacement
+               text is returned.
+
+               Implementation:
+               finite automaton : we are only interested in
+               identifiers, because they might be replaced by some actual
+               parameter.  Other tokens will not be seen as such.
+       */
+       register int c;
+       register int text_size;
+       char *text = Malloc(text_size = ITEXTSIZE);
+       register int pos = 0;
+
+       c = GetChar();
+
+       while ((c != EOI) && (class(c) != STNL)) {
+               if (c == '\'' || c == '"') {
+                       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();
+                       } while (c != delim && c != EOI && class(c) != STNL);
+                       text[pos++] = c;
+                       c = GetChar();
+               }
+               else
+               if (c == '/') {
+                       c = GetChar();
+                       if (pos+1 >= text_size)
+                               text = Srealloc(text, text_size += RTEXTSIZE);
+                       if (c == '*') {
+                               skipcomment();
+                               text[pos++] = ' ';
+                               c = GetChar();
+                       }
+                       else
+                               text[pos++] = '/';
+               }
+               else
+               if (formals && (class(c) == STIDF || class(c) == STELL)) {
+                       char id_buf[IDFSIZE + 1];
+                       register id_size = 0;
+                       register n;
+
+                       /* read identifier: it may be a formal parameter */
+                       id_buf[id_size++] = c;
+                       do {
+                               c = GetChar();
+                               if (id_size <= IDFSIZE)
+                                       id_buf[id_size++] = c;
+                       } 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;
+                       }
+                       else {
+                               register char *ptr = &id_buf[0];
+
+                               while (pos + id_size >= text_size)
+                                       text = Srealloc(text,
+                                               text_size += RTEXTSIZE);
+                               while (text[pos++] = *ptr++) ;
+                               pos--;
+                       }
+               }
+               else {
+                       if (pos+1 >= text_size)
+                               text = Srealloc(text, text_size += RTEXTSIZE);
+                       text[pos++] = c;
+                       c = GetChar();
+               }
+       }
+       text[pos++] = '\0';
+       *length = pos - 1;
+       return text;
+}
+
+#define        BLANK(ch)       ((ch == ' ') || (ch == '\t'))
+
+/*     macroeq() decides whether two macro replacement texts are
+       identical.  This version compares the texts, which occur
+       as strings, without taking care of the leading and trailing
+       blanks (spaces and tabs).
+*/
+macroeq(s, t)
+       register char *s, *t;
+{
+       
+       /* skip leading spaces  */
+       while (BLANK(*s)) s++;
+       while (BLANK(*t)) t++;
+       /* first non-blank encountered in both strings  */
+       /* The actual comparison loop:                  */
+       while (*s && *s == *t)
+               s++, t++;
+       /* two cases are possible when arrived here:    */
+       if (*s == '\0') {       /* *s == '\0'           */
+               while (BLANK(*t)) t++;
+               return *t == '\0';
+       }
+       else    {               /* *s != *t             */
+               while (BLANK(*s)) s++;
+               while (BLANK(*t)) t++;
+               return (*s == '\0') && (*t == '\0');
+       }
+}
+#else NOPP
+domacro()
+{
+       int tok;
+       struct token tk;
+
+       EoiForNewline = 1;
+       if ((tok = GetToken(&tk)) == IDENTIFIER) {
+               if (strcmp(tk.tk_idf->id_text, "line") != 0) {
+                       error("illegal # line");
+                       SkipToNewLine(0);
+                       return;
+               }
+               tok = GetToken(&tk);
+       }
+       if (tok != INTEGER) {
+               error("illegal # line");
+               SkipToNewLine(0);
+               return;
+       }
+       do_line((unsigned int) tk.tk_ival);
+       EoiForNewline = 0;
+}
+#endif NOPP
+
+
+do_line(l)
+       unsigned int l;
+{
+       struct token tk;
+
+       LineNumber = l - 1;     /* the number of the next input line */
+       if (GetToken(&tk) == STRING)    /* is there a filespecifier? */
+               FileName = tk.tk_bts;
+       SkipToNewLine(0);
+}
diff --git a/lang/cem/cemcom.ansi/dumpidf.c b/lang/cem/cemcom.ansi/dumpidf.c
new file mode 100644 (file)
index 0000000..cd11ff4
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     DUMP ROUTINES   */
+
+#include       "debug.h"
+
+#ifdef DEBUG
+#include       "nofloat.h"
+#include       "nopp.h"
+#include       "nobitfield.h"
+#include       "arith.h"
+#include       "stack.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "type.h"
+#include       "proto.h"
+#include       "struct.h"
+#include       "field.h"
+#include       "Lpars.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "static.h"
+#include       "declar.h"
+
+/*     Some routines (symbol2str, token2str, type2str) which should have
+ *     yielded strings are written to yield a pointer to a transient piece
+ *     of memory, containing the string, since this is the only reasonable
+ *     thing to do in C. `Transient' means that the result may soon
+ *     disappear, which is generally not a problem, since normally it is
+ *     consumed immediately. Sometimes we need more than one of them, and
+ *     MAXTRANS is the maximum number we will need simultaneously.
+ */
+#define        MAXTRANS        6
+
+extern char options[];
+
+extern char *sprint();
+
+extern struct idf *idf_hashtable[];
+extern char *symbol2str(), *type2str(), *qual2str(), *next_transient();
+
+enum sdef_kind {selector, field};              /* parameter for dumpsdefs */
+
+static int dumplevel;
+
+newline()      {
+       register int dl = dumplevel;
+       
+       print("\n");
+       while (dl >= 2) {
+               print("\t");
+               dl -= 2;
+       }
+       if (dl)
+               print("    ");
+}
+
+dumpidftab(msg, opt)
+       char msg[];
+{
+       /*      Dumps the identifier table in readable form (but in
+               arbitrary order).
+               Unless opt & 1, macros are not dumped.
+               Unless opt & 2, reserved identifiers are not dumped.
+               Unless opt & 4, universal identifiers are not dumped.
+       */
+       int i;
+
+       print(">>> DUMPIDF, %s (start)", msg);
+       dumpstack();
+       for (i = 0; i < HASHSIZE; i++)  {
+               register struct idf *notch = idf_hashtable[i];
+
+               while (notch)   {
+                       dumpidf(notch, opt);
+                       notch = notch->next;
+               }
+       }
+       newline();
+       print(">>> DUMPIDF, %s (end)\n", msg);
+}
+
+dumpstack()
+{
+       /*      Dumps the identifier stack, starting at the top.
+       */
+       register struct stack_level *stl = local_level;
+       
+       while (stl)     {
+               register struct stack_entry *se = stl->sl_entry;
+               
+               newline();
+               print("%3d: ", stl->sl_level);
+               while (se)      {
+                       print("%s ", se->se_idf->id_text);
+                       se = se->next;
+               }
+               stl = stl->sl_previous;
+       }
+       print("\n");
+}
+
+dumpidf(idf, opt)
+       register struct idf *idf;
+{
+       /*      All information about the identifier idf is divulged in a
+               hopefully readable format.
+       */
+       int started = 0;
+       
+       if (!idf)
+               return;
+#ifndef NOPP
+       if ((opt&1) && idf->id_macro)   {
+               if (!started++) {
+                       newline();
+                       print("%s:", idf->id_text);
+               }
+               print(" macro");
+       }
+#endif NOPP
+       if ((opt&2) && idf->id_reserved)        {
+               if (!started++) {
+                       newline();
+                       print("%s:", idf->id_text);
+               }
+               print(" reserved: %d;", idf->id_reserved);
+       }
+       if (idf->id_def && ((opt&4) || idf->id_def->df_level))  {
+               if (!started++) {
+                       newline();
+                       print("%s:", idf->id_text);
+               }
+               dumpdefs(idf->id_def, opt);
+       }
+       if (idf->id_sdef)       {
+               if (!started++) {
+                       newline();
+                       print("%s:", idf->id_text);
+               }
+               dumpsdefs(idf->id_sdef, selector);
+       }
+       if (idf->id_struct)     {
+               if (!started++) {
+                       newline();
+                       print("%s:", idf->id_text);
+               }
+               dumptags(idf->id_struct);
+       }
+       if (idf->id_enum)       {
+               if (!started++) {
+                       newline();
+                       print("%s:", idf->id_text);
+               }
+               dumptags(idf->id_enum);
+       }
+}
+
+dumpdefs(def, opt)
+       register struct def *def;
+{
+       dumplevel++;
+       while (def && ((opt&4) || def->df_level))       {
+               newline();
+               print("L%d: %s %s%stype%s %lo; ",
+                       def->df_level,
+                       symbol2str(def->df_sc),
+                       def->df_initialized ? "init'd " : "",
+                       def->df_used ? "used " : "",
+                       def->df_sc == ENUM ? ", =" : " at",
+                       def->df_address
+               );
+               print("%s, line %u",
+                       def->df_file ? def->df_file : "NO_FILE", def->df_line);
+               dump_type(def->df_type);
+               def = def->next;
+       }
+       dumplevel--;
+}
+
+dumptags(tag)
+       register struct tag *tag;
+{
+       dumplevel++;
+       while (tag)     {
+               register struct type *tp = tag->tg_type;
+               register int fund = tp->tp_fund;
+
+               newline();
+               print("L%d: %s %s",
+                       tag->tg_level,
+                       fund == STRUCT ? "struct" :
+                       fund == UNION ? "union" :
+                       fund == ENUM ? "enum" : "<UNKNOWN>",
+                       tp->tp_idf->id_text
+               );
+               if (is_struct_or_union(fund))   {
+                       print(" {");
+                       dumpsdefs(tp->tp_sdef, field);
+                       newline();
+                       print("}");
+               }
+               print(";");
+               tag = tag->next;
+       }
+       dumplevel--;
+}
+
+dumpsdefs(sdef, sdk)
+       register struct sdef *sdef;
+       enum sdef_kind sdk;
+{
+       /*      Since sdef's are members of two chains, there are actually
+               two dumpsdefs's, one following the chain of all selectors
+               belonging to the same idf, starting at idf->id_sdef;
+               and the other following the chain of all selectors belonging
+               to the same struct, starting at stp->tp_sdef.
+       */
+
+       dumplevel++;
+       while (sdef)    {
+               newline();
+               print("L%d: ", sdef->sd_level);
+#ifndef NOBITFIELD
+               if (sdk == selector)
+#endif NOBITFIELD
+                       print("selector %s at offset %lu in %s;",
+                               type2str(sdef->sd_type),
+                               sdef->sd_offset, type2str(sdef->sd_stype)
+                       );
+#ifndef NOBITFIELD
+               else    print("field %s at offset %lu;",
+                               type2str(sdef->sd_type), sdef->sd_offset
+                       );
+#endif NOBITFIELD
+               sdef = (sdk == selector ? sdef->next : sdef->sd_sdef);
+       }
+       dumplevel--;
+}
+
+dump_proto(pl)
+       register struct proto *pl;
+{
+       register struct type *type;
+       register int argcnt = 0;
+
+       newline();
+       print("dump proto type list (start)");
+       newline();
+       while (pl) {
+               print("%d: %s", argcnt++,
+                       pl->pl_flag == FORMAL ?
+                       (pl->pl_flag == VOID ? "void" : "formal")
+                       : "ellipsis");
+               newline();
+               if (type = pl->pl_type){
+                       dump_type(type);
+                       newline();
+               }
+               if (pl->pl_idf) {
+                       dumplevel++;
+                       print("idf:");
+                       dumpidf(pl->pl_idf, 7);
+                       dumplevel--;
+               }
+               newline();
+               pl = pl->next;
+       }
+       print("dump proto type list (end)\n");
+}
+
+dump_type(tp)
+       register struct type *tp;
+{
+       int ops = 1;
+
+       dumplevel++;
+       newline();
+       if (!tp) {
+               print("<NILTYPE>");
+               newline();
+               return;
+       }
+
+       print("(@%lx, #%ld, &%d) ", tp, (long)tp->tp_size, tp->tp_align);
+
+       while (ops)     {
+               print("%s", qual2str(tp->tp_typequal));
+               switch (tp->tp_fund)    {
+               case POINTER:
+                       print("pointer to ");
+                       break;
+               case ARRAY:
+                       print("array [%ld] of ", tp->tp_size);
+                       break;
+               case FUNCTION:
+                       print("function ");
+                       if (tp->tp_proto) {
+                               print("with prototype");
+                               dumplevel++;
+                               dump_proto(tp->tp_proto);
+                               dumplevel--;
+                               newline();
+                       }
+                       print("yielding ");
+                       break;
+               default:
+                       print("%s%s ", tp->tp_unsigned ? "unsigned " : "",
+                                      symbol2str(tp->tp_fund));
+                       if (tp->tp_idf)
+                               print("%s ", tp->tp_idf->id_text);
+#ifndef NOBITFIELD
+                       if (tp->tp_field)       {
+                               struct field *fd = tp->tp_field;
+                               
+                               print("[s=%ld,w=%ld] of ",
+                                       fd->fd_shift, fd->fd_width);
+                       }
+                       else
+#endif NOBITFIELD
+                       ops = 0;
+                       break;
+               }
+               tp = tp->tp_up;
+       }
+       dumplevel--;
+}
+
+char *
+type2str(tp)
+       register struct type *tp;
+{
+       /*      Yields a pointer to a one-line description of the type tp.
+       */
+       char *buf = next_transient();
+       int ops = 1;
+
+       buf[0] = '\0';
+       if (!tp)        {
+               sprint(buf, "<NILTYPE>");
+               return buf;
+       }
+       sprint(buf, "%s(@%lx, #%ld, &%d) ",
+                       buf, tp, (long)tp->tp_size, tp->tp_align);
+
+       while (ops)     {
+               sprint(buf, "%s%s", buf, qual2str(tp->tp_typequal));
+               switch (tp->tp_fund)    {
+               case POINTER:
+                       sprint(buf, "%spointer to ", buf);
+                       break;
+               case ARRAY:
+                       sprint(buf, "%sarray [%ld] of ", buf, tp->tp_size);
+                       break;
+               case FUNCTION:
+                       sprint(buf, "%sfunction yielding ", buf);
+                       break;
+               default:
+                       sprint(buf, "%s%s%s ", buf,
+                                       tp->tp_unsigned ? "unsigned " : "",
+                                       symbol2str(tp->tp_fund)
+                       );
+                       if (tp->tp_idf)
+                               sprint(buf, "%s %s ", buf,
+                                       tp->tp_idf->id_text);
+#ifndef NOBITFIELD
+                       if (tp->tp_field)       {
+                               struct field *fd = tp->tp_field;
+                               
+                               sprint(buf, "%s [s=%ld,w=%ld] of ", buf,
+                                       fd->fd_shift, fd->fd_width);
+                       }
+                       else
+#endif NOBITFIELD
+                       ops = 0;
+                       break;
+               }
+               tp = tp->tp_up;
+       }
+       return buf;
+}
+
+char *
+qual2str(qual)
+       int qual;
+{
+       char *buf = next_transient();
+
+       *buf = '\0';
+       if (qual == 0)
+               sprint(buf, "(none)");
+       if (qual & TQ_CONST)
+               sprint(buf, "%sconst ", buf);
+       if (qual & TQ_VOLATILE)
+               sprint(buf, "%svolatile ", buf);
+
+       return qual == 0 ? "" : buf;
+}
+
+GSTATIC char trans_buf[MAXTRANS][300];
+
+char *         /* the ultimate transient buffer supplier */
+next_transient()
+{
+       static int bnum;
+
+       if (++bnum == MAXTRANS)
+               bnum = 0;
+       return trans_buf[bnum];
+}
+
+print_expr(msg, expr)
+       char msg[];
+       struct expr *expr;
+{
+       /*      Provisional routine to print an expression preceded by a
+               message msg.
+       */
+       if (options['x'])       {
+               print("\n%s: ", msg);
+               print("(L=line, T=type, r/lV=r/lvalue, F=flags, D=depth)\n");
+               p1_expr(0, expr);
+       }
+}
+
+p1_expr(lvl, expr)
+       register struct expr *expr;
+{
+       p1_indent(lvl);
+       if (!expr)      {
+               print("NILEXPR\n");
+               return;
+       }
+       print("expr: L=%u, T=%s, %cV, F=%03o, D=%d, %s: ",
+               expr->ex_line,
+               type2str(expr->ex_type),
+               expr->ex_lvalue ? 'l' : 'r',
+               expr->ex_flags & 0xFF,
+               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"
+       );
+       switch (expr->ex_class) {
+               struct oper *o;
+       case Value:
+               switch (expr->VL_CLASS) {
+               case Const:
+                       print("(Const) ");
+                       break;
+               case Name:
+                       print("(Name) %s + ", expr->VL_IDF->id_text);
+                       break;
+               case Label:
+                       print("(Label) .%lu + ", expr->VL_LBL);
+                       break;
+               default:
+                       print("(Unknown) ");
+                       break;
+               }
+               print(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n",
+                       expr->VL_VALUE);
+               break;
+       case String:
+       {
+               char *bts2str();
+
+               print(
+                       "\"%s\"\n",
+                       bts2str(expr->SG_VALUE, expr->SG_LEN-1,
+                                                       next_transient())
+               );
+               break;
+       }
+#ifndef NOFLOAT
+       case Float:
+               print("%s\n", expr->FL_VALUE);
+               break;
+#endif NOFLOAT
+       case Oper:
+               o = &expr->ex_object.ex_oper;
+               print("\n");
+               p1_expr(lvl+1, o->op_left);
+               p1_indent(lvl);
+               print("%s <%s>\n", symbol2str(o->op_oper),
+                       type2str(o->op_type)
+               );
+               p1_expr(lvl+1, o->op_right);
+               break;
+       case Type:
+               print("\n");
+               break;
+       default:
+               print("UNKNOWN CLASS\n");
+               break;
+       }
+}
+
+p1_indent(lvl)
+       register int lvl;
+{
+       while (lvl--)
+               print("  ");
+}
+#endif DEBUG
diff --git a/lang/cem/cemcom.ansi/error.c b/lang/cem/cemcom.ansi/error.c
new file mode 100644 (file)
index 0000000..89517f4
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     E R R O R   A N D  D I A G N O S T I C   R O U T I N E S        */
+
+#include       <varargs.h>
+#include       <system.h>
+#include       <em.h>
+
+#include       "lint.h"
+#include       "nopp.h"
+#include       "errout.h"
+#include       "debug.h"
+
+#include       "tokenname.h"
+#include       "arith.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "def.h"
+#include       "LLlex.h"
+
+/*     This file contains the error-message and diagnostic
+       functions.  Beware, they are called with a variable number of
+       arguments!
+*/
+
+/* error classes */
+#define        STRICT          1
+#define        WARNING         2
+#define        ERROR           3
+#define        CRASH           4
+#define        FATAL           5
+
+int err_occurred = 0;
+
+extern char options[];
+#ifdef LINT
+extern char loptions[];
+#endif LINT
+
+/*     There are three general error-message functions:
+               lexerror()      lexical and pre-processor error messages
+               error()         syntactic and semantic error messages
+               expr_error()    errors in expressions
+       The difference lies in the place where the file name and line
+       number come from.
+       Lexical errors report from the global variables LineNumber and
+       FileName, expression errors get their information from the
+       expression, whereas other errors use the information in the token.
+*/
+
+static _error();
+
+/*VARARGS*/
+error(va_alist)                                /* fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               _error(ERROR, dot.tk_file, dot.tk_line, ap);
+       }
+       va_end(ap);
+}
+
+/*VARARGS*/
+expr_error(va_alist)                   /* expr, fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               register struct expr *expr = va_arg(ap, struct expr *);
+
+               if (!(expr->ex_flags & EX_ERROR)) {
+                       /* to prevent proliferation */
+                       _error(ERROR, expr->ex_file, expr->ex_line, ap);
+                       expr->ex_flags |= EX_ERROR;
+               }
+       }
+       va_end(ap);
+}
+
+/*VARARGS*/
+strict(va_alist)
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               _error(STRICT, FileName, LineNumber, ap);
+       }
+       va_end(ap);
+}
+
+/*VARARGS*/
+warning(va_alist)
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               _error(WARNING, NILEXPR, ap);
+       }
+       va_end(ap);
+}
+
+/*VARARGS*/
+expr_warning(va_alist)                 /* expr, fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               struct expr *expr = va_arg(ap, struct expr *);
+
+               if (!(expr->ex_flags & EX_ERROR)) {
+                       /* to prevent proliferation */
+                       _error(WARNING, expr->ex_file, expr->ex_line, ap);
+               }
+       }
+       va_end(ap);
+}
+
+#ifdef LINT
+
+/*VARARGS*/
+def_warning(va_alist)                  /* def, fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               register struct def *def = va_arg(ap, struct def *);
+
+               _error(WARNING, def->df_file, def->df_line, ap);
+       }
+       va_end(ap);
+}
+
+
+/*VARARGS*/
+hwarning(va_alist)                     /* fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               if (loptions['h'])
+                       _error(WARNING, dot.tk_file, dot.tk_line, ap);
+       }
+       va_end(ap);
+}
+
+/*VARARGS*/
+awarning(va_alist)                     /* fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               if (loptions['a'])
+                       _error(WARNING, dot.tk_file, dot.tk_line, ap);
+       }
+       va_end(ap);
+}
+
+#endif LINT
+
+/*VARARGS*/
+lexerror(va_alist)                     /* fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               _error(ERROR, FileName, LineNumber, ap);
+       }
+       va_end(ap);
+}
+
+#ifndef        NOPP
+/*VARARGS*/
+lexwarning(va_alist)                   /* fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               _error(WARNING, FileName, LineNumber, ap);
+       }
+       va_end(ap);
+}
+#endif NOPP
+
+/*VARARGS*/
+crash(va_alist)                                /* fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               _error(CRASH, FileName, LineNumber, ap);
+       }
+       va_end(ap);
+
+       C_close();
+#ifdef DEBUG
+       sys_stop(S_ABORT);
+#else  DEBUG
+       sys_stop(S_EXIT);
+#endif DEBUG
+       /* NOTREACHED */
+}
+
+/*VARARGS*/
+fatal(va_alist)                                /* fmt, args */
+       va_dcl
+{
+       va_list ap;
+
+       va_start(ap);
+       {
+               _error(FATAL, FileName, LineNumber, ap);
+       }
+       va_end(ap);
+
+       if (C_busy()) C_close();
+       sys_stop(S_EXIT);
+       /*NOTREACHED*/
+}
+
+static
+_error(class, fn, ln, ap)
+       int class;
+       char *fn;
+       unsigned int ln;
+       va_list ap;
+{
+       /*      _error attempts to limit the number of error messages
+               for a given line to MAXERR_LINE.
+       */
+#ifndef        LINT
+       static char *last_fn = 0;
+       static unsigned int last_ln = 0;
+       static int e_seen = 0;
+#endif LINT
+       char *remark;
+       char *fmt = va_arg(ap, char *);
+       
+       /*      Since name and number are gathered from different places
+               depending on the class, we first collect the relevant
+               values and then decide what to print.
+       */
+       /* preliminaries */
+       switch (class)  {
+       case WARNING:
+               if (options['w'])
+                       return;
+               break;
+
+       case STRICT:
+               if (options['s'])
+                       return;
+               break;
+
+       case ERROR:
+       case CRASH:
+       case FATAL:
+               if (C_busy())
+                       C_ms_err();
+               err_occurred = 1;
+               break;
+       }
+
+       /* the remark */
+       switch (class)  {       
+       case STRICT:
+               remark = "(strict)";
+               break;
+       case WARNING:
+#ifndef        LINT
+               remark = "(warning)";
+#else  LINT
+               remark = 0;
+#endif LINT
+               break;
+
+       case ERROR:
+               remark = 0;
+               break;
+
+       case CRASH:
+               remark = "CRASH\007";
+               break;
+
+       case FATAL:
+               remark = "fatal error --";
+               break;
+       default:
+               /*NOTREACHED*/;
+       }
+       
+#ifndef        LINT
+       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)
+                       fmt = "etc ...";
+               else
+               if (e_seen > MAXERR_LINE)
+                       /* and too often, I'd say ! */
+                       return;
+       }
+       else    {
+               /* brand new place */
+               last_fn = fn;
+               last_ln = ln;
+               e_seen = 0;
+       }
+#endif LINT
+
+#ifdef LINT
+       if (    /* there is a file name */
+               fn
+       &&      /* the file name is global */
+               fn[0] == '/'
+       &&      /* it is not a .c file */
+               strcmp(&fn[strlen(fn)-2], ".c") != 0
+       ) {
+               /* we skip this message */
+               return;
+       }
+#endif LINT
+       
+       if (fn)
+               fprint(ERROUT, "\"%s\", line %u: ", fn, ln);
+       if (remark)
+               fprint(ERROUT, "%s ", remark);
+       doprnt(ERROUT, fmt, ap);                /* contents of error */
+       fprint(ERROUT, "\n");
+}
diff --git a/lang/cem/cemcom.ansi/estack.str b/lang/cem/cemcom.ansi/estack.str
new file mode 100644 (file)
index 0000000..b71bdb3
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* EXPRESSION STACK */
+/* Used for global initializations */
+struct e_stack {
+       struct e_stack  *next;
+       arith           s_cnt1, s_cnt2;
+       struct sdef     *s_def;
+       struct type     **s_tpp;
+       char            s_nested;
+};
+
+/* ALLOCDEF "e_stack" 5 */
+
+#define bytes_upto_here        s_cnt1
+#define last_offset    s_cnt2
+#define elem_count     s_cnt1
+#define nelem          s_cnt2
diff --git a/lang/cem/cemcom.ansi/eval.c b/lang/cem/cemcom.ansi/eval.c
new file mode 100644 (file)
index 0000000..a34cb77
--- /dev/null
@@ -0,0 +1,994 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* EXPRESSION-CODE GENERATOR */
+
+#include       "lint.h"
+#ifndef        LINT
+
+#include       "nofloat.h"
+#include       <em.h>
+#include       <em_reg.h>
+#include       "debug.h"
+#include       "nobitfield.h"
+#include       "dataflow.h"
+#include       "arith.h"
+#include       "type.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "code.h"
+#include       "assert.h"
+#include       "def.h"
+#include       "expr.h"
+#include       "sizes.h"
+#include       "Lpars.h"
+#include       "level.h"
+#include       "stack.h"
+#include       "align.h"
+#include       "mes.h"
+#include       "atw.h"
+#include       "specials.h"
+
+#define        CRASH()         crash("EVAL: CRASH at line %u", __LINE__)
+
+char *symbol2str();
+char *long2str();
+arith NewLocal();      /* util.c */
+#define LocalPtrVar()  NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER)
+
+/*     EVAL() is the main expression-tree evaluator, which turns
+       any legal expression tree into EM code. Parameters:
+
+       struct expr *expr
+               pointer to root of the expression tree to be evaluated
+
+       int val
+               indicates whether the resulting expression is to be
+               dereferenced (if val == RVAL and expr->ex_lvalue == 1)
+               or not (val == LVAL).  The latter case indicates that
+               the resulting expression is an lvalue expression which
+               should not be dereferenced by EVAL
+       
+       int code
+               indicates whether the expression tree must be turned
+               into EM code or not. E.g. the expression statement "12;"
+               delivers the expression "12" to EVAL while this should
+               not result in any EM code
+       
+       label false_label, label true_label
+               if the expression is a logical or relational expression
+               and if the loop of the program depends on the resulting
+               value then EVAL generates jumps to the specified program
+               labels, in case they are specified (i.e. are non-zero)
+*/
+
+EVAL(expr, val, code, true_label, false_label)
+       register struct expr *expr;
+       int val, code;
+       label true_label, false_label;
+{
+       register int gencode = (code == TRUE);
+
+       switch (expr->ex_class) {
+       case Value:     /* just a simple value  */
+               if (gencode)
+                       load_val(expr, val);
+               break;
+       case String:    /* a string constant    */
+               if (gencode) {
+                       string2pointer(expr);
+                       C_lae_dlb(expr->VL_LBL, expr->VL_VALUE);
+               }
+               break;
+#ifndef NOFLOAT
+       case Float:     /* a floating constant  */
+               if (gencode) {
+                       label datlab = data_label();
+                       
+                       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;
+               register struct expr *left = expr->OP_LEFT;
+               register struct expr *right = expr->OP_RIGHT;
+               register struct type *tp = expr->OP_TYPE;
+
+               if (tp->tp_fund == ERRONEOUS || (expr->ex_flags & EX_ERROR)) {
+                       /* stop immediately */
+                       break;
+               }
+               if (tp->tp_fund == VOID)
+                       gencode = 0;
+               switch (oper) {
+               case '+':
+                       /*      We have the following possibilities :
+                               int + int, pointer + int, pointer + long,
+                               long + long, double + double
+                       */
+                       EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       if (gencode) {
+                               switch (tp->tp_fund) {
+                               case INT:
+                               case LONG:
+                                       if (tp->tp_unsigned)
+                                               C_adu(tp->tp_size);
+                                       else
+                                               C_adi(tp->tp_size);
+                                       break;
+                               case POINTER:
+                                       C_loc(right->ex_type->tp_size);
+                                       C_loc(pointer_size);
+                                       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 +");
+                               }
+                       }
+                       break;
+               case '-':
+                       if (left == 0) {        /* unary        */
+                               EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                               if (gencode) {
+                                       switch (tp->tp_fund) {
+                                       case INT:
+                                       case LONG:
+                                       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();
+                                       }
+                               }
+                               break;
+                       }
+                       /*      else binary; we have the following flavours:
+                               int - int, pointer - int, pointer - long,
+                               pointer - pointer, long - long, double - double
+                       */
+                       EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       if (!gencode)
+                               break;
+                       switch (tp->tp_fund) {
+                       case INT:
+                       case LONG:
+                               if (tp->tp_unsigned)
+                                       C_sbu(tp->tp_size);
+                               else
+                                       C_sbi(tp->tp_size);
+                               break;
+                       case POINTER:
+                               if (right->ex_type->tp_fund == POINTER)
+                                       C_sbs(pointer_size);
+                               else {
+                                       C_ngi(right->ex_type->tp_size);
+                                       C_loc(right->ex_type->tp_size);
+                                       C_loc(pointer_size);
+                                       C_cuu();
+                                       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 -");
+                       }
+                       break;
+               case '*':
+                       if (left == 0) { /* unary */
+                               EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                               if (gencode && right->ex_class == String) {
+                                       C_loi((arith)1);
+                               }
+                       }
+                       else { /* binary */
+                               EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                               EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                               if (gencode)
+                                       switch (tp->tp_fund) {
+                                       case INT:
+                                       case LONG:
+                                       case POINTER:
+                                               if (tp->tp_unsigned)
+                                                       C_mlu(tp->tp_size);
+                                               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 *");
+                                       }
+                       }
+                       break;
+               case '/':
+                       EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       if (gencode)
+                               switch (tp->tp_fund) {
+                               case INT:
+                               case LONG:
+                               case POINTER:
+                                       if (tp->tp_unsigned)
+                                               C_dvu(tp->tp_size);
+                                       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 /");
+                               }
+                       break;
+               case '%':
+                       EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       ASSERT(tp->tp_fund==INT || tp->tp_fund==LONG);
+                       if (gencode)
+                               if (tp->tp_unsigned)
+                                       C_rmu(tp->tp_size);
+                               else
+                                       C_rmi(tp->tp_size);
+                       break;
+               case LEFT:
+                       EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       if (gencode)
+                               if (tp->tp_unsigned)
+                                       C_slu(tp->tp_size);
+                               else
+                                       C_sli(tp->tp_size);
+                       break;
+               case RIGHT:
+                       EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       if (gencode)
+                               if (tp->tp_unsigned)
+                                       C_sru(tp->tp_size);
+                               else
+                                       C_sri(tp->tp_size);
+                       break;
+               case '<':
+               case LESSEQ:
+               case '>':
+               case GREATEREQ:
+               case EQUAL:
+               case NOTEQUAL:
+                       EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       if (gencode) {
+                               /* The operands have the same type */
+                               arith size = left->ex_type->tp_size;
+                               
+                               switch (tp->tp_fund) {
+                               case INT:
+                               case LONG:
+                                       if (left->ex_type->tp_unsigned)
+                                               C_cmu(size);
+                                       else
+                                               C_cmi(size);
+                                       break;
+#ifndef NOFLOAT
+                               case FLOAT:
+                               case DOUBLE:
+                               case LNGDBL:
+                                       C_cmf(size);
+                                       break;
+#endif NOFLOAT
+                               case POINTER:
+                                       C_cmp();
+                                       break;
+                               case ENUM:
+                                       C_cmi(size);
+                                       break;
+                               default:
+                                       CRASH();
+                               }
+                               if (true_label != 0) {
+                                       compare(oper, true_label);
+                                       C_bra(false_label);
+                               }
+                               else {
+                                       truthvalue(oper);
+                               }
+                       }
+                       break;
+               case '&':
+               case '|':
+               case '^':
+                       /* both operands should have type int   */
+                       EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       if (gencode) {
+                               arith size = tp->tp_size;
+
+                               if ((int)size < (int)word_size)
+                                       size = word_size;
+                               switch (oper) {
+                               case '&':
+                                       C_and(size);
+                                       break;
+                               case '|':
+                                       C_ior(size);
+                                       break;
+                               case '^':
+                                       C_xor(size);
+                                       break;
+                               }
+                       }
+                       break;
+               case '=': {
+                       int newcode = tp->tp_size > 0;  /* CJ */
+#ifndef NOBITFIELD
+                       if (left->ex_type->tp_fund == FIELD) {
+                               eval_field(expr, gencode);
+                               break;
+                       }
+#endif NOBITFIELD
+                       EVAL(right, RVAL, newcode, NO_LABEL, NO_LABEL);
+                       if (gencode)
+                               C_dup(ATW(tp->tp_size));
+                       if (left->ex_class != Value) {
+                               EVAL(left, LVAL, newcode, NO_LABEL, NO_LABEL);
+                               if (newcode)
+                                       store_block(tp->tp_size, tp->tp_align);
+                       }
+                       else if (newcode)
+                               store_val(&(left->EX_VALUE), left->ex_type);
+                       }
+                       break;
+               case PLUSAB:
+               case MINAB:
+               case TIMESAB:
+               case DIVAB:
+               case MODAB:
+               case LEFTAB:
+               case RIGHTAB:
+               case ANDAB:
+               case XORAB:
+               case ORAB:
+               case POSTINCR:
+               case POSTDECR:
+               case PLUSPLUS:
+               case MINMIN:
+               {
+                       arith tmp;
+                       int compl;      /* Complexity of left operand */
+                       int newcode = left->ex_type->tp_size > 0; /* CJ */
+#ifndef NOBITFIELD
+                       if (left->ex_type->tp_fund == FIELD) {
+                               eval_field(expr, gencode);
+                               break;
+                       }
+#endif NOBITFIELD
+                       if (newcode && left->ex_class == Value) {
+                               compl = 0; /* Value */
+                               load_val(left, RVAL);
+                       }
+                       else
+                       if (left->ex_depth == 1 &&
+                           !(left->ex_flags & EX_SIDEEFFECTS)) {
+                               compl = 1;
+                               EVAL(left, RVAL, newcode, NO_LABEL, NO_LABEL);
+                       }
+                       else {
+                               compl = 2; /* otherwise */
+                               EVAL(left, LVAL, newcode, NO_LABEL, NO_LABEL);
+                               if (newcode) {
+                                       tmp = LocalPtrVar();
+                                       C_dup(pointer_size);
+                                       StoreLocal(tmp, pointer_size);
+                                       C_loi(left->ex_type->tp_size);
+                               }
+                       }
+                       if (newcode) {
+                               if (gencode && (oper == POSTINCR ||
+                                               oper == POSTDECR))
+                                       C_dup(ATW(left->ex_type->tp_size));
+                               conversion(left->ex_type, tp);
+                       }
+                       EVAL(right, RVAL, newcode, NO_LABEL, NO_LABEL);
+                       if (newcode) {
+                               int dupval = gencode && oper != POSTINCR &&
+                                               oper != POSTDECR;
+                               assop(tp, oper);
+                               conversion(tp, left->ex_type);
+                               if (compl == 0) {
+                                       store_val(&(left->EX_VALUE),
+                                               left->ex_type);
+                                       if (dupval) load_val(left, RVAL);
+                               }
+                               else if (compl == 1) {
+                                       EVAL(left, LVAL,1, NO_LABEL, NO_LABEL);
+                                       C_sti(left->ex_type->tp_size);
+                                       if (dupval) {
+                                               EVAL(left, LVAL, 1, NO_LABEL,
+                                                       NO_LABEL);
+                                               C_loi(left->ex_type->tp_size);
+                                       }
+                               }
+                               else {
+                                       LoadLocal(tmp, pointer_size);
+                                       C_sti(left->ex_type->tp_size);
+                                       if (dupval) {
+                                               LoadLocal(tmp, pointer_size);
+                                               C_loi(left->ex_type->tp_size);
+                                       }
+                                       FreeLocal(tmp);
+                               }
+                       }
+                       break;
+               }
+               case '(':
+               {
+                       register struct expr *ex;
+                       arith ParSize = (arith)0;
+                       label setjmp_label = 0;
+
+                       if (ISNAME(left)) {
+                               if (left->VL_IDF->id_special == SP_SETJMP) {
+                                       label addr_label = data_label();
+
+                                       setjmp_label = text_label();
+                                       C_df_dlb(addr_label);
+                                       C_rom_ilb(setjmp_label);
+                                       C_lae_dlb(addr_label, (arith) 0);
+                                       C_loi(pointer_size);
+                                       ParSize += pointer_size;
+                               }
+                       }
+                       if ((ex = right) != NILEXPR) {
+                               /* function call with parameters*/
+                               while ( ex->ex_class == Oper &&
+                                       ex->OP_OPER == PARCOMMA
+                               ) {
+                                       EVAL(ex->OP_RIGHT, RVAL,
+                                            ex->ex_type->tp_size > 0,
+                                                       NO_LABEL, NO_LABEL);
+                                       ParSize += ATW(ex->ex_type->tp_size);
+                                       ex = ex->OP_LEFT;
+                               }
+                               EVAL(ex, RVAL, ex->ex_type->tp_size > 0,
+                                               NO_LABEL, NO_LABEL);
+                               ParSize += ATW(ex->ex_type->tp_size);
+                       }
+                       if (ISNAME(left)) {
+                               /* e.g., main() { (*((int (*)())0))(); } */
+                               C_cal(left->VL_IDF->id_text);
+                               if (setjmp_label) {
+                                       C_df_ilb(setjmp_label);
+                               }
+#ifdef DATAFLOW
+                               {       extern char options[];
+                                       if (options['d'])
+                                               DfaCallFunction(
+                                                       left->VL_IDF->id_text);
+                               }
+#endif DATAFLOW
+                       }
+                       else {
+                               EVAL(left, LVAL, TRUE, NO_LABEL, NO_LABEL);
+                               C_cai();
+                       }
+                       /* remove parameters from stack */
+                       if (ParSize > (arith)0)
+                               C_asp(ParSize);
+                       if (gencode) {
+                               if (is_struct_or_union(tp->tp_fund)) {
+                                       C_lfr(pointer_size);
+                                       load_block(tp->tp_size, (int) word_size);
+                               }
+                               else
+                                       C_lfr(ATW(tp->tp_size));
+                       }
+                       break;
+               }
+               case '.':
+                       EVAL(left, LVAL, gencode, NO_LABEL, NO_LABEL);
+                       ASSERT(is_cp_cst(right));
+                       if (gencode)
+                               C_adp(right->VL_VALUE);
+                       break;
+               case ARROW:
+                       EVAL(left, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       ASSERT(is_cp_cst(right));
+                       if (gencode)
+                               C_adp(right->VL_VALUE);
+                       break;
+               case ',':
+                       EVAL(left, RVAL, FALSE, NO_LABEL, NO_LABEL);
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       break;
+               case '~':
+                       EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       if (gencode)
+                               C_com(tp->tp_size);
+                       break;
+               case '?':       /* must be followed by ':'      */
+               {
+                       label l_true = text_label();
+                       label l_false = text_label();
+                       label l_end = text_label();
+
+                       EVAL(left, RVAL, TRUE, l_true, l_false);
+                       C_df_ilb(l_true);
+                       EVAL(right->OP_LEFT, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       C_bra(l_end);
+                       C_df_ilb(l_false);
+                       EVAL(right->OP_RIGHT, RVAL, gencode, NO_LABEL, NO_LABEL);
+                       C_df_ilb(l_end);
+                       break;
+               }
+               case OR:
+               case AND: {
+                       label l_false, l_true, l_maybe;
+
+                       l_maybe = text_label();
+                       if (true_label) {
+                               l_false = false_label;
+                               l_true = true_label;
+                       }
+                       else {
+                               l_false = text_label();
+                               l_true = gencode ? text_label(): l_false;
+                       }
+
+                       EVAL(left, RVAL, TRUE, oper == AND ? l_maybe : l_true,
+                                              oper == AND ? l_false : l_maybe);
+                       C_df_ilb(l_maybe);
+                       EVAL(right, RVAL, gencode, l_true, l_false);
+                       if (gencode && !true_label) {
+                               label l_end = text_label();
+
+                               C_df_ilb(l_true);
+                               C_loc((arith)1);
+                               C_bra(l_end);
+                               C_df_ilb(l_false);
+                               C_loc((arith)0);
+                               C_df_ilb(l_end);
+                       }
+                       else {
+                               if (! true_label) C_df_ilb(l_false);
+                       }
+                       }
+                       break;
+               case '!':
+                       if (true_label == 0) {
+                               EVAL(right, RVAL, gencode, NO_LABEL, NO_LABEL);
+                               if (gencode) {
+                                       C_teq();
+                               }
+                       }
+                       else
+                               EVAL(right, RVAL, gencode, 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);
+                       break;
+               default:
+                       crash("(EVAL) bad operator %s\n", symbol2str(oper));
+               }
+               /*      If the rvalue of the expression is required but
+                       only its lvalue is evaluated, its rvalue is
+                       loaded by the following statements:
+               */
+               if (gencode && val == RVAL && expr->ex_lvalue == 1)
+                       load_block(expr->ex_type->tp_size,
+                               expr->ex_type->tp_align);
+               break;
+       }
+       default:
+               crash("(EVAL) bad expression class");
+       }
+}
+
+/*     compare() serves as an auxiliary function of EVAL       */
+compare(relop, lbl)
+       int relop;
+       label lbl;
+{
+       switch (relop) {
+       case '<':
+               C_zlt(lbl);
+               break;
+       case LESSEQ:
+               C_zle(lbl);
+               break;
+       case '>':
+               C_zgt(lbl);
+               break;
+       case GREATEREQ:
+               C_zge(lbl);
+               break;
+       case EQUAL:
+               C_zeq(lbl);
+               break;
+       case NOTEQUAL:
+               C_zne(lbl);
+               break;
+       default:
+               CRASH();
+       }
+}
+
+/*     truthvalue() serves as an auxiliary function of EVAL    */
+truthvalue(relop)
+       int relop;
+{
+       switch (relop)  {
+       case '<':
+               C_tlt();
+               break;
+       case LESSEQ:
+               C_tle();
+               break;
+       case '>':
+               C_tgt();
+               break;
+       case GREATEREQ:
+               C_tge();
+               break;
+       case EQUAL:
+               C_teq();
+               break;
+       case NOTEQUAL:
+               C_tne();
+               break;
+       default:
+               CRASH();
+       }
+}
+
+
+/*     assop() generates the opcode of an assignment operators op=     */
+assop(type, oper)
+       register struct type *type;
+       int oper;
+{
+       register arith size;
+       register uns = type->tp_unsigned;
+
+       if ((int)(size = type->tp_size) < (int)word_size)
+               size = word_size;
+       switch (type->tp_fund) {
+       case CHAR:
+       case SHORT:
+       case INT:
+       case LONG:
+       case ENUM:
+               switch (oper) {
+               case PLUSAB:
+               case PLUSPLUS:
+               case POSTINCR:
+                       if (uns)
+                               C_adu(size);
+                       else
+                               C_adi(size);
+                       break;
+               case MINAB:
+               case MINMIN:
+               case POSTDECR:
+                       if (uns)
+                               C_sbu(size);
+                       else
+                               C_sbi(size);
+                       break;
+               case TIMESAB:
+                       if (uns)
+                               C_mlu(size);
+                       else
+                               C_mli(size);
+                       break;
+               case DIVAB:
+                       if (uns)
+                               C_dvu(size);
+                       else
+                               C_dvi(size);
+                       break;
+               case MODAB:
+                       if (uns)
+                               C_rmu(size);
+                       else
+                               C_rmi(size);
+                       break;
+               case LEFTAB:
+                       if (uns)
+                               C_slu(size);
+                       else
+                               C_sli(size);
+                       break;
+               case RIGHTAB:
+                       if (uns)
+                               C_sru(size);
+                       else
+                               C_sri(size);
+                       break;
+               case ANDAB:
+                       C_and(size);
+                       break;
+               case XORAB:
+                       C_xor(size);
+                       break;
+               case ORAB:
+                       C_ior(size);
+                       break;
+               }
+               break;
+#ifndef NOFLOAT
+       case FLOAT:
+       case DOUBLE:
+       case LNGDBL:
+               switch (oper) {
+               case PLUSAB:
+               case PLUSPLUS:
+               case POSTINCR:
+                       C_adf(size);
+                       break;
+               case MINAB:
+               case MINMIN:
+               case POSTDECR:
+                       C_sbf(size);
+                       break;
+               case TIMESAB:
+                       C_mlf(size);
+                       break;
+               case DIVAB:
+                       C_dvf(size);
+                       break;
+               }
+               break;
+#endif NOFLOAT
+       case POINTER:
+               if (oper == MINAB || oper == MINMIN || oper == POSTDECR)
+                       C_ngi(size);
+               C_loc(size);
+               C_loc(pointer_size);
+               C_cuu();
+               C_ads(pointer_size);
+               break;
+       case ERRONEOUS:
+               break;
+       default:
+               crash("(assop) bad type %s\n", symbol2str(type->tp_fund));
+       }
+}
+
+/*     store_val() generates code for a store operation.
+       There are four ways of storing data:
+       - into a global variable
+       - into an automatic local variable
+       - into a local static variable
+       - absolute addressing
+*/
+store_val(vl, tp)
+       register struct value *vl;
+       struct type *tp;
+{
+       arith size = tp->tp_size;
+       int tpalign = tp->tp_align;
+       int al_on_word;
+       register int inword;
+       register int indword;
+       arith val = vl->vl_value;
+
+       if (vl->vl_class == Const) {    /* absolute addressing */
+               load_cst(val, pointer_size);
+               store_block(size, tpalign);
+               return;
+       }
+       al_on_word = (tpalign % word_align == 0);
+       if (!(inword = (size == word_size && al_on_word)))
+               indword = (size == dword_size && al_on_word);
+       if (vl->vl_class == Name) {
+               register struct idf *id = vl->vl_data.vl_idf;
+               register struct def *df = id->id_def;
+
+               if (df->df_level == L_GLOBAL) {
+                       if (inword)
+                               C_ste_dnam(id->id_text, val);
+                       else
+                       if (indword)
+                               C_sde_dnam(id->id_text, val);
+                       else {
+                               C_lae_dnam(id->id_text, val);
+                               store_block(size, tpalign);
+                       }
+               }
+               else {
+                       ASSERT(df->df_sc != STATIC);
+                       if (inword || indword)
+                               StoreLocal(df->df_address + val, size);
+                       else {
+                               AddrLocal(df->df_address + val);
+                               store_block(size, tpalign);
+                       }
+               }
+       }
+       else {  
+               label dlb = vl->vl_data.vl_lbl;
+
+               ASSERT(vl->vl_class == Label);
+               if (inword)
+                       C_ste_dlb(dlb, val);
+               else
+               if (indword)
+                       C_sde_dlb(dlb, val);
+               else {
+                       C_lae_dlb(dlb, val);
+                       store_block(size, tpalign);
+               }
+       }
+}
+
+
+/*     load_val() generates code for stacking a certain value (from ex),
+       which can be obtained in one of the following ways:
+       - value from absolute addressed memory
+       - constant value
+       - function result
+       - global variable
+       - static variable
+       - local variable
+*/
+load_val(expr, rlval)
+       register struct expr *expr; /* expression containing the value  */
+       int rlval;              /* generate either LVAL or RVAL         */
+{
+       register struct type *tp = expr->ex_type;
+       int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
+       arith size = tp->tp_size;
+       int tpalign = tp->tp_align;
+       int al_on_word;
+       register int inword, indword;
+       register arith val = expr->VL_VALUE;
+
+       if (expr->VL_CLASS == Const) {
+               if (rvalue) { /* absolute addressing */
+                       load_cst(val, pointer_size);
+                       load_block(size, tpalign);
+               }
+               else    /* integer, unsigned, long, enum etc    */
+                       load_cst(val, size);
+               return;
+       }
+       if (rvalue) {
+               al_on_word = (tpalign % word_align == 0);
+               if (!(inword = (size == word_size && al_on_word)))
+                       indword = (size == dword_size && al_on_word);
+       }
+       if (expr->VL_CLASS == Label) {
+               if (rvalue) {
+                       if (inword)
+                               C_loe_dlb(expr->VL_LBL, val);
+                       else
+                       if (indword)
+                               C_lde_dlb(expr->VL_LBL, val);
+                       else {
+                               C_lae_dlb(expr->VL_LBL, val);
+                               load_block(size, tpalign);
+                       }
+
+               }
+               else {
+                       C_lae_dlb(expr->VL_LBL, (arith)0);
+                       C_adp(val);
+               }
+       }
+       else {
+               register struct idf *id = expr->VL_IDF;
+               register struct def *df = id->id_def;
+
+               ASSERT(ISNAME(expr));
+               if (df->df_type->tp_fund == FUNCTION) {
+                       /*      the previous statement tried to catch a function
+                               identifier, which may be cast to a pointer to a
+                               function.
+                               ASSERT(!(rvalue)); ???
+                       */
+                       C_lpi(id->id_text);
+               }
+               else
+               if (df->df_level == L_GLOBAL) {
+                       if (rvalue) {
+                               if (inword)
+                                       C_loe_dnam(id->id_text, val);
+                               else
+                               if (indword)
+                                       C_lde_dnam(id->id_text, val);
+                               else {
+                                       C_lae_dnam(id->id_text, val);
+                                       load_block(size, tpalign);
+                               }
+                       }
+                       else {
+                               C_lae_dnam(id->id_text, (arith)0);
+                               C_adp(val);
+                       }
+               }
+               else {
+                       ASSERT(df->df_sc != STATIC);
+                       if (rvalue) {
+                               if (inword || indword)
+                                       LoadLocal(df->df_address + val, size);
+                               else {
+                                       AddrLocal(df->df_address + val);
+                                       load_block(size, tpalign);
+                               }
+                       }
+                       else {
+                               AddrLocal(df->df_address);
+                               C_adp(val);
+                       }
+               }
+       }
+}
+
+load_cst(val, siz)
+       arith val, siz;
+{
+       if (siz <= word_size)
+               C_loc(val);
+       else
+       if (siz == dword_size)
+               C_ldc(val);
+       else {
+               label datlab;
+
+               C_df_dlb(datlab = data_label());
+               C_rom_icon(long2str((long)val, 10), siz);
+               C_lae_dlb(datlab, (arith)0);
+               C_loi(siz);
+       }
+}
+
+#endif LINT
+
diff --git a/lang/cem/cemcom.ansi/expr.c b/lang/cem/cemcom.ansi/expr.c
new file mode 100644 (file)
index 0000000..3e26e16
--- /dev/null
@@ -0,0 +1,536 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* EXPRESSION TREE HANDLING */
+
+#include       "lint.h"
+#include       "nofloat.h"
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "idf.h"
+#include       "arith.h"
+#include       "def.h"
+#include       "type.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "decspecs.h"
+#include       "declar.h"
+#include       "sizes.h"
+#include       "level.h"
+#include       "noRoption.h"
+
+extern char *symbol2str();
+extern char options[];
+
+int
+rank_of(oper)
+       int oper;
+{
+       /*      The rank of the operator oper is returned.
+       */
+       switch (oper)   {
+       default:
+               return 0;                       /* INT2INT etc. */
+       case '[':
+       case '(':
+       case '.':
+       case ARROW:
+       case PARCOMMA:
+               return 1;
+       case '!':
+       case PLUSPLUS:
+       case MINMIN:
+       case CAST:
+       case SIZEOF:
+               return 2;                       /* monadic */
+       case '*':
+       case '/':
+       case '%':
+               return 3;
+       case '+':
+       case '-':
+               return 4;
+       case LEFT:
+       case RIGHT:
+               return 5;
+       case '<':
+       case '>':
+       case LESSEQ:
+       case GREATEREQ:
+               return 6;
+       case EQUAL:
+       case NOTEQUAL:
+               return 7;
+       case '&':
+               return 8;
+       case '^':
+               return 9;
+       case '|':
+               return 10;
+       case AND:
+               return 11;
+       case OR:
+               return 12;
+       case '?':
+       case ':':
+               return 13;
+       case '=':
+       case PLUSAB:
+       case MINAB:
+       case TIMESAB:
+       case DIVAB:
+       case MODAB:
+       case RIGHTAB:
+       case LEFTAB:
+       case ANDAB:
+       case XORAB:
+       case ORAB:
+               return 14;
+       case ',':
+               return 15;
+       }
+       /*NOTREACHED*/
+}
+
+#ifndef NOROPTION
+int
+rank_of_expression(ex)
+       register struct expr *ex;
+{
+       /*      Returns the rank of the top node in the expression.
+       */
+       if (!ex || (ex->ex_flags & EX_PARENS) || ex->ex_class != Oper)
+               return 0;
+       return rank_of(ex->OP_OPER);
+}
+
+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.
+       */
+       if (options['R'] && rank_of_expression(expr) >= rank_of(oper))
+               expr_warning(expr, "%s %s is ungrammatical",
+                       symbol2str(expr->OP_OPER), pos_descr);
+}
+#endif
+
+dot2expr(expp)
+       struct expr **expp;
+{
+       /*      The token in dot is converted into an expression, a
+               pointer to which is stored in *expp.
+       */
+       register struct expr *ex = new_expr();
+
+       *expp = ex;
+       ex->ex_file = dot.tk_file;
+       ex->ex_line = dot.tk_line;
+       switch (DOT)    {
+       case IDENTIFIER:
+               idf2expr(ex);
+               break;
+       case INTEGER:
+               int2expr(ex);
+               break;
+#ifndef NOFLOAT
+       case FLOATING:
+               float2expr(ex);
+               break;
+#endif NOFLOAT
+       default:
+               crash("bad conversion to expression");
+               /*NOTREACHED*/
+       }
+}
+
+idf2expr(expr)
+       register struct expr *expr;
+{
+       /*      Dot contains an identifier which is turned into an
+               expression.
+               Note that this constitutes an applied occurrence of
+               the identifier.
+       */
+       register struct idf *idf = dot.tk_idf;  /* != 0*/
+       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 (!is_anon_idf(idf))
+                               error("%s undefined", idf->id_text);
+                       /* declare idf anyway */
+                       add_def(idf, 0, error_type, level);
+               }
+               def = idf->id_def;
+       }
+       /* now def != 0 */
+       if (def->df_type->tp_fund == LABEL) {
+               expr_error(expr, "illegal use of label %s", idf->id_text);
+               expr->ex_type = error_type;
+       }
+       else {
+#ifndef        LINT
+               def->df_used = 1;
+#endif LINT
+               expr->ex_type = def->df_type;
+               if (expr->ex_type == error_type)
+                       expr->ex_flags |= EX_ERROR;
+       }
+       expr->ex_lvalue =
+               (       def->df_type->tp_fund == FUNCTION ||
+                       def->df_type->tp_fund == ARRAY ||
+                       def->df_sc == ENUM
+               ) ? 0 : 1;
+       if (def->df_type->tp_typequal & TQ_CONST)
+               expr->ex_flags |= EX_READONLY;
+       if (def->df_type->tp_typequal & TQ_VOLATILE)
+               expr->ex_flags |= EX_VOLATILE;
+       expr->ex_class = Value;
+       if (def->df_sc == ENUM) {
+               expr->VL_CLASS = Const;
+               expr->VL_VALUE = def->df_address;
+       }
+#ifndef        LINT
+       else
+       if (def->df_sc == STATIC && def->df_level >= L_LOCAL) {
+               expr->VL_CLASS = Label;
+               expr->VL_LBL = def->df_address;
+               expr->VL_VALUE = (arith)0;
+       }
+#endif LINT
+       else {
+               expr->VL_CLASS = Name;
+               expr->VL_IDF = idf;
+               expr->VL_VALUE = (arith)0;
+       }
+}
+
+string2expr(expp, typ, str, len)
+       register struct expr **expp;
+       int typ, len;
+       char *str;
+{
+       /*      The string in the argument is converted into an expression,
+               a pointer to which is stored in *expp.
+       */
+       register struct expr *ex = new_expr();
+
+       *expp = ex;
+       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_flags |= EX_READONLY;
+       ex->ex_lvalue = 0;
+       ex->ex_class = String;
+       ex->SG_VALUE = str;
+       ex->SG_LEN = len;
+       ex->SG_DATLAB = 0;
+}
+
+int2expr(expr)
+       struct expr *expr;
+{
+       /*      Dot contains an integer constant which is turned
+               into an expression.
+       */
+       fill_int_expr(expr, dot.tk_ival, dot.tk_fund);
+}
+
+#ifndef NOFLOAT
+float2expr(expr)
+       register struct expr *expr;
+{
+       /*      Dot contains a floating point constant which is turned
+               into an expression.
+       */
+       register int fund;
+
+       fund = dot.tk_fund;
+       switch (fund) {
+       case FLOAT:
+               expr->ex_type = float_type;
+               break;
+       case DOUBLE:
+               expr->ex_type = double_type;
+               break;
+       case LNGDBL:
+               expr->ex_type = lngdbl_type;
+               break;
+       default:
+               crash("(float2expr) bad fund %s\n", symbol2str(fund));
+       }
+       expr->ex_class = Float;
+       expr->FL_VALUE = dot.tk_fval;
+       expr->FL_DATLAB = 0;
+}
+#endif NOFLOAT
+
+struct expr*
+intexpr(ivalue, fund)
+       arith ivalue;
+       int fund;
+{
+       /*      The value ivalue is turned into an integer expression of
+               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);
+       return expr;
+}
+
+fill_int_expr(ex, ivalue, fund)
+       register struct expr *ex;
+       arith ivalue;
+       int fund;
+{
+       /*      Details derived from ivalue and fund are put into the
+               constant integer expression ex.
+       */
+       switch (fund) {
+       case INT:
+               ex->ex_type = int_type;
+               break;
+       case INTEGER:
+               if (ivalue >= 0 && ivalue <= max_int) {
+                       ex->ex_type = int_type;
+                       break;
+               }
+               /*FALL THROUGH*/
+       case LONG:
+               ex->ex_type = 
+                       (ivalue & (1L << (8*long_size - 1))) ? ulong_type
+                               : long_type;
+               break;
+       case ULONG:
+               ex->ex_type = ulong_type;
+               break;
+       case UNSIGNED:
+               /*      We cannot make a test like
+                               ivalue <= max_unsigned
+                       because, if
+                               sizeof(long) == int_size
+                       holds, max_unsigned may be a negative long in
+                       which case the comparison results in an unexpected
+                       answer.
+               */
+               ex->ex_type = 
+                       (ivalue & ~max_int) ?
+                         ( (ivalue & ~max_unsigned) ? 
+                             ( ivalue & (1L<<(8*long_size-1)) ?
+                                       ulong_type : long_type
+                             ) : uint_type
+                         ) : int_type;
+               break;
+       default:
+               crash("(intexpr) bad fund %s\n", symbol2str(fund));
+               /*NOTREACHED*/
+       }
+       ex->ex_class = Value;
+       ex->VL_CLASS = Const;
+       ex->VL_VALUE = ivalue;
+       cut_size(ex);
+}
+
+struct expr *
+new_oper(tp, e1, oper, e2)
+       struct type *tp;
+       register struct expr *e1, *e2;
+{
+       /*      A new expression is constructed which consists of the
+               operator oper which has e1 and e2 as operands; for a
+               monadic operator e1 == NILEXPR.
+               During the construction of the right recursive initialisation
+               tree it is possible for e2 to be NILEXPR.
+       */
+       register struct expr *expr = new_expr();
+       register struct oper *op;
+
+       if (e2) {
+               register struct expr *e = e2;
+               
+               while (e->ex_class == Oper && e->OP_LEFT)
+                       e = e->OP_LEFT;
+               expr->ex_file = e->ex_file;
+               expr->ex_line = e->ex_line;
+       }
+       else
+       if (e1) {
+               register struct expr *e = e1;
+               
+               while (e->ex_class == Oper && e->OP_RIGHT)
+                       e = e->OP_RIGHT;
+               expr->ex_file = e->ex_file;
+               expr->ex_line = e->ex_line;
+       }
+       else    {
+               expr->ex_file = dot.tk_file;
+               expr->ex_line = dot.tk_line;
+       }
+
+       expr->ex_type = tp;
+       expr->ex_class = Oper;
+       /* combine depths and flags of both expressions */
+       if (e2) {
+               int e1_depth = e1 ? e1->ex_depth : 0;
+               int e1_flags = e1 ? e1->ex_flags : 0;
+               
+               expr->ex_depth =
+                       (e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + 1;
+               expr->ex_flags = (e1_flags | e2->ex_flags) & ~EX_PARENS;
+       }
+       op = &expr->ex_object.ex_oper;
+       op->op_type = tp;
+       op->op_oper = oper;
+       op->op_left = e1;
+       op->op_right = e2;
+#ifdef LINT
+       lint_new_oper(expr);
+#endif LINT
+       return expr;
+}
+
+chk_cst_expr(expp)
+       register struct expr **expp;
+{
+       /*      The expression expr is checked for constancy.
+       
+               There are 6 places where constant expressions occur in C:
+               1.      after #if
+               2.      in a global initialization
+               3.      as size in an array declaration
+               4.      as value in an enum declaration
+               5.      as width in a bit field
+               6.      as case value in a switch
+               
+               The constant expression in a global initialization is
+               handled separately (by IVAL()).
+               
+               There are various disparate restrictions on each of
+               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");
+       }
+#endif NOROPTION
+       if (err)
+               erroneous2int(expp);
+}
+
+init_expression(eppp, expr)
+       register struct expr ***eppp, *expr;
+{
+       /*      The expression expr is added to the tree designated
+               indirectly by **eppp.
+               The natural form of a tree representing an
+               initial_value_list is right-recursive, ie. with the
+               left-most comma as main operator. The iterative grammar in
+               expression.g, however, tends to produce a left-recursive
+               tree, ie. one with the right-most comma as its main
+               operator.
+               To produce a right-recursive tree from the iterative
+               grammar, we keep track of the address of the pointer where
+               the next expression must be hooked in.
+       */
+       **eppp = new_oper(void_type, expr, INITCOMMA, NILEXPR);
+       *eppp = &(**eppp)->OP_RIGHT;
+}
+
+int
+is_ld_cst(expr)
+       register struct expr *expr;
+{
+       /*      An expression is a `load-time constant' if it is of the form
+               <idf> +/- <integral> or <integral>.
+       */
+#ifdef LINT
+       if (expr->ex_class == String)
+               return 1;
+#endif LINT
+       return expr->ex_lvalue == 0 && expr->ex_class == Value;
+}
+
+int
+is_cp_cst(expr)
+       register struct expr *expr;
+{
+       /*      An expression is a `compile-time constant' if it is a
+               load-time constant, and the idf is not there.
+       */
+       return is_ld_cst(expr) && expr->VL_CLASS == Const;
+}
+
+#ifndef NOFLOAT
+int
+is_fp_cst(expr)
+       register struct expr *expr;
+{
+       /*      An expression is a `floating-point constant' if it consists
+               of the float only.
+       */
+       return expr->ex_class == Float;
+}
+#endif NOFLOAT
+
+free_expression(expr)
+       register struct expr *expr;
+{
+       /*      The expression expr is freed recursively.
+       */
+       if (expr) {
+               if (expr->ex_class == Oper)     {
+                       free_expression(expr->OP_LEFT);
+                       free_expression(expr->OP_RIGHT);
+               }
+               free_expr(expr);
+       }
+}
diff --git a/lang/cem/cemcom.ansi/expr.str b/lang/cem/cemcom.ansi/expr.str
new file mode 100644 (file)
index 0000000..16648e0
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* EXPRESSION DESCRIPTOR */
+
+/*     What we want to define is the struct expr, but since it contains
+       a union of various goodies, we define them first; so be patient.
+*/
+
+#include       "nofloat.h"
+
+/* classes of value */
+#define Const  1
+#define Name   2
+#define Label  3
+
+struct value   {
+       int vl_class;           /* Const, Name or Label */
+       arith vl_value;         /* constant value or offset */
+       union {
+               struct idf *vl_idf;     /* external name */
+               label vl_lbl;           /* compiler-generated label */
+       } vl_data;
+};
+
+struct string  {
+       char *sg_value;         /* row of bytes repr. the constant */
+       int sg_len;             /* length of the row */
+       label sg_datlab;        /* global data-label                    */
+};
+
+#ifndef NOFLOAT
+struct floating        {
+       char *fl_value;         /* pointer to string repr. the fp const. */
+       label fl_datlab;        /* global data_label    */
+};
+#endif NOFLOAT
+
+struct oper    {
+       struct type *op_type;   /* resulting type of the operation      */
+       struct expr *op_left;
+       int op_oper;                    /* the symbol of the operator   */
+       struct expr *op_right;
+};
+
+/* 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 */
+
+struct expr    {
+       struct expr *next;
+       char *ex_file;          /* the file it (probably) comes from */
+       unsigned int ex_line;   /* the line it (probably) comes from */
+       struct type *ex_type;
+       char ex_lvalue;
+       short ex_flags;
+       int ex_class;
+       int ex_depth;
+       union   {
+               struct value ex_value;
+               struct string ex_string;
+#ifndef NOFLOAT
+               struct floating ex_float;
+#endif NOFLOAT
+               struct oper ex_oper;
+       } ex_object;
+};
+
+/* some abbreviated selections */
+#define EX_VALUE       ex_object.ex_value
+#define VL_CLASS       EX_VALUE.vl_class
+#define        VL_VALUE        EX_VALUE.vl_value
+#define        VL_IDF          EX_VALUE.vl_data.vl_idf
+#define        VL_LBL          EX_VALUE.vl_data.vl_lbl
+#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_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
+#define        OP_RIGHT        ex_object.ex_oper.op_right
+
+/*     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        NILEXPR         ((struct expr *)0)
+
+/* some useful tests */
+#define        ISNAME(e)       ((e)->ex_class == Value && (e)->VL_CLASS == Name)
+#define        ISCOMMA(e)      ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
+
+extern struct expr *intexpr(), *new_oper();
+
+/* ALLOCDEF "expr" 20 */
+
diff --git a/lang/cem/cemcom.ansi/expression.g b/lang/cem/cemcom.ansi/expression.g
new file mode 100644 (file)
index 0000000..e341ed6
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     EXPRESSION SYNTAX PARSER        */
+
+{
+#include       <alloc.h>
+#include       "lint.h"
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "type.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "code.h"
+#include       "noRoption.h"
+
+extern struct expr *intexpr();
+}
+
+/* 7.1 */
+primary(register struct expr **expp;) :
+       IDENTIFIER
+       {dot2expr(expp);}
+|
+       constant(expp)
+|
+       string(expp)
+|
+       '(' expression(expp) ')'
+       {(*expp)->ex_flags |= EX_PARENS;}
+;
+
+
+/*     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;
+               register int fund;
+       }
+:
+       STRING
+       {       str = dot.tk_bts;
+               len = dot.tk_len;
+               fund = dot.tk_fund;
+       }
+       [
+               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.
+                       */
+                       if (dot.tk_fund != fund)
+                               warning("illegal pasting of string literals");
+                       str = Srealloc(str, (unsigned) (--len + dot.tk_len));
+                       for (i = 0; i < dot.tk_len; i++)
+                               str[len++] = dot.tk_bts[i];
+               }
+       ]*
+       {string2expr(expp, STRING, str, len);}
+;
+
+secundary(register struct expr **expp;) :
+       primary(expp)
+       [
+               index_pack(expp)
+       |
+               parameter_pack(expp)
+       |
+               selection(expp)
+       ]*
+;
+
+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);}
+;
+
+parameter_list(struct expr **expp;)
+       {struct expr *e1 = 0;}
+:
+       assignment_expression(expp)
+       {any2opnd(expp, PARCOMMA);}
+       [       ','
+               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;
+
+unary(register struct expr **expp;)
+       {struct type *tp; int oper;}
+:
+%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
+       cast(&tp) unary(expp)
+       {       ch7cast(expp, CAST, tp);
+               (*expp)->ex_flags |= EX_CAST;
+       }
+|
+       postfixed(expp)
+|
+       unop(&oper) unary(expp)
+       {ch7mon(oper, expp);}
+|
+       size_of(expp)
+;
+
+size_of(register struct expr **expp;)
+       {struct type *tp;}
+:
+       SIZEOF
+       [%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER)
+               cast(&tp)
+               {
+                       *expp = intexpr(size_of_type(tp, "type"), INT);
+                       (*expp)->ex_flags |= EX_SIZEOF;
+               }
+       |
+               unary(expp)
+               {ch7mon(SIZEOF, expp);}
+       ]
+;
+
+/* 7.3-7.12 */
+/*     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:
+               binary_expression(int maxrank;)
+                       {int oper;}
+               :
+                       binary_expression(maxrank - 1)
+                       [%if (rank_of(DOT) <= maxrank)
+                               binop(&oper)
+                               binary_expression(rank_of(oper)-1)
+                       ]?
+               ;
+       except that some call of 'unary' is necessary, depending on the
+       grammar.
+       
+       This simple view is marred by three complications:
+       1.      Level 15 (comma operator) is not allowed in many
+               contexts and is different.
+       2.      Level 13 (conditional operator) is a ternary operator,
+               which does not fit this scheme at all.
+       3.      Level 14 (assignment operators) group right-to-left, as
+               opposed to 2-12, which group left-to-right (or are
+               immaterial).
+       4.      The operators in level 14 start with operators in levels
+               2-13 (RM 7.14: The two parts of a compound assignment
+               operator are separate tokens.)  This causes LL1 problems.
+       This forces us to have four rules:
+               binary_expression       for level 2-12
+               conditional_expression  for level 13
+               assignment_expression   for level 14 and
+               expression              for the most general expression
+*/
+
+binary_expression(int maxrank; struct expr **expp;)
+       {int oper; 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
+               */
+               binop(&oper)
+               binary_expression(rank_of(oper)-1, &e1)
+               {
+                       ch7bin(expp, oper, e1);
+               }
+       ]*
+;
+
+/* 7.13 */
+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;}
+:
+       /* allow all binary operators */
+       binary_expression(rank_of('?') - 1, expp)
+       [       '?'
+               expression(&e1)
+               {
+#ifndef NOROPTION
+                       check_conditional(e1, '?', "between ? and :");
+#endif
+               }
+               ':'
+               assignment_expression(&e2)
+               {       
+#ifndef NOROPTION
+                       check_conditional(e2, '=', "after :");
+#endif
+                       ch7bin(&e1, ':', e2);
+                       opnd2test(expp, '?');
+                       ch7bin(expp, '?', e1);
+               }
+       ]?
+;
+
+/* 7.14 */
+assignment_expression(struct expr **expp;)
+       {
+               int oper;
+               struct expr *e1 = 0;
+       }
+:
+       conditional_expression(expp)
+       [%prefer        /* (rank_of(DOT) <= maxrank) for any asgnop */
+               asgnop(&oper)
+               assignment_expression(&e1)
+               {ch7asgn(expp, oper, e1);}
+       |
+               empty           /* LLgen artefact ??? */
+       ]
+;
+
+/* 7.15 */
+expression(struct expr **expp;)
+       {struct expr *e1;}
+:
+       assignment_expression(expp)
+       [       ','
+               assignment_expression(&e1)
+               {
+                       ch7bin(expp, ',', e1);
+               }
+       ]*
+;
+
+unop(int *oper;) :
+       ['*' | '&' | '-' | '+' | '!' | '~' | PLUSPLUS | MINMIN]
+       {*oper = DOT;}
+;
+
+postop(int *oper;):
+       PLUSPLUS {*oper = POSTINCR;}
+|
+       MINMIN {*oper = POSTDECR;}
+;
+
+multop:
+       '*' | '/' | '%'
+;
+
+addop:
+       '+' | '-'
+;
+
+shiftop:
+       LEFT | RIGHT
+;
+
+relop:
+       '<' | '>' | LESSEQ | GREATEREQ
+;
+
+eqop:
+       EQUAL | NOTEQUAL
+;
+
+arithop:
+       multop | addop | shiftop
+|
+       '&' | '^' | '|'
+;
+
+binop(int *oper;) :
+       [ arithop | relop | eqop | AND | OR ]
+       {*oper = DOT;}
+;
+
+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 ]
+       { *oper = DOT; }
+
+;
+
+constant(struct expr **expp;) :
+[
+       INTEGER
+|
+       FLOATING
+]      {dot2expr(expp);}
+;
+
+/* 15 */
+constant_expression (struct expr **expp;) :
+       assignment_expression(expp)
+       {chk_cst_expr(expp);}
+;
+
+identifier(struct idf **idfp;) :
+[
+       IDENTIFIER
+|
+       TYPE_IDENTIFIER
+]
+       {
+               *idfp = dot.tk_idf;
+       }
+;
diff --git a/lang/cem/cemcom.ansi/field.c b/lang/cem/cemcom.ansi/field.c
new file mode 100644 (file)
index 0000000..3b94431
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     BITFIELD EXPRESSION EVALUATOR   */
+
+#include       "lint.h"
+#ifndef        LINT
+
+#include       "nobitfield.h"
+
+#ifndef NOBITFIELD
+#include       <em.h>
+#include       <em_reg.h>
+#include       "debug.h"
+#include       "arith.h"
+#include       "type.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "code.h"
+#include       "assert.h"
+#include       "expr.h"
+#include       "sizes.h"
+#include       "align.h"
+#include       "Lpars.h"
+#include       "field.h"
+
+arith NewLocal();              /* util.c       */
+char *symbol2str();            /* symbol2str.c */
+
+/*     Eval_field() evaluates expressions involving bit fields.
+       The various instructions are not yet optimised in the expression
+       tree and are therefore dealt with in this function.
+       The actions taken at any operation are described clearly by the
+       code for this actions.
+       Notes
+       [1]     the bitfields are packed in target machine integers!
+       [2]     op is either an assignment operator or an increment/
+               decrement operator
+       [3]     atype: the type in which the bitfield arithmetic is done;
+               and in which bitfields are stored!
+*/
+eval_field(expr, code)
+       struct expr *expr;
+       int code;
+{
+       int op = expr->OP_OPER;
+       register struct expr *leftop = expr->OP_LEFT;
+       register struct expr *rightop = expr->OP_RIGHT;
+       register struct field *fd = leftop->ex_type->tp_field;
+       struct type *tp = leftop->ex_type->tp_up;
+       arith tmpvar;
+       struct type *atype = tp->tp_unsigned ? uword_type : word_type;
+       arith asize = atype->tp_size;
+
+       /* First some assertions to be sure that the rest is legal */
+       ASSERT(asize == word_size);     /* make sure that C_loc() is legal */
+       ASSERT(leftop->ex_type->tp_fund == FIELD);
+       leftop->ex_type = atype;        /* this is cheating but it works... */
+       if (op == '=') {
+               /* F = E: f = ((E & mask)<<shift) | (~(mask<<shift) & f) */
+               ASSERT(tp == rightop->ex_type);
+               EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
+               conversion(tp, atype);
+               C_loc(fd->fd_mask);
+               C_and(asize);
+               if (code == TRUE)
+                       C_dup(asize);
+               C_loc((arith)fd->fd_shift);
+               if (atype->tp_unsigned)
+                       C_slu(asize);
+               else
+                       C_sli(asize);
+               C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize))));
+               if (leftop->ex_depth == 0)      {       /* simple case  */
+                       load_val(leftop, RVAL);
+                       C_and(asize);
+                       C_ior(asize);
+                       store_val(&(leftop->EX_VALUE), atype);
+               }
+               else    {                       /* complex case */
+                       tmpvar = NewLocal(pointer_size, pointer_align, 
+                                         reg_pointer, 0);
+                       EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
+                       C_dup(pointer_size);
+                       StoreLocal(tmpvar, pointer_size);
+                       C_loi(asize);
+                       C_and(asize);
+                       C_ior(asize);
+                       LoadLocal(tmpvar, pointer_size);
+                       C_sti(asize);
+                       FreeLocal(tmpvar);
+               }
+       }
+       else {          /* treat ++F as F += 1 and --F as F -= 1        */
+               /*      F op= e: f = (((((f>>shift)&mask) op e)&mask)<<shift)|
+                                       (f&~(mask<<shift))
+               */
+               if (leftop->ex_depth == 0)      /* simple case  */
+                       load_val(leftop, RVAL);
+               else    {                       /* complex case */
+                       tmpvar = NewLocal(pointer_size, pointer_align, 
+                                         reg_pointer, 0);
+                       EVAL(leftop, LVAL, TRUE, NO_LABEL, NO_LABEL);
+                       C_dup(pointer_size);
+                       StoreLocal(tmpvar, pointer_size);
+                       C_loi(asize);
+               }
+               if (atype->tp_unsigned) {
+                       C_loc((arith)fd->fd_shift);
+                       C_sru(asize);
+                       C_loc(fd->fd_mask);
+                       C_and(asize);
+               }
+               else {
+                       arith bits_in_type = asize * 8;
+                       C_loc(bits_in_type - (fd->fd_width + fd->fd_shift));
+                       C_sli(asize);
+                       C_loc(bits_in_type - fd->fd_width);
+                       C_sri(asize);
+               }
+               if (code == TRUE && (op == POSTINCR || op == POSTDECR))
+                       C_dup(asize);
+               conversion(atype, rightop->ex_type);
+               EVAL(rightop, RVAL, TRUE, NO_LABEL, NO_LABEL);
+               /* the 'op' operation: */
+               if (op == PLUSPLUS || op == POSTINCR)
+                       assop(rightop->ex_type, PLUSAB);
+               else
+               if (op == MINMIN || op == POSTDECR)
+                       assop(rightop->ex_type, MINAB);
+               else
+                       assop(rightop->ex_type, op);
+               conversion(rightop->ex_type, atype);
+               C_loc(fd->fd_mask);
+               C_and(asize);
+               if (code == TRUE && op != POSTINCR && op != POSTDECR)
+                       C_dup(asize);
+               C_loc((arith)fd->fd_shift);
+               if (atype->tp_unsigned)
+                       C_slu(asize);
+               else
+                       C_sli(asize);
+               C_loc(~((fd->fd_mask << fd->fd_shift) | (~0 << (8 * asize))));
+               if (leftop->ex_depth == 0)      {
+                       load_val(leftop, RVAL);
+                       C_and(asize);
+                       C_ior(asize);
+                       store_val(&(leftop->EX_VALUE), atype);
+               }
+               else    {
+                       LoadLocal(tmpvar, pointer_size);
+                       C_loi(asize);
+                       C_and(asize);
+                       C_ior(asize);
+                       LoadLocal(tmpvar, pointer_size);
+                       C_sti(asize);
+                       FreeLocal(tmpvar);
+               }
+       }
+       if (code == TRUE) {
+               /*      Take care that the effective value stored in
+                       the bit field (i.e. the value that is got on
+                       retrieval) is on top of stack.
+               */
+               if (atype->tp_unsigned == 0) {  /* sign extension */
+                       register arith shift = asize * 8 - fd->fd_width;
+
+                       C_loc(shift);
+                       C_sli(asize);
+                       C_loc(shift);
+                       C_sri(asize);
+               }
+               conversion(atype, expr->ex_type);
+       }
+}
+#endif NOBITFIELD
+
+#endif LINT
+
diff --git a/lang/cem/cemcom.ansi/field.str b/lang/cem/cemcom.ansi/field.str
new file mode 100644 (file)
index 0000000..520c9ab
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* FIELD DESCRIPTOR */
+
+struct field   {       /* for field specifiers */
+       struct field *next;
+       arith fd_mask;
+       int fd_shift;
+       int fd_width;
+       struct sdef *fd_sdef;   /* upward pointer       */
+};
+
+/* ALLOCDEF "field" 50 */
diff --git a/lang/cem/cemcom.ansi/file_info.h b/lang/cem/cemcom.ansi/file_info.h
new file mode 100644 (file)
index 0000000..ef2892b
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* F I L E   I N F O R M A T I O N   S T R U C T U R E */
+
+struct file_info {
+       unsigned int    fil_lino;
+       int             fil_nestlow;
+       char            *fil_name;
+       char            *fil_wdir;
+};
+
+#define nestlow                finfo.fil_nestlow
+#define LineNumber     finfo.fil_lino
+#define FileName       finfo.fil_name
+#define WorkingDir     finfo.fil_wdir
+
+extern struct file_info finfo; /* input.c */
diff --git a/lang/cem/cemcom.ansi/idf.c b/lang/cem/cemcom.ansi/idf.c
new file mode 100644 (file)
index 0000000..49537a8
--- /dev/null
@@ -0,0 +1,736 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     IDENTIFIER  FIDDLING & SYMBOL TABLE HANDLING    */
+
+#include       "lint.h"
+#include       <em_reg.h>
+#include       "nofloat.h"
+#include       "debug.h"
+#include       "idfsize.h"
+#include       "botch_free.h"
+#include       "nopp.h"
+#include       "nparams.h"
+#include       <alloc.h>
+#include       "arith.h"
+#include       "align.h"
+#include       "LLlex.h"
+#include       "level.h"
+#include       "stack.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "def.h"
+#include       "type.h"
+#include       "proto.h"
+#include       "struct.h"
+#include       "declar.h"
+#include       "decspecs.h"
+#include       "sizes.h"
+#include       "Lpars.h"
+#include       "assert.h"
+#include       "specials.h"    /* registration of special identifiers  */
+#include       "noRoption.h"
+
+int idfsize = IDFSIZE;
+extern char options[];
+extern arith NewLocal();
+
+char sp_occurred[SP_TOTAL+1];  /* indicate occurrence of special id    */
+
+struct idf *idf_hashtable[HASHSIZE];
+       /*      All identifiers can in principle be reached through
+               idf_hashtable; idf_hashtable[hc] is the start of a chain of
+               idf's whose tags all hash to hc. Each idf is the start of
+               a chain of def's for that idf, sorted according to level,
+               with the most recent one on top.
+               Any identifier occurring on a level is entered into this
+               list, regardless of the nature of its declaration
+               (variable, selector, structure tag, etc.).
+       */
+
+struct idf *
+idf_hashed(tg, size, hc)
+       char *tg;
+       int size;               /* includes the '\0' character */
+       int hc;
+{
+       /*      The tag tg with length size and known hash value hc is
+               looked up in the identifier table; if not found, it is
+               entered. A pointer to it is returned.
+               The identifier has already been truncated to idfsize
+               characters.
+       */
+       register struct idf **hook = &idf_hashtable[hc], *notch;
+
+       while ((notch = *hook)) {
+               register char *s1 = tg;
+               register char *cp = notch->id_text;
+               register int cmp;
+
+               while (!(cmp = (*s1 - *cp++))) {
+                       if (*s1++ == '\0') {
+                               break;
+                       }
+               }
+
+               if (cmp < 0)
+                       break;
+               if (cmp == 0)   {
+                       /*      suppose that special identifiers, as
+                               "setjmp", are already inserted
+                       */
+                       sp_occurred[notch->id_special] = 1;
+                       return notch;
+               }
+               hook = &notch->next;
+       }
+       /* a new struct idf must be inserted at the hook */
+       notch = new_idf();
+       notch->next = *hook;
+       *hook = notch;          /* hooked in */
+       notch->id_text = Salloc(tg, (unsigned) size);
+#ifndef NOPP
+       notch->id_resmac = 0;
+#endif NOPP
+       return notch;
+}
+
+#ifdef DEBUG
+hash_stat()
+{
+       if (options['h'])       {
+               register int i;
+               
+               print("Hash table tally:\n");
+               for (i = 0; i < HASHSIZE; i++)  {
+                       register struct idf *notch = idf_hashtable[i];
+                       int cnt = 0;
+       
+                       while (notch)   {
+                               cnt++;
+                               notch = notch->next;
+                       }
+                       print("%d %d\n", i, cnt);
+               }
+               print("End hash table tally\n");
+       }               
+}
+#endif DEBUG
+
+struct idf *
+str2idf(tg)
+       char tg[];
+{
+       /*      str2idf() returns an entry in the symbol table for the
+               identifier tg.  If necessary, an entry is created.
+               It is used where the text of the identifier is available
+               but its hash value is not; otherwise idf_hashed() is to
+               be used.
+       */
+       register char *cp = tg;
+       register int hash;
+       register int pos = -1;
+       register int ch;
+       char ntg[IDFSIZE + 1];
+       register char *ncp = ntg;
+
+       hash = STARTHASH();
+       while (++pos < idfsize && (ch = *cp++)) {
+               *ncp++ = ch;
+               hash = ENHASH(hash, ch, pos);
+       }
+       hash = STOPHASH(hash);
+       *ncp++ = '\0';
+       return idf_hashed(ntg, ncp - ntg, hash);
+}
+
+struct idf *
+gen_idf()
+{
+       /*      A new idf is created out of nowhere, to serve as an
+               anonymous name.
+       */
+       static int name_cnt;
+       char buff[100];
+
+       sprint(buff, "#%d in %s, line %u",
+                       ++name_cnt, dot.tk_file, dot.tk_line);
+       return str2idf(buff);
+}
+
+int
+is_anon_idf(idf)
+       struct idf *idf;
+{
+       return idf->id_text[0] == '#';
+}
+
+declare_idf(ds, dc, lvl)
+       struct decspecs *ds;
+       struct declarator *dc;
+{
+       /*      The identifier inside dc is declared on the level lvl, with
+               properties deduced from the decspecs ds and the declarator
+               dc.
+               The level is given explicitly to be able to insert, e.g.,
+               labels on the outermost level inside the function.
+               This routine implements the rich semantics of C
+               declarations.
+       */
+       register struct idf *idf = dc->dc_idf;
+       register int sc = ds->ds_sc;
+               /*      This local copy is essential:
+                               char b(), c;
+                       makes b GLOBAL and c AUTO.
+               */
+       register struct def *def = idf->id_def;         /* may be NULL */
+       register struct type *type;
+       struct stack_level *stl = stack_level_of(lvl);
+       char formal_array = 0;
+       
+       /* determine the present type */
+       if (ds->ds_type == 0)   {
+               /*      at the L_FORMAL1 level there is no type specified yet
+               */
+               ASSERT(lvl == L_FORMAL1);
+               type = int_type;        /* may change at L_FORMAL2 */
+       }
+       else    {
+               /* combine the decspecs and the declarator into one type */
+               type = declare_type(ds->ds_type, dc);
+               if (type->tp_size <= (arith)0 &&
+                   actual_declaration(sc, type))       {
+                       if (type->tp_size == (arith) -1) {
+                               /* the type is not yet known,
+                                  but it has to be:
+                               */
+                               extern char *symbol2str();
+                               error("unknown %s-type",
+                                       symbol2str(type->tp_fund));
+                       }
+                       else if (type->tp_fund != LABEL) {
+                               /* CJ */
+                               warning("%s has size 0", idf->id_text);
+                       }
+               }
+       }
+
+       /* some additional work for formal definitions */
+       if (lvl == L_FORMAL2)   {
+               switch (type->tp_fund)  {
+               case FUNCTION:
+                       warning("%s is a function; cannot be formal",
+                               idf->id_text);
+                       type = construct_type(POINTER, type, 0, (arith)0,
+                                             NO_PROTO);
+                       break;
+               case ARRAY:     /* RM 10.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 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.
+                       */
+                       break;
+               }
+       }
+       /*      The tests on types, postponed from do_decspecs(), can now
+               be performed.
+       */
+       /* 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;
+               }
+       }
+       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
+
+#ifdef LINT
+       if (    def && def->df_level < lvl
+       &&      !(      lvl == L_FORMAL2
+               ||      def->df_level == L_UNIVERSAL
+               ||      sc == GLOBAL
+               ||      sc == EXTERN
+               )
+       ) {
+               /*      there is already a definition for this non-extern name
+                       on a more global level
+               */
+               warning("%s is already defined as a %s",
+                       idf->id_text,
+                       def->df_level == L_GLOBAL ? "global" :
+                       def->df_level == L_FORMAL2 ? "formal" :
+                               "more global local"
+               );
+       }
+#endif LINT
+
+       if (def && 
+           ( def->df_level == lvl ||
+             ( lvl != L_GLOBAL && def->df_level > lvl )
+           )
+          )    {
+               /*      There is already a declaration for idf on this
+                       level, or even more inside.
+                       The rules differ for different levels.
+               */
+               switch (lvl)    {
+               case L_GLOBAL:
+                       global_redecl(idf, sc, type);
+                       def->df_file = idf->id_file;
+                       def->df_line = idf->id_line;
+                       break;
+               case L_FORMAL1: /* formal declaration */
+                       error("formal %s redeclared", idf->id_text);
+                       break;
+               case L_FORMAL2: /* formal definition */
+               default:        /* local */
+                       error("%s redeclared", idf->id_text);
+                       break;
+               }
+       }
+       else    /* the idf is unknown on this level */
+       if (lvl == L_FORMAL2 && sc != ENUM && good_formal(def, idf))    {
+               /* formal declaration, update only */
+               def->df_type = type;
+               def->df_formal_array = formal_array;
+               def->df_sc = sc;
+               def->df_level = L_FORMAL2;      /* CJ */
+               def->df_file = idf->id_file;
+               def->df_line = idf->id_line;
+       }
+       else
+       if (    lvl >= L_LOCAL &&
+               (type->tp_fund == FUNCTION || sc == EXTERN)
+       )       {
+               /*      extern declaration inside function is treated the
+                       same way as global extern declaration
+               */
+#ifndef NOROPTION
+               if (    options['R'] &&
+                       (sc == STATIC && type->tp_fund == FUNCTION)
+               )
+                       if (!is_anon_idf(idf))
+                               warning("non-global static function %s",
+                                       idf->id_text);
+#endif
+               declare_idf(ds, dc, L_GLOBAL);
+       }
+       else    { /* fill in the def block */
+               register struct def *newdef = new_def();
+
+               newdef->next = def;
+               newdef->df_level = lvl;
+               newdef->df_type = type;
+               newdef->df_sc = sc;
+               newdef->df_file = idf->id_file;
+               newdef->df_line = idf->id_line;
+#ifdef LINT
+               newdef->df_set = (type->tp_fund == ARRAY);
+               newdef->df_firstbrace = 0;
+#endif LINT
+
+               /* link it into the name list in the proper place */
+               idf->id_def = newdef;
+               update_ahead(idf);
+               stack_idf(idf, stl);
+               /*      We now calculate the address.
+                       Globals have names and don't get addresses, they
+                       get numbers instead (through data_label()).
+                       Formals are handled by declare_formals().
+                       So here we hand out local addresses only.
+               */
+               if (lvl >= L_LOCAL)     {
+                       ASSERT(sc);
+                       switch (sc)     {
+                       case REGISTER:
+                       case AUTO:
+                               if (type->tp_size == (arith)-1) {
+                                       error("size of local %s unknown",
+                                               idf->id_text);
+                               /** type = idf->id_def->df_type = int_type; **/
+                               }
+                               newdef->df_address =
+                                       NewLocal(type->tp_size,
+                                                type->tp_align,
+                                                regtype(type),
+                                                sc);
+                               break;
+                       case STATIC:
+                               newdef->df_address = (arith) data_label();
+                               break;
+                       }
+               }
+       }
+}
+
+actual_declaration(sc, tp)
+       int sc;
+       struct type *tp;
+{
+       /*      An actual_declaration needs space, right here and now.
+       */
+       register int fund = tp->tp_fund;
+       
+       if (sc == ENUM || sc == TYPEDEF) /* virtual declarations */
+               return 0;
+       if (fund == FUNCTION || fund == ARRAY)
+               /* allocation solved in other ways */
+               return 0;
+       /* to be allocated */
+       return 1;
+}
+
+global_redecl(idf, new_sc, tp)
+       register struct idf *idf;
+       struct type *tp;
+{
+       /*      A global identifier may be declared several times,
+               provided the declarations do not conflict; they might
+               conflict in type (or supplement each other in the case of
+               an array) or they might conflict or supplement each other
+               in storage class.
+       */
+       register struct def *def = idf->id_def;
+
+       if (!equal_type(tp, def->df_type))
+               error("redeclaration of %s with different type", idf->id_text);
+       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 [] */
+                       /* nothing new */
+               } else
+               if (def->df_type->tp_size < 0)  {       /* old decl has [] */
+                       def->df_type = tp;
+               }
+       }
+
+       /*      Now we may be able to update the storage class.
+               Clean out this mess as soon as we know all the possibilities
+               for new_sc.
+               For now we have:
+                       EXTERN:         we have seen the word "extern"
+                       GLOBAL:         the item was declared on the outer
+                                       level, without either "extern" or
+                                       "static".
+                       STATIC:         we have seen the word "static"
+                       IMPLICIT:       function declaration inferred from
+                                       call
+       */
+       if (new_sc == IMPLICIT)
+               return;                 /* no new information */
+       switch (def->df_sc)     {       /* the old storage class */
+       case EXTERN:
+               switch (new_sc) {       /* the new storage class */
+               case EXTERN:
+               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;
+                       break;
+               default:
+                       crash("bad storage class");
+                       /*NOTREACHED*/
+               }
+               break;
+       case GLOBAL:
+               switch (new_sc) {       /* the new storage class */
+               case EXTERN:
+                       def->df_sc = EXTERN;
+                       break;
+               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;
+                       }
+                       break;
+               default:
+                       crash("bad storage class");
+                       /*NOTREACHED*/
+               }
+               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:
+               case STATIC:
+                       if (def->df_type->tp_fund != FUNCTION)
+                               warning("%s was already static",
+                                       idf->id_text);
+                       break;
+               default:
+                       crash("bad storage class");
+                       /*NOTREACHED*/
+               }
+               break;
+       case IMPLICIT:
+               switch (new_sc) {       /* the new storage class */
+               case EXTERN:
+               case GLOBAL:
+                       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:
+                       crash("bad storage class");
+                       /*NOTREACHED*/
+               }
+               break;
+       case ENUM:
+       case TYPEDEF:
+               error("illegal redeclaration of %s", idf->id_text);
+               break;
+       default:
+               crash("bad storage class");
+               /*NOTREACHED*/
+       }
+}
+
+int
+good_formal(def, idf)
+       register struct def *def;
+       register struct idf *idf;
+{
+       /*      Succeeds if def is a proper L_FORMAL1 definition and
+               gives an error message otherwise.
+       */
+       if (!def || def->df_level != L_FORMAL1) { /* not in parameter list */
+               if (!is_anon_idf(idf))
+                       error("%s not in parameter list", idf->id_text);
+               return 0;
+       }
+       ASSERT(def->df_sc == FORMAL);   /* CJ */
+       return 1;
+}
+
+declare_params(dc)
+       register 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)
+       register struct idf *idf;
+{
+       /*      The topmost definition of idf is set to initialized.
+       */
+       register struct def *def = idf->id_def; /* the topmost */
+       
+       if (def->df_initialized)
+               error("multiple initialization of %s", idf->id_text);
+       if (def->df_sc == TYPEDEF)      {
+               warning("typedef cannot be initialized");
+               def->df_sc = EXTERN;            /* ??? *//* What else ? */
+       }
+       def->df_initialized = 1;
+}
+
+declare_parameter(idf)
+       struct idf *idf;
+{
+       /*      idf is declared as a formal.
+       */
+       add_def(idf, FORMAL, int_type, level);
+}
+
+declare_enum(tp, idf, l)
+       struct type *tp;
+       struct idf *idf;
+       arith l;
+{
+       /*      idf is declared as an enum constant with value l.
+       */
+       add_def(idf, ENUM, tp, level);
+       idf->id_def->df_address = l;
+}
+
+declare_formals(fp)
+       arith *fp;
+{
+       /*      Declares those formals as int that haven't been declared
+               by the user.
+               An address is assigned to each formal parameter.
+               The total size of the formals is returned in *fp;
+       */
+       register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
+       arith f_offset = (arith)0;
+       register int nparams = 0;
+
+#ifdef DEBUG
+       if (options['t'])
+               dumpidftab("start declare_formals", 0);
+#endif DEBUG
+       while (se)      {
+               register struct def *def = se->se_idf->id_def;
+               
+               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 */
+               se = se->next;
+               def->df_level = L_FORMAL2;      /* CJ */
+               RegisterAccount(def->df_address, def->df_type->tp_size,
+                               regtype(def->df_type),
+                               def->df_sc);
+               if (nparams++ >= STDC_NPARAMS)
+                       strict("number of formal parameters exceeds ANSI limit");
+       }
+       *fp = f_offset;
+}
+
+int
+regtype(tp)
+       struct type *tp;
+{
+       switch(tp->tp_fund) {
+       case INT:
+       case LONG:
+               return reg_any;
+#ifndef NOFLOAT
+       case FLOAT:
+       case DOUBLE:
+               return reg_float;
+#endif NOFLOAT
+       case POINTER:
+               return reg_pointer;
+       }
+       return -1;
+}
+
+add_def(idf, sc, tp, lvl)
+       struct idf *idf;
+       struct type *tp;
+       int lvl;
+       int sc;
+{
+       /*      The identifier idf is declared on level lvl with storage
+               class sc and type tp, through a faked C declaration.
+               This is probably the wrong way to structure the problem,
+               but it will have to do for the time being.
+       */
+       struct decspecs Ds; struct declarator Dc;
+
+       Ds = null_decspecs;
+       Ds.ds_type = tp;
+       Ds.ds_sc = sc;
+       Dc = null_declarator;
+       Dc.dc_idf = idf;
+       declare_idf(&Ds, &Dc, lvl);
+}
+
+update_ahead(idf)
+       register struct idf *idf;
+{
+       /*      The tk_symb of the token ahead is updated in the light of new
+               information about the identifier idf.
+       */
+       register int tk_symb = AHEAD;
+
+       if (    (tk_symb == IDENTIFIER || tk_symb == TYPE_IDENTIFIER) &&
+               ahead.tk_idf == idf
+       )
+               AHEAD = idf->id_def && idf->id_def->df_sc == TYPEDEF ?
+                               TYPE_IDENTIFIER : IDENTIFIER;
+}
+
+free_formals(fm)
+       register struct formal *fm;
+{
+       while (fm)      {
+               struct formal *tmp = fm->next;
+
+               free_formal(fm);
+               fm = tmp;
+       }
+}
+
+char hmask[IDFSIZE];
+
+init_hmask()
+{
+       /*      A simple congruence random number generator, as
+               described in Knuth, vol 2.
+       */
+       register int h, rnd = HASH_X;
+       
+       for (h = 0; h < IDFSIZE; h++)   {
+               hmask[h] = rnd;
+               rnd = (HASH_A * rnd + HASH_C) & HASHMASK;
+       }
+}
diff --git a/lang/cem/cemcom.ansi/idf.str b/lang/cem/cemcom.ansi/idf.str
new file mode 100644 (file)
index 0000000..f6f1106
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* IDENTIFIER DESCRIPTOR */
+
+#include       "nopp.h"
+
+/*     Since the % operation in the calculation of the hash function
+       turns out to be expensive, it is replaced by the cheaper XOR (^).
+       Each character of the identifier is xored with an 8-bit mask which
+       depends on the position of the character; the sum of these results
+       is the hash value.  The random masks are obtained from a
+       congruence generator in idf.c.
+*/
+
+#define        HASHSIZE        256     /* must be a power of 2 */
+#define        HASH_X          0253    /* Knuth's X */
+#define        HASH_A          77      /* Knuth's a */
+#define        HASH_C          153     /* Knuth's c */
+
+extern char hmask[];           /* the random masks */
+#define        HASHMASK                (HASHSIZE-1)    /* since it is a power of 2 */
+#define        STARTHASH()             (0)
+#define        ENHASH(hs,ch,ps)        (hs + (ch ^ hmask[ps]))
+#define        STOPHASH(hs)            (hs & HASHMASK)
+
+struct idf     {
+       struct idf *next;
+       char *id_text;
+#ifndef NOPP
+       struct macro *id_macro;
+       int id_resmac;          /* if nonzero: keyword of macroproc.    */
+#endif NOPP
+       int id_reserved;        /* non-zero for reserved words          */
+       char *id_file;          /* file containing the occurrence       */
+       unsigned int id_line;   /* line number of the occurrence        */
+       struct def *id_def;     /* variables, typedefs, enum-constants  */
+       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  */
+};
+
+/* ALLOCDEF "idf" 50 */
+
+extern struct idf *str2idf(), *idf_hashed();
+
+extern int level;
+extern struct idf *gen_idf();
diff --git a/lang/cem/cemcom.ansi/init.c b/lang/cem/cemcom.ansi/init.c
new file mode 100644 (file)
index 0000000..2e77ca1
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* PREPROCESSOR: INITIALIZATION ROUTINES */
+
+#include       "nopp.h"
+
+#ifndef NOPP
+#include       <system.h>
+#include       <alloc.h>
+#include       <time.h>
+#include       "class.h"
+#include       "macro.h"
+#include       "idf.h"
+
+struct mkey    {
+       char *mk_reserved;
+       int mk_key;
+} mkey[] =     {
+       {"define",      K_DEFINE},
+       {"elif",        K_ELIF},
+       {"else",        K_ELSE},
+       {"endif",       K_ENDIF},
+       {"error",       K_ERROR},
+       {"if",          K_IF},
+       {"ifdef",       K_IFDEF},
+       {"ifndef",      K_IFNDEF},
+       {"include",     K_INCLUDE},
+       {"line",        K_LINE},
+       {"pragma",      K_PRAGMA},
+       {"undef",       K_UNDEF},
+       {0,             K_UNKNOWN}
+};
+
+char *strcpy();
+
+init_pp()
+{
+       static char *months[12] = {
+               "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+       };
+       long clock, sys_time();
+       static char dbuf[30];
+       static char tbuf[30];
+       struct tm  *tp;
+
+       /*      Initialise the control line keywords (if, include, define, etc)
+               Although the lexical analyzer treats them as identifiers, the
+               control line handler can recognize them as keywords by the
+               id_resmac field of the identifier.
+       */
+       {
+               register struct mkey *mk = &mkey[0];
+
+               while (mk->mk_reserved) {
+                       register struct idf *idf = str2idf(mk->mk_reserved);
+                       
+                       if (idf->id_resmac)
+                               fatal("maximum identifier length insufficient");
+                       idf->id_resmac = mk->mk_key;
+                       mk++;
+               }
+       }
+
+       /*      Initialize __LINE__, __FILE__, __DATE__, __TIME__,
+               and __STDC__ macro definitions.
+       */
+       clock = sys_time();
+       tp = localtime(&clock);
+
+       /* __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);
+
+       /* __TIME__ */
+       sprintf(tbuf, "\"%.2d:%.2d:%.2d\"", tp->tm_hour, tp->tm_min, tp->tm_sec);
+       macro_def(str2idf("__TIME__"), tbuf, -1, 10, NOFLAG);
+
+       /* __LINE__     */
+       macro_def(str2idf("__LINE__"), "0", -1, 1, FUNC);
+
+       /* __FILE__     */
+       macro_def(str2idf("__FILE__"), "", -1, 1, FUNC);
+
+       /* __STDC__ */
+       macro_def(str2idf("__STDC__"), "1", -1, 1, NOFLAG);
+
+       /* defined(??) */
+       macro_def(str2idf("defined"), "", 1, 1, FUNC);
+}
+#endif NOPP
diff --git a/lang/cem/cemcom.ansi/input.c b/lang/cem/cemcom.ansi/input.c
new file mode 100644 (file)
index 0000000..dcabc85
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+
+#include "inputtype.h"
+#include "file_info.h"
+#include "input.h"
+
+#define INP_PUSHBACK   3
+#define INP_TYPE       struct file_info
+#define INP_VAR                finfo
+struct file_info       finfo;
+extern int             nestlevel;
+#include "nopp.h"
+#include <inp_pkg.body>
+
+#ifndef NOPP
+char *
+getwdir(fn)
+       register char *fn;
+{
+       register char *p;
+       char *strrindex();
+
+       p = strrindex(fn, '/');
+       while (p && *(p + 1) == '\0') { /* remove trailing /'s */
+               *p = '\0';
+               p = strrindex(fn, '/');
+       }
+
+       if (fn[0] == '\0' || (fn[0] == '/' && p == &fn[0])) /* absolute path */
+               return "";
+       if (p) {
+               *p = '\0';
+               fn = Salloc(fn, p - &fn[0] + 1);
+               *p = '/';
+               return fn;
+       }
+       return ".";
+}
+#endif NOPP
+
+int    NoUnstack;
+
+AtEoIT()
+{
+       unstackrepl();
+       return 0;
+}
+
+AtEoIF()
+{
+#ifndef NOPP
+       if (nestlevel != nestlow) lexwarning("missing #endif");
+       else
+#endif NOPP
+       if (NoUnstack) lexerror("unexpected EOF");
+#ifndef NOPP
+       nestlevel = nestlow;
+#endif
+       return 0;
+}
diff --git a/lang/cem/cemcom.ansi/input.h b/lang/cem/cemcom.ansi/input.h
new file mode 100644 (file)
index 0000000..43e11d4
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+#define INP_PUSHBACK 3
+
+#include <inp_pkg.spec>
+
+/*     Note: The following macro only garuantees one PushBack.
+*/
+#define UnGetChar()    ChPushBack(LexSave)
+
+extern int LexSave;    /* last character read by GetChar               */
+extern         int GetChar();  /* character input, with trigraph parsing       */
diff --git a/lang/cem/cemcom.ansi/interface.h b/lang/cem/cemcom.ansi/interface.h
new file mode 100644 (file)
index 0000000..e75dd77
--- /dev/null
@@ -0,0 +1,8 @@
+/* $Header$ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+#define PRIVATE        /*static                /* or not */
+#define IMPORT extern
+#define EXPORT
diff --git a/lang/cem/cemcom.ansi/ival.g b/lang/cem/cemcom.ansi/ival.g
new file mode 100644 (file)
index 0000000..b385db2
--- /dev/null
@@ -0,0 +1,700 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* CODE FOR THE INITIALISATION OF GLOBAL VARIABLES */
+
+{
+#include       "lint.h"
+#include       "nofloat.h"
+#include       <em.h>
+#include       "debug.h"
+#include       <alloc.h>
+#include       <assert.h>
+#include       "nobitfield.h"
+#include       "arith.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "type.h"
+#include       "proto.h"
+#include       "struct.h"
+#include       "field.h"
+#include       "assert.h"
+#include       "Lpars.h"
+#include       "sizes.h"
+#include       "idf.h"
+#include       "level.h"
+#include       "def.h"
+#include       "LLlex.h"
+#include       "noRoption.h"
+#include       "estack.h"
+#ifdef LINT
+#include       "l_lint.h"
+#endif LINT
+
+#define con_nullbyte() C_con_ucon("0", (arith)1)
+#define aggregate_type(tp) ((tp)->tp_fund == ARRAY || (tp)->tp_fund == STRUCT)
+
+char *long2str();
+char *strncpy();
+extern char options[];
+static int gen_error;
+struct type **gen_tphead(), **gen_tpmiddle();
+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(register struct type **tpp; register struct expr **expp;) :
+       { if (tpp) gen_tpcheck(tpp, 0); }
+[
+       assignment_expression(expp)
+               {
+#ifdef LINT
+                       lint_expr(*expp, USED);
+#endif LINT
+                       if ((*expp)->ex_type->tp_fund == ARRAY)
+                               array2pointer(*expp);
+                       if (tpp) {
+                               gen_simple_exp(tpp, expp);
+                               free_expression(*expp);
+                               *expp = 0;
+                       }
+               }
+|
+       initial_value_pack(tpp, expp)
+]
+;
+
+initial_value_pack(struct type **tpp; struct expr **expp;)
+       { static int pack_level; }
+:
+       '{'
+                       { if (pack_level == 0) gen_error = 0; pack_level++; }
+       initial_value_list(tpp, expp)
+                       { pack_level--;
+                         if (!pack_level) {
+                               while (p_stack) {
+                                       struct e_stack *p = p_stack->next;
+
+                                       free_e_stack(p_stack);
+                                       p_stack = p;
+                               }
+                         }
+                       }
+       '}'
+;
+
+initial_value_list(register struct type **tpp; struct expr **expp;)
+       { struct expr *e1;
+         register struct type **tpp2 = 0;
+       }
+:
+                       { if (tpp) tpp2 = gen_tphead(tpp, 0); }
+       initial_value(tpp2, &e1)
+                       { if (!tpp) init_expression(&expp, e1); }
+       [%while (AHEAD != '}')          /* >>> conflict on ',' */
+               ','
+                       { if (tpp) tpp2 = gen_tpmiddle(); }
+               initial_value(tpp2, &e1)
+                       { if (!tpp) init_expression(&expp, e1); }
+       ]*
+                       { if (tpp) gen_tpend(); }
+       ','?                            /* optional trailing comma */
+;
+
+{
+gen_tpcheck(tpp, union_allowed)
+       struct type **tpp;
+{
+       register struct type *tp;
+
+       if (gen_error) return;
+       switch((tp = *tpp)->tp_fund) {
+       case ARRAY:
+               if (! valid_type(tp->tp_up, "array element"))
+                       gen_error = 1;
+               break;
+       case STRUCT:
+               if (! valid_type(tp, "struct"))
+                       gen_error = 1;
+               break;
+       case UNION:
+               if (! valid_type(tp, "union"))
+                       gen_error = 1;
+               break;
+       }
+}
+
+gen_simple_exp(tpp, expp)
+       struct type **tpp;
+       struct expr **expp;
+{
+       register struct type *tp;
+
+       if (gen_error) return;
+       tp = *tpp;
+       switch(tp->tp_fund) {
+       case ARRAY:
+               if ((*expp)->ex_class == String && tp->tp_up->tp_fund == CHAR) {
+                       ch_array(tpp,*expp);
+                       break;
+               }
+               /* Fall through */
+       case UNION:
+       case STRUCT:
+               check_and_pad(expp, tpp);
+               break;
+       case ERRONEOUS:
+               gen_error = 1;
+               break;
+       default:
+               check_ival(expp, tp);
+               break;
+       }
+}
+
+struct type **
+arr_elem(tpp, p)
+       struct type **tpp;
+       struct e_stack *p;
+{
+       register struct type *tp = *tpp;
+
+       if (tp->tp_up->tp_fund == CHAR && AHEAD == STRING && p->elem_count == 1) {
+               p->nelem = 1;
+               return tpp;
+       }
+       if (AHEAD == '{' || ! aggregate_type(tp->tp_up))
+               return &(tp->tp_up);
+       return gen_tphead(&(tp->tp_up), 1);
+}
+
+struct sdef *
+next_field(sd, p)
+       register struct sdef *sd;
+       register struct e_stack *p;
+{
+       if (sd->sd_sdef)
+               p->bytes_upto_here += zero_bytes(sd);
+       if (p->last_offset != sd->sd_offset) {
+               p->bytes_upto_here +=
+                       size_of_type(sd->sd_type, "selector");
+               p->last_offset = sd->sd_offset;
+       }
+       return sd->sd_sdef;
+}
+
+struct type **
+gen_tphead(tpp, nest)
+       struct type **tpp;
+{
+       register struct type *tp = *tpp;
+       register struct e_stack *p;
+       register struct sdef *sd;
+
+       if (tpp && *tpp == error_type) {
+               gen_error = 1;
+               return 0;
+       }
+       if (gen_error) return tpp;
+       p = new_e_stack();
+       p->next = p_stack;
+       p_stack = p;
+       p->s_nested = nest;
+       p->s_tpp = tpp;
+       switch(tp->tp_fund) {
+       case ARRAY:
+               p->nelem = -1;
+               p->elem_count = 1;
+               if (tp->tp_size != (arith) -1) {
+                       p->nelem = (tp->tp_size / tp->tp_up->tp_size);
+               }
+               return arr_elem(tpp, p);
+       case STRUCT:
+               p->s_def = sd = tp->tp_sdef;
+               p->bytes_upto_here = 0;
+               p->last_offset = -1;
+#ifndef NOBITFIELD
+               while (sd && is_anon_idf(sd->sd_idf)) {
+                       put_bf(sd->sd_type, (arith) 0);
+                       sd = next_field(sd, p);
+               }
+#endif
+               if (! sd) {
+                       /* something wrong with this struct */
+                       gen_error = 1;
+                       p_stack = p->next;
+                       free_e_stack(p);
+                       return 0;
+               }
+               p->s_def = sd;
+               if (AHEAD != '{' && aggregate_type(sd->sd_type)) {
+                       return gen_tphead(&(sd->sd_type), 1);
+               }
+               return &(sd->sd_type);
+       default:
+               p->nelem = 1;
+               p->elem_count = 1;
+               return tpp;
+       }
+}
+
+struct type **
+gen_tpmiddle()
+{
+       register struct type *tp;
+       register struct sdef *sd;
+       register struct e_stack *p = p_stack;
+
+       if (gen_error) {
+               if (p) return p->s_tpp;
+               return 0;
+       }
+again:
+       tp = *(p->s_tpp);
+       switch(tp->tp_fund) {
+       default:
+               if (p->elem_count == p->nelem && p->s_nested) {
+                       p = p->next;
+                       free_e_stack(p_stack);
+                       p_stack = p;
+                       goto again;
+               }
+               p->elem_count++;
+               if (p->nelem >= 0 && p->elem_count > p->nelem) {
+                       too_many_initialisers();
+                       return p->s_tpp;
+               }
+               if (tp->tp_fund == ARRAY) {
+                       return arr_elem(p->s_tpp, p);
+               }
+               return p->s_tpp;
+       case STRUCT:
+               sd = gen_align_to_next(p);
+               if (! sd) {
+                       while (p->bytes_upto_here++ < tp->tp_size)
+                               con_nullbyte();
+                       if (p->s_nested) {
+                               p = p->next;
+                               free_e_stack(p_stack);
+                               p_stack = p;
+                               goto again;
+                       }
+                       too_many_initialisers();
+                       return p->s_tpp;
+               }
+               if (AHEAD != '{' && aggregate_type(sd->sd_type)) {
+                       return gen_tphead(&(sd->sd_type), 1);
+               }
+               return &(sd->sd_type);
+       }
+}
+
+struct sdef *
+gen_align_to_next(p)
+       register struct e_stack *p;
+{
+       register struct sdef *sd = p->s_def;
+
+       if (! sd) return sd;
+#ifndef NOBITFIELD
+       do {
+               if (is_anon_idf(sd->sd_idf)) put_bf(sd->sd_type, (arith) 0);
+#endif
+               sd = next_field(sd, p);
+#ifndef NOBITFIELD
+       } while (sd && is_anon_idf(sd->sd_idf));
+#endif
+       p->s_def = sd;
+       return sd;
+}
+
+gen_tpend()
+{
+       register struct e_stack *p = p_stack;
+       register struct type *tp;
+       register struct sdef *sd;
+       int getout = 0;
+
+       while (!getout && p) {
+           if (!gen_error) {
+               tp = *(p->s_tpp);
+               switch(tp->tp_fund) {
+               case ARRAY:
+                       if (tp->tp_size == -1) {
+                               *(p->s_tpp) = construct_type(ARRAY, tp->tp_up,
+                                       0, p->elem_count, NO_PROTO);
+                       }
+                       else {
+                               while (p->nelem-- > p->elem_count) {
+                                       pad(tp->tp_up);
+                               }
+                       }
+                       break;
+               case STRUCT:
+                       sd = gen_align_to_next(p);
+                       while (sd) {
+                               pad(sd->sd_type);
+                               if (sd->sd_sdef)
+                                       p->bytes_upto_here += zero_bytes(sd);
+                               p->bytes_upto_here +=
+                                       size_of_type(sd->sd_type, "selector");
+                               sd = sd->sd_sdef;
+                       }
+                       while (p->bytes_upto_here++ < tp->tp_size)
+                               con_nullbyte();
+                       break;
+               }
+           }
+           if (! p->s_nested) getout = 1;
+           p = p->next;
+           free_e_stack(p_stack);
+           p_stack = p;
+       }
+       gen_error = 0;
+}
+
+/*     check_and_pad() is given a simple initialisation expression
+       where the type can be either a simple or an aggregate type.
+       In the latter case, only the first member is initialised and
+       the rest is zeroed.
+*/
+check_and_pad(expp, tpp)
+       struct type **tpp;
+       struct expr **expp;
+{
+       register struct type *tp = *tpp;
+
+       if (tp->tp_fund == ARRAY) {
+               check_and_pad(expp, &(tp->tp_up));      /* first member */
+               if (tp->tp_size == (arith)-1)
+                       /*      no size specified upto here: just
+                               set it to the size of one member.
+                       */
+                       tp = *tpp = construct_type(ARRAY, tp->tp_up,
+                                       0, (arith)1, NO_PROTO);
+               else {
+                       register int dim = tp->tp_size / tp->tp_up->tp_size;
+                       /* pad remaining members with zeroes */
+                       while (--dim > 0)
+                               pad(tp->tp_up);
+               }
+       }
+       else
+       if (tp->tp_fund == STRUCT) {
+               register struct sdef *sd = tp->tp_sdef;
+
+               check_and_pad(expp, &(sd->sd_type));
+               /* next selector is aligned by adding extra zeroes */
+               if (sd->sd_sdef)
+                       zero_bytes(sd);
+               while (sd = sd->sd_sdef) { /* pad remaining selectors   */
+                       pad(sd->sd_type);
+                       if (sd->sd_sdef)
+                               zero_bytes(sd);
+               }
+       }
+       else if (tp->tp_fund == UNION) {
+               /* only the first selector can be initialized */
+               register struct sdef *sd = tp->tp_sdef;
+
+               check_and_pad(expp, &(sd->sd_type));
+       }
+       else    /* simple type  */
+               check_ival(expp, tp);
+}
+
+/*     pad() fills an element of type tp with zeroes.
+       If the element is an aggregate, pad() is called recursively.
+*/
+pad(tpx)
+       struct type *tpx;
+{
+       register struct type *tp = tpx;
+       register arith sz = tp->tp_size;
+
+       gen_tpcheck(&tpx, 1);
+       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:
+               put_bf(tp, (arith)0);
+               return;
+#endif NOBITFIELD
+               default:
+                       break;
+       }
+
+       while (sz >= word_size) {
+               C_con_cst((arith) 0);
+               sz -= word_size;
+       }
+       while (sz) {
+               C_con_icon("0", (arith) 1);
+               sz--;
+       }
+}
+
+/*     check_ival() checks whether the initialisation of an element
+       of a fundamental type is legal and, if so, performs the initialisation
+       by directly generating the necessary code.
+       No further comment is needed to explain the internal structure
+       of this straightforward function.
+*/
+check_ival(expp, tp)
+       register struct type *tp;
+       struct expr **expp;
+{
+       /*      The philosophy here is that ch7cast puts an explicit
+               conversion node in front of the expression if the types
+               are not compatible.  In this case, the initialisation
+               expression is no longer a constant.
+       */
+       register struct expr *expr = *expp;
+       
+       switch (tp->tp_fund) {
+       case CHAR:
+       case SHORT:
+       case INT:
+       case LONG:
+       case ENUM:
+       case POINTER:
+               ch7cast(expp, '=', tp);
+               expr = *expp;
+#ifdef DEBUG
+               print_expr("init-expr after cast", expr);
+#endif DEBUG
+               if (!is_ld_cst(expr))
+                       illegal_init_cst(expr);
+               else
+               if (expr->VL_CLASS == Const)
+                       con_int(expr);
+               else
+               if (expr->VL_CLASS == Name) {
+                       register struct idf *idf = expr->VL_IDF;
+
+                       if (idf->id_def->df_level >= L_LOCAL)
+                               illegal_init_cst(expr);
+                       else    /* e.g., int f(); int p = f; */
+                       if (idf->id_def->df_type->tp_fund == FUNCTION)
+                               C_con_pnam(idf->id_text);
+                       else    /* e.g., int a; int *p = &a; */
+                               C_con_dnam(idf->id_text, expr->VL_VALUE);
+               }
+               else {
+                       ASSERT(expr->VL_CLASS == Label);
+                       C_con_dlb(expr->VL_LBL, expr->VL_VALUE);
+               }
+               break;
+#ifndef NOFLOAT
+       case FLOAT:
+       case DOUBLE:
+               ch7cast(expp, '=', tp);
+               expr = *expp;
+#ifdef DEBUG
+               print_expr("init-expr after cast", expr);
+#endif DEBUG
+               if (expr->ex_class == Float)
+                       C_con_fcon(expr->FL_VALUE, expr->ex_type->tp_size);
+#ifdef NOTDEF
+
+Coercion from int to float is now always done compile time.
+This, to accept declarations like
+double x = -(double)1;
+and also to prevent runtime coercions for compile-time constants.
+
+               else
+               if (expr->ex_class == Oper && expr->OP_OPER == INT2FLOAT) {
+                       /* float f = 1; */
+                       expr = expr->OP_RIGHT;
+                       if (is_cp_cst(expr))
+                               C_con_fcon(long2str((long)expr->VL_VALUE, 10),
+                                       tp->tp_size);
+                       else 
+                               illegal_init_cst(expr);
+               }
+#endif NOTDEF
+               else
+                       illegal_init_cst(expr);
+               break;
+#endif NOFLOAT
+
+#ifndef NOBITFIELD
+       case FIELD:
+               ch7cast(expp, '=', tp->tp_up);
+               expr = *expp;
+#ifdef DEBUG
+               print_expr("init-expr after cast", expr);
+#endif DEBUG
+               if (is_cp_cst(expr))
+                       put_bf(tp, expr->VL_VALUE);
+               else
+                       illegal_init_cst(expr);
+               break;
+#endif NOBITFIELD
+
+       case ERRONEOUS:
+               break;
+       default:
+               crash("check_ival");
+               /*NOTREACHED*/
+       }
+}
+
+/*     ch_array() initialises an array of characters when given
+       a string constant.
+       Alignment is taken care of.
+*/
+ch_array(tpp, ex)
+       struct type **tpp;      /* type tp = array of characters        */
+       struct expr *ex;
+{
+       register struct type *tp = *tpp;
+       register arith length = ex->SG_LEN;
+       char *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);
+       }
+       else {
+               arith dim = tp->tp_size / tp->tp_up->tp_size;
+
+               if (length > dim) {
+                       expr_warning(ex, "too many initialisers");
+               }
+               length = dim;
+       }
+       /* throw out the characters of the already prepared string      */
+       s = Malloc((unsigned) (length));
+       clear(s, (int) (length));
+       strncpy(s, ex->SG_VALUE, (int) length);
+       free(ex->SG_VALUE);
+       str_cst(s, (int) (length));
+       free(s);
+}
+
+/*     As long as some parts of the pipeline cannot handle very long string
+       constants, string constants are written out in chunks
+*/
+str_cst(str, len)
+       register char *str;
+       register int len;
+{
+       int chunksize = ((127 + (int) word_size) / (int) word_size) * (int) word_size;
+
+       while (len > chunksize) {
+               C_con_scon(str, (arith) chunksize);
+               len -= chunksize;
+               str += chunksize;
+       }
+       C_con_scon(str, (arith) len);
+}
+
+#ifndef NOBITFIELD
+/*     put_bf() takes care of the initialisation of (bit-)field
+       selectors of a struct: each time such an initialisation takes place,
+       put_bf() is called instead of the normal code generating routines.
+       Put_bf() stores the given integral value into "field" and
+       "throws" the result of "field" out if the current selector
+       is the last of this number of fields stored at the same address.
+*/
+put_bf(tp, val)
+       struct type *tp;
+       arith val;
+{
+       static long field = (arith)0;
+       static arith offset = (arith)-1;
+       register struct field *fd = tp->tp_field;
+       register struct sdef *sd =  fd->fd_sdef;
+       static struct expr exp;
+
+       ASSERT(sd);
+       if (offset == (arith)-1) {
+               /* first bitfield in this field */
+               offset = sd->sd_offset;
+               exp.ex_type = tp->tp_up;
+               exp.ex_class = Value;
+               exp.VL_CLASS = Const;
+       }
+       if (val != 0)   /* insert the value into "field"        */
+               field |= (val & fd->fd_mask) << fd->fd_shift;
+       if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) {
+               /* the selector was the last stored at this address     */
+               exp.VL_VALUE = field;
+               con_int(&exp);
+               field = (arith)0;
+               offset = (arith)-1;
+       }
+}
+#endif NOBITFIELD
+
+int
+zero_bytes(sd)
+       register struct sdef *sd;
+{
+       /*      fills the space between a selector of a struct
+               and the next selector of that struct with zero-bytes.
+       */
+       register int n = sd->sd_sdef->sd_offset - sd->sd_offset -
+               size_of_type(sd->sd_type, "struct member");
+       register int count = n;
+
+       while (n-- > 0)
+               con_nullbyte();
+       return count;
+}
+
+int
+valid_type(tp, str)
+       struct type *tp;
+       char *str;
+{
+       ASSERT(tp!=(struct type *)0);
+       if (tp->tp_size < 0) {
+               error("size of %s unknown", str);
+               return 0;
+       }
+       return 1;
+}
+
+con_int(ex)
+       register struct expr *ex;
+{
+       register struct type *tp = ex->ex_type;
+
+       ASSERT(is_cp_cst(ex));
+       if (tp->tp_unsigned)
+               C_con_ucon(long2str((long)ex->VL_VALUE, -10), tp->tp_size);
+       else if (tp->tp_size == word_size)
+               C_con_cst(ex->VL_VALUE);
+       else
+               C_con_icon(long2str((long)ex->VL_VALUE, 10), tp->tp_size);
+}
+
+illegal_init_cst(ex)
+       struct expr *ex;
+{
+       expr_error(ex, "illegal initialisation constant");
+       gen_error = 1;
+}
+
+too_many_initialisers()
+{
+       error("too many initialisers");
+       gen_error = 1;
+}
+}
diff --git a/lang/cem/cemcom.ansi/l_brace.str b/lang/cem/cemcom.ansi/l_brace.str
new file mode 100644 (file)
index 0000000..2e7b71d
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+
+/*     To determine the minimum scope of a local variable, all (braced)
+       scopes are numbered consecutively.  Next we maintain an array which
+       maps the nesting depth (level) onto the scope number; we record
+       the scope number of the first application of a local variable
+       in its definition.  Each further application requires that the
+       level of the variable be at least large enough to comprise both
+       the present scope and that of its first application.  That level
+       number is determined by searching the array and is then recorded in
+       the definition (beacuse it is always equal to or smaller than the
+       level already there).
+
+       The array is implemented as a linked list of struct brace.
+*/
+
+struct brace   {
+       struct brace *next;
+       int br_count;
+       int br_level;
+};
+
+/* ALLOCDEF "brace" 10 */
+
diff --git a/lang/cem/cemcom.ansi/l_class.h b/lang/cem/cemcom.ansi/l_class.h
new file mode 100644 (file)
index 0000000..2a77e54
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+
+/*     Lint class constants    */
+
+#define        LFDF    'a'     /* Library Function Definition */
+#define        LVDF    'b'     /* Library Variable Definition */
+#define        EFDF    'c'     /* External Function Definition */
+#define        EVDF    'd'     /* External Variable Definition */
+#define        EFDC    'e'     /* External Function Declaration */
+#define        EVDC    'f'     /* External Variable Declaration */
+#define        IFDC    'g'     /* Implicit Function Declaration */
+#define        SFDF    'h'     /* Static Function Definition */
+#define        SVDF    'i'     /* Static Variable Definition */
+#define        FC      'j'     /* Function Call */
+#define        VU      'k'     /* Variable Usage */
+#define        XXDF    'l'     /* Ignore Class */
+
diff --git a/lang/cem/cemcom.ansi/l_comment.c b/lang/cem/cemcom.ansi/l_comment.c
new file mode 100644 (file)
index 0000000..a2a74af
--- /dev/null
@@ -0,0 +1,211 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint-specific comment handling  */
+
+#include       <ctype.h>
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>
+#include       "interface.h"
+#include       "arith.h"
+#include       "l_state.h"
+#include       "l_comment.h"
+
+extern char loptions[];
+
+/*     Since the lexical analyser does a one-token look-ahead, pseudo-
+       comments are read too soon.  This is remedied by first storing them
+       in static variables and then moving them to the real variables
+       one token later.
+*/
+
+PRIVATE int notreached;
+PRIVATE int varargsN = -1;
+PRIVATE int argsused;
+PRIVATE int formatN;
+PRIVATE int formatVAR;
+PRIVATE char *format;
+PRIVATE char *prev_format;
+
+PRIVATE make_format();
+
+int LINTLIB;                           /* file is lint library */
+int s_NOTREACHED;                      /* statement not reached */
+int f_VARARGSn;                                /* function with variable # of args */
+int f_ARGSUSED;                                /* function does not use all args */
+int f_FORMATn;                         /* argument f_FORMATn is f_FORMAT */
+char *f_FORMAT;
+int f_FORMATvar;                       /* but the formal argument may be
+                                          absent because of varargs.h */
+
+lint_init_comment()
+{
+       LINTLIB = loptions['L'];
+}
+
+lint_comment_ahead()
+{
+       s_NOTREACHED = notreached;
+       notreached = 0;
+}
+
+lint_comment_function()
+{
+       f_ARGSUSED = argsused | loptions['v'];
+       argsused = 0;
+
+       f_VARARGSn = varargsN;
+       varargsN = -1;
+
+       f_FORMATn = formatN;
+       formatN = 0;
+       f_FORMAT = format;
+       if (format)
+               prev_format = format;
+       format = 0;
+
+       f_FORMATvar = formatVAR;
+       formatVAR = 0;
+}
+
+PRIVATE char buf[1000];
+PRIVATE char *bufpos;                  /* next free position in buf */
+
+lint_start_comment()
+{
+       bufpos = &buf[0];
+}
+
+lint_comment_char(c)
+       int c;
+{
+/* This function is called with every character between /_* and *_/ */
+       if (bufpos - &buf[0] < sizeof(buf)-1)
+               *bufpos++ = (char)c;
+}
+
+lint_end_comment()
+{
+       *bufpos++ = '\0';
+       bufpos = &buf[0];
+
+       /* skip initial blanks */
+       while (*bufpos && isspace(*bufpos)) {
+               bufpos++;
+       }
+
+       /* now test for one of the pseudo-comments */
+       if (strncmp(bufpos, "NOTREACHED", 10) == 0) {
+               notreached = 1;
+       }
+       else
+       if (strncmp(bufpos, "ARGSUSED", 8) == 0) {
+               argsused = 1;
+       }
+       else
+       if (strncmp(bufpos, "LINTLIBRARY", 11) == 0) {
+               LINTLIB = 1;
+       }
+       else
+       if (strncmp(bufpos, "VARARGS", 7) == 0) {
+               bufpos += 7;
+               varargsN = isdigit(*bufpos) ? atoi(bufpos) : 0;
+       }
+       else
+       if (strncmp(bufpos, "FORMAT", 6) == 0 && isdigit(bufpos[6])) {
+               register int argn;
+
+               bufpos += 6;
+               argn = *bufpos++ - '0';
+               varargsN = argn + 1;
+               if (*bufpos == 'v') {
+                       /* something like FORMAT3v */
+                       formatVAR = 1;
+                       bufpos++;
+               }
+               make_format(argn, bufpos);
+               
+       }
+}
+
+/*     We use a small FSA to skip layout inside formats, but to preserve
+       a space between letters and digits.
+*/
+
+#define        NONE            0
+#define        LETGIT          1
+#define        LETGITSPACE     2
+
+PRIVATE
+make_format(argn, oldf)
+       int argn;
+       char *oldf;
+{
+       register char *newf;
+       register int last_stat;
+
+       while (*oldf && *oldf != '$') {
+               oldf++;
+       }
+       if (!*oldf) {
+               /* no format given, repeat previous format */
+               if (!prev_format) {
+                       warning("format missing and no previous format");
+               }
+               formatN = argn;
+               format = prev_format;
+               return;
+       }
+       if (*oldf++ != '$') {
+               warning("no format in FORMAT pseudo-comment");
+               format = 0;
+               return;
+       }
+
+       /* there is a new format to be composed */
+       newf = Malloc(strlen(oldf));
+               /* certainly enough and probably not overly too much */
+       formatN = argn;
+       format = newf;
+
+       last_stat = NONE;
+       while (*oldf && *oldf != '$') {
+               register char ch = *oldf++;
+
+               if (isspace(ch)) {
+                       if (last_stat == LETGIT)
+                               last_stat = LETGITSPACE;
+               }
+               else
+               if (isalnum(ch)) {
+                       switch (last_stat) {
+                       case NONE:
+                               last_stat = LETGIT;
+                               break;
+                       case LETGITSPACE:
+                               *newf++ = ' ';
+                               last_stat = LETGIT;
+                               break;
+                       }
+                       *newf++ = ch;
+               }
+               else {
+                       last_stat = NONE;
+                       *newf++ = ch;
+               }
+       }
+       if (*oldf != '$') {
+               warning("no end of format in FORMAT pseudo-comment");
+               format = 0;
+               return;
+       }
+       *newf++ = '\0';
+}
+
+#endif LINT
diff --git a/lang/cem/cemcom.ansi/l_comment.h b/lang/cem/cemcom.ansi/l_comment.h
new file mode 100644 (file)
index 0000000..9340b08
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+
+extern int LINTLIB;                    /* file is lint library */
+extern int s_NOTREACHED;               /* statement not reached */
+extern int f_VARARGSn;                 /* function with variable # of args */
+extern int f_ARGSUSED;                 /* function does not use all args */
+extern int f_FORMATn;                  /* argument f_FORMATn is f_FORMAT */
+extern char *f_FORMAT;
+extern int f_FORMATvar;                        /* but the formal argument may be
+                                          absent because of varargs.h */
+
diff --git a/lang/cem/cemcom.ansi/l_dummy.c b/lang/cem/cemcom.ansi/l_dummy.c
new file mode 100644 (file)
index 0000000..f0633a6
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+
+/*
+ *The following functions are hacked to null-functions (i.e. they
+ * do nothing). This needs another solution in the future.
+ */
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       "arith.h"
+#include       "label.h"
+
+C_close(){}
+int C_busy(){return 0;}
+
+
+/* More routines */
+/* ARGSUSED */
+CC_bhcst(ps_xxx,n,w,i) arith n,w; {}
+/* ARGSUSED */
+CC_crcst(ps_xxx,v) arith v; {}
+/* ARGSUSED */
+CC_crdlb(ps_xxx,v,s) label v; arith s; {}
+/* ARGSUSED */
+CC_crdnam(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_crfcon(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_cricon(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_crilb(ps_xxx,v) label v; {}
+/* ARGSUSED */
+CC_crpnam(ps_xxx,v) char *v; {}
+/* ARGSUSED */
+CC_crscon(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_crucon(ps_xxx,v,s) char *v; arith s; {}
+/* ARGSUSED */
+CC_cst(l) {}
+/* ARGSUSED */
+CC_dfdlb(l) label l; {}
+/* ARGSUSED */
+CC_dfdnam(s) char *s; {}
+/* ARGSUSED */
+CC_dfilb(l) label l; {}
+/* ARGSUSED */
+CC_end(l) arith l; {}
+CC_msend() {}
+/* ARGSUSED */
+CC_msstart(ms) {}
+/* ARGSUSED */
+CC_opcst(op_xxx,c) arith c; {}
+/* ARGSUSED */
+CC_opdlb(op_xxx,g,o) label g; arith o; {}
+/* ARGSUSED */
+CC_opilb(op_xxx,b) label b; {}
+/* ARGSUSED */
+CC_oppnam(op_xxx,p) char *p; {}
+/* ARGSUSED */
+CC_pronarg(s) char *s; {}
+/* ARGSUSED */
+CC_psdlb(ps_xxx,l) label l; {}
+/* ARGSUSED */
+CC_psdnam(ps_xxx,s) char *s; {}
+/* ARGSUSED */
+CC_pspnam(ps_xxx,s) char *s; {}
+/* ARGSUSED */
+CC_scon(v,s) char *s; {}
+#endif LINT
diff --git a/lang/cem/cemcom.ansi/l_ev_ord.c b/lang/cem/cemcom.ansi/l_ev_ord.c
new file mode 100644 (file)
index 0000000..c0cfe4c
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint evaluation order checking  */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>       /* for st_free */
+#include       "interface.h"
+#include       "assert.h"
+#include       "arith.h"       /* definition arith */
+#include       "label.h"       /* definition label */
+#include       "expr.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "code.h"        /* RVAL etc */
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "type.h"
+#include       "level.h"
+#include       "nofloat.h"
+#include       "l_lint.h"
+#include       "l_state.h"
+
+extern char *symbol2str();
+
+PRIVATE check_ev_order();
+
+check_and_merge(expr, espp, esp)
+       struct expr *expr;
+       struct expr_state **espp, *esp;
+{
+/* Checks for undefined evaluation orders in case of a non-sequencing operator.
+ * In addition the sets of used and set variables of both expressions are
+ * united.
+ * *espp will be pointing to this new list. esp is used for this list.
+ */
+       register struct expr_state **pp, *p1, *p2;
+       int oper = expr->OP_OPER;
+       int is_sequencer =
+               (oper == '?' || oper == OR || oper == AND || oper ==',');
+
+       for (p1 = *espp; p1; p1 = p1->next) {
+               /* scan the list esp for the same variable */
+               p2 = esp;
+               pp = &esp;
+               while (p2) {
+                       if (    /* p1 and p2 refer to the same location */
+                               p1->es_idf == p2->es_idf
+                       &&      p1->es_offset == p2->es_offset
+                       ) {
+                               /* check */
+                               if (!is_sequencer)
+                                       check_ev_order(p1, p2, expr);
+
+                               /* merge the info */
+                               p1->es_used |= p2->es_used;
+                               p1->es_referred |= p2->es_referred;
+                               p1->es_set |= p2->es_set;
+
+                               /* and remove the entry from esp */
+                               *pp = p2->next;
+                               free_expr_state(p2);
+                               p2 = *pp;
+                       }
+                       else {
+                               /* skip over the entry in esp */
+                               pp = &p2->next;
+                               p2 = p2->next;
+                       }
+               }
+       }
+       /*      If there is anything left in the list esp, this is put in
+               front of the list *espp is now pointing to, and *espp will be
+               left pointing to this new list.
+       */
+       if (!esp)
+               return;
+       p1 = *espp;
+       *espp = esp;
+       while (esp->next)
+               esp = esp->next;
+       esp->next = p1;
+}
+
+PRIVATE
+check_ev_order(esp1, esp2, expr)
+       struct expr_state *esp1, *esp2;
+       struct expr *expr;
+{
+       if (    (esp1->es_used && esp2->es_set)
+       ||      (esp1->es_set && esp2->es_used)
+       ||      (esp1->es_set && esp2->es_set)
+       ) {
+               expr_warning(expr,
+                       "result of %s depends on evaluation order on %s",
+                       symbol2str(expr->OP_OPER),
+                       esp1->es_idf->id_text);
+       }
+}
+
+#endif LINT
diff --git a/lang/cem/cemcom.ansi/l_lint.c b/lang/cem/cemcom.ansi/l_lint.c
new file mode 100644 (file)
index 0000000..b591e11
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint main routines      */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>       /* for st_free */
+#include       "debug.h"
+#include       "interface.h"
+#include       "assert.h"
+#include       "arith.h"       /* definition arith */
+#include       "label.h"       /* definition label */
+#include       "expr.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "code.h"        /* RVAL etc */
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "type.h"
+#include       "level.h"
+#include       "nofloat.h"
+#include       "l_lint.h"
+#include       "l_state.h"
+#include       "l_outdef.h"
+
+extern char options[128];
+extern char *symbol2str();
+
+PRIVATE struct expr_state *expr2state();
+PRIVATE struct expr_state *value2state();
+PRIVATE struct expr_state *oper2state();
+PRIVATE expr_ignored();
+PRIVATE add_expr_state();
+PRIVATE referred_esp();
+PRIVATE free_expr_states();
+
+lint_init()
+{
+       lint_init_comment();
+       lint_init_stack();
+}
+
+lint_expr(expr, used)
+       struct expr *expr;
+       int used;                       /* USED or IGNORED */
+{
+       register struct expr_state *esp;
+
+       esp = expr2state(expr, RVAL, used);
+       referred_esp(esp);
+       free_expr_states(esp);
+}
+
+PRIVATE struct expr_state *
+expr2state(expr, val, used)
+       register struct expr *expr;
+       int val;                        /* RVAL or LVAL */
+       int used;                       /* USED or IGNORED */
+{
+/* Main function to process an expression tree.
+ * It returns a structure containing information about which variables
+ * are set and which are used in the expression.
+ * In addition it sets 'used' and 'set' fields of the corresponding
+ * variables in the current state.
+ * If the value of an operation without side-effects is not used,
+ * a warning is given.
+ */
+       if (used == IGNORED) {
+               expr_ignored(expr);
+       }
+
+       switch (expr->ex_class) {
+       case Value:
+               return value2state(expr, val);
+
+       case Oper:
+               return oper2state(expr, val, used);
+
+       default:                        /* String, Float, Type */
+               return 0;
+       }
+}
+
+PRIVATE struct expr_state *
+value2state(expr, val)
+       struct expr *expr;
+       int val;                        /* RVAL or LVAL */
+{
+       switch (expr->VL_CLASS) {
+       case Const:
+       case Label:
+               return 0;
+
+       case Name:
+       {
+               register struct idf *idf = expr->VL_IDF;
+               struct expr_state *esp = 0;
+
+               if (!idf || !idf->id_def)
+                       return 0;
+
+               if (val == RVAL && expr->ex_lvalue == 1) {
+                       /* value of identifier used */
+                       change_state(idf, USED);
+                       add_expr_state(expr->EX_VALUE, USED, &esp);
+               }
+               if (val == RVAL && expr->ex_lvalue == 0) {
+                       /* address of identifier used */
+                       add_expr_state(expr->EX_VALUE, REFERRED, &esp);
+               }
+               return esp;
+       }
+
+       default:
+               NOTREACHED();
+               /* NOTREACHED */
+       }
+}
+
+/*     Let's get this straight.
+       An assignment is performed by elaborating the LHS and the RHS
+       collaterally, to use the A68 terminology, and then serially do the
+       actual assignment. This means:
+       1.      evaluate the LHS as an LVAL,
+       2.      evaluate the RHS as an RVAL,
+       3.      merge them checking for interference,
+       4.      set the result of the LHS to SET, if it is a named variable
+*/
+
+PRIVATE struct expr_state *
+oper2state(expr, val, used)
+       struct expr *expr;
+       int val;                        /* RVAL or LVAL */
+       int used;                       /* USED or IGNORED */
+{
+       register int oper = expr->OP_OPER;
+       register struct expr *left = expr->OP_LEFT;
+       register struct expr *right = expr->OP_RIGHT;
+       struct expr_state *esp_l = 0;
+       struct expr_state *esp_r = 0;
+
+       switch (oper) {
+
+       /* assignments */
+       case '=':
+       case PLUSAB:
+       case MINAB:
+       case TIMESAB:
+       case DIVAB:
+       case MODAB:
+       case LEFTAB:
+       case RIGHTAB:
+       case ANDAB:
+       case XORAB:
+       case ORAB:
+               /* evaluate the LHS, only once; see RM 7.14 */
+               esp_l = expr2state(left, (oper == '=' ? LVAL : RVAL), USED);
+
+               /* evaluate the RHS as an RVAL and merge */
+               esp_r = expr2state(right, RVAL, USED);
+               check_and_merge(expr, &esp_l, esp_r);
+
+               /* set resulting variable, if any */
+               if (ISNAME(left)) {
+                       change_state(left->VL_IDF, SET);
+                       add_expr_state(left->EX_VALUE, SET, &esp_l);
+               }
+
+               return esp_l;
+
+       case POSTINCR:
+       case POSTDECR:
+       case PLUSPLUS:
+       case MINMIN:
+               esp_l = expr2state(left, RVAL, USED);
+
+               /* set resulting variable, if any */
+               if (ISNAME(left)) {
+                       change_state(left->VL_IDF, SET);
+                       add_expr_state(left->EX_VALUE, SET, &esp_l);
+               }
+
+               return esp_l;
+
+       case '?':
+               esp_l = expr2state(left, RVAL, USED);
+               esp_r = expr2state(right->OP_LEFT, RVAL, USED);
+               check_and_merge(expr, &esp_l, esp_r);
+               esp_r = expr2state(right->OP_RIGHT, RVAL, USED);
+               check_and_merge(expr, &esp_l, esp_r);
+               return esp_l;
+
+       case '(':
+               if (right != 0) {
+                       /* function call with parameters */
+                       register struct expr *ex = right;
+
+                       while ( ex->ex_class == Oper
+                       &&      ex->OP_OPER == PARCOMMA
+                       ) {
+                               esp_r = expr2state(ex->OP_RIGHT, RVAL, USED);
+                               check_and_merge(expr, &esp_l, esp_r);
+                               ex = ex->OP_LEFT;
+                       }
+                       esp_r = expr2state(ex, RVAL, USED);
+                       check_and_merge(expr, &esp_l, esp_r);
+               }
+
+               if (ISNAME(left)) {
+                       fill_outcall(expr,
+                               expr->ex_type->tp_fund == VOID ?
+                               VOIDED : used
+                       );
+                       outcall();
+                       left->VL_IDF->id_def->df_used = 1;
+               }
+               else {
+                       esp_r = expr2state(left, RVAL, USED);
+                       check_and_merge(expr, &esp_l, esp_r);
+               }
+               referred_esp(esp_l);
+               return esp_l;
+
+       case '.':
+               return expr2state(left, val, USED);
+
+       case ARROW:
+               return expr2state(left, RVAL, USED);
+
+       case INT2INT:
+       case INT2FLOAT:
+       case FLOAT2INT:
+       case FLOAT2FLOAT:
+               return expr2state(right, RVAL, USED);
+
+       /* monadic operators */
+       case '-':
+       case '*':
+               if (left)
+                       goto dyadic;
+       case '~':
+       case '!':
+               return expr2state(right, RVAL, USED);
+
+       /* relational operators */
+       case '<':
+       case '>':
+       case LESSEQ:
+       case GREATEREQ:
+       case EQUAL:
+       case NOTEQUAL:
+               lint_relop(left, right, oper);
+               lint_relop(right, left, 
+                       oper == '<' ? '>' :
+                       oper == '>' ? '<' :
+                       oper == LESSEQ ? GREATEREQ :
+                       oper == GREATEREQ ? LESSEQ :
+                       oper
+               );
+               goto dyadic;
+
+       /* dyadic operators */
+       dyadic:
+       case '+':
+       case '/':
+       case '%':
+       case ',':
+       case LEFT:
+       case RIGHT:
+       case '&':
+       case '|':
+       case '^':
+       case OR:
+       case AND:
+               esp_l = expr2state(left, RVAL,
+                                       oper == ',' ? IGNORED : USED);
+               esp_r = expr2state(right, RVAL,
+                                       oper == ',' ? used : USED);
+               check_and_merge(expr, &esp_l, esp_r);
+
+               return esp_l;
+
+       default:
+               return 0;       /* for initcomma */
+       }
+}
+
+PRIVATE
+expr_ignored(expr)
+       struct expr *expr;
+{
+       switch (expr->ex_class) {
+       case Oper:
+               switch (expr->OP_OPER) {
+               case '=':
+               case TIMESAB:
+               case DIVAB:
+               case MODAB:
+               case LEFTAB:
+               case RIGHTAB:
+               case ANDAB:
+               case XORAB:
+               case ORAB:
+               case AND:                       /* doubtful but useful */
+               case OR:                        /* doubtful but useful */
+               case '(':
+               case '?':
+               case ',':
+                       break;
+
+               case PLUSAB:
+               case MINAB:
+               case POSTINCR:
+               case POSTDECR:
+               case PLUSPLUS:
+               case MINMIN:
+                       /* may hide the operator '*' */
+                       if (    /* operation on a pointer */
+                               expr->OP_TYPE->tp_fund == POINTER
+                       &&      /* the result is dereferenced, e.g. *p++; */
+                               expr->ex_type == expr->OP_TYPE->tp_up
+                       ) {
+                               hwarning("result of * ignored");
+                       }
+                       break;
+
+               default:
+                       hwarning("result of %s ignored",
+                                               symbol2str(expr->OP_OPER));
+                       break;
+               }
+               break;
+
+       case Value:
+               hwarning("value as statement");
+               break;
+
+       default:                        /* String Float */
+               hwarning("constant as statement");
+               break;
+       }
+}
+
+PRIVATE
+add_expr_state(value, to_state, espp)
+       struct value value;
+       struct expr_state **espp;
+{
+       register struct expr_state *esp = *espp;
+
+       ASSERT(value.vl_class == Name);
+
+       /* try to find the esp */
+       while ( esp
+       &&      !(      esp->es_idf == value.vl_data.vl_idf
+               &&      esp->es_offset == value.vl_value
+               )
+       ) {
+               esp = esp->next;
+       }
+
+       /* if not found, add it */
+       if (!esp) {
+               esp = new_expr_state();
+               esp->es_idf = value.vl_data.vl_idf;
+               esp->es_offset = value.vl_value;
+               esp->next = *espp;
+               *espp = esp;
+       }
+
+       /* set state */
+       switch (to_state) {
+       case USED:
+               esp->es_used = 1;
+               break;
+       case REFERRED:
+               esp->es_referred = 1;
+               break;
+       case SET:
+               esp->es_set = 1;
+               break;
+       default:
+               NOTREACHED();
+               /* NOTREACHED */
+       }
+}
+
+PRIVATE
+referred_esp(esp)
+       struct expr_state *esp;
+{
+       /* raises all REFERRED items to SET and USED status */
+       while (esp) {
+               if (esp->es_referred) {
+                       esp->es_set = 1;
+                       change_state(esp->es_idf, SET);
+                       esp->es_used = 1;
+                       change_state(esp->es_idf, USED);
+                       esp->es_referred = 0;
+               }
+               esp = esp->next;
+       }
+}
+
+PRIVATE
+free_expr_states(esp)
+       register struct expr_state *esp;
+{
+       while (esp) {
+               register struct expr_state *esp2 = esp;
+
+               esp = esp->next;
+               free_expr_state(esp2);
+       }
+}
+
+#ifdef DEBUG
+print_esp(msg, esp)
+       char *msg;
+       struct expr_state *esp;
+{
+       print("%s: <", msg);
+       while (esp) {
+               print(" %s[%d]%c%c%c ",
+                       esp->es_idf->id_text, esp->es_offset,
+                       (esp->es_used ? 'U' : ' '),
+                       (esp->es_referred ? 'R' : ' '),
+                       (esp->es_set ? 'S' : ' ')
+               );
+               esp = esp->next;
+       }
+       print(">\n");
+}
+#endif DEBUG
+
+#endif LINT
diff --git a/lang/cem/cemcom.ansi/l_lint.h b/lang/cem/cemcom.ansi/l_lint.h
new file mode 100644 (file)
index 0000000..0bdffde
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     LINT FLAGS      */
+
+#define        USED            0
+#define        IGNORED         1
+#define        SET             2
+#define        VOIDED          3
+#define        REFERRED        4
+
+/* for od_valreturned */
+#define        NOVALRETURNED   0
+#define        VALRETURNED     1
+#define        NORETURN        2               /* end of function NOTREACHED */
+
diff --git a/lang/cem/cemcom.ansi/l_misc.c b/lang/cem/cemcom.ansi/l_misc.c
new file mode 100644 (file)
index 0000000..1384c5f
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint miscellaneous routines     */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>       /* for st_free */
+#include       "interface.h"
+#include       "arith.h"       /* definition arith */
+#include       "label.h"       /* definition label */
+#include       "expr.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "code.h"        /* RVAL etc */
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "type.h"
+#include       "level.h"
+#include       "nofloat.h"
+#include       "l_state.h"
+
+extern char *symbol2str();
+extern struct type *func_type;
+
+PRIVATE lint_enum_arith();
+PRIVATE lint_conversion();
+PRIVATE int numsize();
+
+lint_new_oper(expr)
+       struct expr *expr;
+{
+       /*      Does additional checking on a newly constructed expr node
+               of class Oper.
+
+               Some code in this routine could be contracted, but since
+               I am not sure we have covered the entire ground, we'll
+               leave the contracting for some rainy day.
+       */
+       register struct expr *left = expr->OP_LEFT;
+       register struct expr *right = expr->OP_RIGHT;
+       register int oper = expr->OP_OPER;
+       register int l_fund =
+               left == 0 ? 0 :                 /* for monadics */
+               left->ex_type->tp_fund;
+       register int r_fund =
+               right == 0 ? 0 :                /* for ( without parameters */
+               right->ex_type->tp_fund;
+
+       /*      In ch7.c, in ch7asgn(), a combined operator/assignment
+               is hammered into correctness by repeated application of
+               ch7bin(), which calls new_oper(), which calls lint_new_oper().
+               These spurious calls understandably cause spurious error
+               messages, which we don't like.  So we try to suppress these
+               wierd calls here.  This refers to the code marked
+                       this is really $#@&*%$# !
+               in ch7asgn().
+       */
+       switch (oper) {
+       case PLUSAB:
+       case MINAB:
+       case TIMESAB:
+       case DIVAB:
+       case MODAB:
+       case LEFTAB:
+       case RIGHTAB:
+       case ANDAB:
+       case XORAB:
+       case ORAB:
+               /* is the left operand wierd? */
+               if (    left->ex_class == Value
+               &&      left->VL_CLASS == Const
+               &&      left->VL_VALUE == 0
+               ) {
+                       return;
+               }
+       }
+
+       switch (oper) {
+       case '=':
+               lint_conversion(right, l_fund);
+               break;
+
+       case PLUSAB:
+               lint_conversion(right, l_fund);
+       case '+':
+               lint_enum_arith(l_fund, oper, r_fund);
+               break;
+
+       case MINAB:
+               lint_conversion(right, l_fund);
+       case '-':
+               if (left == 0) {
+                       /* unary */
+                       if (r_fund == ENUM)
+                               warning("negating an enum");
+               }
+               else {
+                       /* binary */
+                       if (l_fund == ENUM && r_fund == ENUM) {
+                               if (!equal_type(left->ex_type, right->ex_type))
+                                       warning("subtracting enums of different type");
+                               /* update the type, cem does not do it */
+                               expr->ex_type = int_type;
+                       }
+                       lint_enum_arith(l_fund, oper, r_fund);
+               }
+               break;
+
+       case TIMESAB:
+               lint_conversion(right, l_fund);
+       case '*':
+               if (left == 0) {
+                       /* unary */
+               }
+               else {
+                       /* binary */
+                       if (l_fund == ENUM || r_fund == ENUM)
+                               warning("multiplying enum");
+               }
+               break;
+
+       case DIVAB:
+               lint_conversion(right, l_fund);
+       case '/':
+               if (l_fund == ENUM || r_fund == ENUM)
+                       warning("division on enum");
+               break;
+
+       case MODAB:
+               lint_conversion(right, l_fund);
+       case '%':
+               if (l_fund == ENUM || r_fund == ENUM)
+                       warning("modulo on enum");
+               break;
+
+       case '~':
+               if (r_fund == ENUM || r_fund == FLOAT || r_fund == DOUBLE)
+                       warning("~ on %s", symbol2str(r_fund));
+               break;
+
+       case '!':
+               if (r_fund == ENUM)
+                       warning("! on enum");
+               break;
+
+       case INT2INT:
+       case INT2FLOAT:
+       case FLOAT2INT:
+       case FLOAT2FLOAT:
+               lint_conversion(right, l_fund);
+               break;
+
+       case '<':
+       case '>':
+       case LESSEQ:
+       case GREATEREQ:
+       case EQUAL:
+       case NOTEQUAL:
+               if (    (l_fund == ENUM || r_fund == ENUM)
+               &&      !equal_type(left->ex_type, right->ex_type)
+               ) {
+                       warning("comparing enum with non-enum");
+               }
+               lint_relop(left, right, oper);
+               lint_relop(right, left, 
+                       oper == '<' ? '>' :
+                       oper == '>' ? '<' :
+                       oper == LESSEQ ? GREATEREQ :
+                       oper == GREATEREQ ? LESSEQ :
+                       oper
+               );
+               break;
+
+       case LEFTAB:
+       case RIGHTAB:
+               lint_conversion(right, l_fund);
+       case LEFT:
+       case RIGHT:
+               if (l_fund == ENUM || r_fund == ENUM)
+                       warning("shift on enum");
+               break;
+
+       case ANDAB:
+       case ORAB:
+       case XORAB:
+               lint_conversion(right, l_fund);
+       case '&':
+       case '|':
+       case '^':
+               if (l_fund == ENUM || r_fund == ENUM)
+                       warning("bit operations on enum");
+               break;
+
+       case ',':
+       case '?':
+       case ':':
+       case AND:
+       case OR:
+       case POSTINCR:
+       case POSTDECR:
+       case PLUSPLUS:
+       case MINMIN:
+       case '(':
+       case '.':
+       case ARROW:
+       default:
+               /* OK with lint */
+               break;
+       }
+}
+
+PRIVATE
+lint_enum_arith(l_fund, oper, r_fund)
+       int l_fund, oper, r_fund;
+{
+       if (    l_fund == ENUM
+       &&      r_fund != CHAR
+       &&      r_fund != SHORT
+       &&      r_fund != INT
+       ) {
+               warning("%s on enum and %s",
+                       symbol2str(oper), symbol2str(r_fund));
+       }
+       else
+       if (    r_fund == ENUM
+       &&      l_fund != CHAR
+       &&      l_fund != SHORT
+       &&      l_fund != INT
+       ) {
+               warning("%s on %s and enum",
+                       symbol2str(oper), symbol2str(l_fund));
+       }
+}
+
+PRIVATE
+lint_conversion(from_expr, to_fund)
+       struct expr *from_expr;
+       int to_fund;
+{
+       register int from_fund = from_expr->ex_type->tp_fund;
+
+       /*      was there an attempt to reduce the type of the from_expr
+               of the form
+                       expr & 0377
+               or something like this?
+       */
+       if (from_expr->ex_class == Oper && from_expr->OP_OPER == INT2INT) {
+               from_expr = from_expr->OP_LEFT;
+       }
+       if (from_expr->ex_class == Oper && from_expr->OP_OPER == '&') {
+               struct expr *bits =
+                       is_cp_cst(from_expr->OP_LEFT) ? from_expr->OP_LEFT :
+                       is_cp_cst(from_expr->OP_RIGHT) ? from_expr->OP_RIGHT :
+                       0;
+
+               if (bits) {
+                       arith val = bits->VL_VALUE;
+
+                       if (val < 256)
+                               from_fund = CHAR;
+                       else if (val < 256)
+                               from_fund = SHORT;
+               }
+       }
+       if (numsize(from_fund) > numsize(to_fund)) {
+               awarning("conversion from %s to %s may lose accuracy",
+                       symbol2str(from_fund), symbol2str(to_fund));
+       }
+}
+
+PRIVATE int
+numsize(fund)
+{
+       switch (fund) {
+       case CHAR:      return 1;
+       case SHORT:     return 2;
+       case INT:       return 3;
+       case ENUM:      return 3;
+       case LONG:      return 4;
+       case FLOAT:     return 5;
+       case DOUBLE:    return 6;
+       default:        return 0;
+       }
+}
+
+lint_ret_conv(from_expr)
+       struct expr *from_expr;
+{
+       lint_conversion(from_expr, func_type->tp_fund);
+}
+
+lint_ptr_conv(from, to)
+       short from, to;
+{
+/* X -> X ok                   -- this includes struct -> struct, of any size
+ * X -> CHAR ok
+ * DOUBLE -> X ok
+ * FLOAT -> LONG -> INT -> SHORT  ok
+ */
+       if (from == to)
+               return;
+
+       if (to == CHAR)
+               return;
+
+       if (from == DOUBLE)
+               return;
+
+       switch (from) {
+       case FLOAT:
+               switch (to) {
+               case LONG:
+               case INT:
+               case SHORT:
+                       return;
+               }
+               break;
+       case LONG:
+               switch (to) {
+               case INT:
+               case SHORT:
+                       return;
+               }
+               break;
+       case INT:
+               switch (to) {
+               case SHORT:
+                       return;
+               }
+               break;
+       }
+
+       if (from == CHAR) {
+               hwarning("pointer to char may not align correctly for a %s",
+                       symbol2str(to));
+       }
+       else {
+               warning("pointer to %s may not align correctly for a %s",
+                       symbol2str(from), symbol2str(to));
+       }
+}
+
+lint_relop(left, right, oper)
+       struct expr *left, *right;
+       int oper;       /* '<', '>', LESSEQ, GREATEREQ, EQUAL, NOTEQUAL */
+{
+       /* left operand may be converted */
+       if (    left->ex_class == Oper
+       &&      left->OP_OPER == INT2INT
+       ) {
+               left = left->OP_RIGHT;
+       }
+
+       /* <unsigned> <relop> <neg-const|0> is doubtful */
+       if (    left->ex_type->tp_unsigned
+       &&      right->ex_class == Value
+       &&      right->VL_CLASS == Const
+       ) {
+               if (right->VL_VALUE < 0) {
+                       warning("unsigned compared to negative constant");
+               }
+               if (right->VL_VALUE == 0) {
+                       switch (oper) {
+                       case '<':
+                               warning("unsigned < 0 will always fail");
+                               break;
+
+                       case LESSEQ:
+                               warning("unsigned <= 0 is probably wrong");
+                               break;
+
+                       case GREATEREQ:
+                               warning("unsigned >= 0 will always succeed");
+                               break;
+                       }
+               }
+       }
+
+       /* <char> <relop> <neg-const> is undefined */
+       if (    left->ex_type->tp_fund == CHAR
+       &&      right->ex_class == Value
+       &&      right->VL_CLASS == Const
+       &&      (right->VL_VALUE < 0 || right->VL_VALUE > 127)
+       ) {
+               warning("character compared to negative constant");
+       }
+}
+
+#endif LINT
diff --git a/lang/cem/cemcom.ansi/l_outdef.c b/lang/cem/cemcom.ansi/l_outdef.c
new file mode 100644 (file)
index 0000000..ef31a1a
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint outdef construction        */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>
+#include       "interface.h"
+#include       "arith.h"
+#include       "assert.h"
+#include       "type.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "def.h"
+#include       "struct.h"
+#include       "field.h"
+#include       "idf.h"
+#include       "level.h"
+#include       "label.h"
+#include       "code.h"
+#include       "expr.h"
+#include       "l_lint.h"
+#include       "l_comment.h"
+#include       "l_outdef.h"
+#include       "l_class.h"
+
+extern char *bts2str();
+extern char *symbol2str();
+
+int stat_number = 9999;                        /* static scope number */
+struct outdef OutDef;
+
+PRIVATE struct outdef OutCall;
+
+PRIVATE local_EFDC();
+PRIVATE output_def();
+PRIVATE outargs();
+PRIVATE outarg();
+PRIVATE outargstring();
+PRIVATE outargtype();
+PRIVATE implicit_func_decl();
+PRIVATE fill_arg();
+
+lint_declare_idf(idf, sc)
+       struct idf *idf;
+       int sc;
+{
+       register struct def *def = idf->id_def;
+       register int is_function = def->df_type->tp_fund == FUNCTION;
+
+       if (level == L_GLOBAL) {
+               lint_ext_def(idf, sc);
+               if (is_function)
+                       def2decl(sc);
+               if (sc != TYPEDEF)
+                       outdef();
+       }
+       else
+       if (level >= L_LOCAL && sc != STATIC && is_function) {
+               local_EFDC(idf);
+       }
+}
+
+lint_ext_def(idf, sc)
+       struct idf *idf;
+{
+/* At this place the following fields of the outputdefinition can be
+ * filled:
+ *             name, stat_number, class, file, line, type.
+ * For variable definitions and declarations this will be all.
+ * For functions the fields nrargs and argtps are filled after parsing
+ * the arguments.
+ * The returns-field is known at the end of the function definition.
+ * sc indicates the storage class defined by the declaration specifier.
+ */
+       register struct def *def = idf->id_def;
+       register struct type *type = def->df_type;
+
+       OutDef.od_name = idf->id_text;
+       OutDef.od_statnr = (sc == STATIC ? stat_number : 0);
+
+       switch (type->tp_fund) {
+       case ERRONEOUS:
+               OutDef.od_class = XXDF;
+               break;
+       case FUNCTION:
+               /* For the moment assume it will be a definition.
+                * If no compound_statement follows, it is a declaration,
+                * in which case the class will be adjusted by def2decl().
+                */
+               OutDef.od_class = (sc == STATIC ? SFDF : EFDF);
+               break;
+       default:        /* a variable */
+               OutDef.od_class =
+                       sc == EXTERN ? EVDC :
+                       sc == STATIC ? SVDF : EVDF;
+               break;
+       }
+       OutDef.od_file = def->df_file;
+       OutDef.od_line = def->df_line;
+       OutDef.od_type = (type->tp_fund == FUNCTION ? type->tp_up : type);
+       OutDef.od_valreturned = NORETURN;
+}
+
+def2decl(sc)
+       int sc;
+{
+/* It was assumed we were parsing a function definition.
+ * There was no compound statement following, so actually it was a
+ * declaration. This function updates the class.
+ */
+       OutDef.od_class = (sc == STATIC ? XXDF : EFDC);
+}
+
+set_od_valreturned(n)
+{
+       OutDef.od_valreturned = n;
+}
+
+PRIVATE
+local_EFDC(idf)
+       struct idf *idf;
+{
+       struct outdef od;
+
+       od.od_class = EFDC;
+       od.od_statnr = 0;
+       od.od_name = idf->id_text;
+       od.od_file = idf->id_def->df_file;
+       od.od_line = idf->id_def->df_line;
+       od.od_type = idf->id_def->df_type->tp_up;
+       output_def(&od);
+       /* The other fields are not used for this class. */
+}
+
+lint_formals()
+{
+/* Make a list of tp_entries containing the types of the formal
+ * parameters of the function definition just parsed.
+ */
+       register struct stack_entry *se = stack_level_of(L_FORMAL1)->sl_entry;
+       register struct argument **hook = &OutDef.od_arg;
+       register int nrargs = 0;
+
+       while (se) {
+               register struct type *type = se->se_idf->id_def->df_type;
+               register struct argument *arg = new_argument();
+
+               /*      Do the conversions on the formals that could not be
+                       done in declare_idf().
+                       It is, unfortunately, impossible not to do them,
+                       since the corresponding actuals will have been
+                       converted to generate proper code and we do not
+                       want to duplicate the whole of expression handling
+                       for lint.
+               */
+               switch (type->tp_fund) {
+               case CHAR:
+               case SHORT:
+                       type = int_type;
+                       break;
+               case FLOAT:
+                       type = double_type;
+                       break;
+               }
+
+               if (f_FORMAT && nrargs == f_FORMATn) {
+                       if (    !f_FORMATvar
+                       &&      (       type->tp_fund != POINTER
+                               ||      type->tp_up->tp_fund != CHAR
+                               )
+                       ) {
+                               warning("format parameter %d is not pointer to char",
+                                       nrargs);
+                       }
+                       arg->ar_type = string_type;
+                       arg->ar_class = ArgString;
+                       arg->CAS_VALUE = f_FORMAT;
+                       arg->CAS_LEN = strlen(f_FORMAT);
+                       f_FORMAT = 0;
+               }
+               else {
+                       arg->ar_type = type;
+                       arg->ar_class = ArgFormal;
+               }
+               *hook = arg;
+               hook = &arg->next;
+
+               nrargs++;
+               se = se->next;
+       }
+
+       if (f_FORMAT) {
+               /*      f_FORMAT has not been consumed, perhaps due to
+                       a varargs-like construction; add erroneous ArgFormals
+                       until f_FORMATn, then an ArgString, if necessary.
+               */
+               if (!f_FORMATvar) {
+                       warning("FORMAT%d function has only %d argument%s",
+                               f_FORMATn, nrargs, nrargs == 1 ? "" : "s"
+                       );
+               }
+
+               while (nrargs < f_FORMATn) {
+                       register struct argument *arg = new_argument();
+                       
+                       arg->ar_type = error_type;
+                       arg->ar_class = ArgFormal;
+                       *hook = arg;
+                       hook = &arg->next;
+                       nrargs++;
+               }
+               if (nrargs == f_FORMATn) {
+                       register struct argument *arg = new_argument();
+                       
+                       arg->ar_type = string_type;
+                       arg->ar_class = ArgString;
+                       arg->CAS_VALUE = f_FORMAT;
+                       arg->CAS_LEN = strlen(f_FORMAT);
+                       f_FORMAT = 0;
+                       *hook = arg;
+                       hook = &arg->next;
+                       nrargs++;
+               }
+               /* life is full of duplicated code; this is no good */
+       }
+
+       if (f_VARARGSn > nrargs) {
+               warning("VARARGS%d function has only %d argument%s",
+                       f_VARARGSn, nrargs, nrargs == 1 ? "" : "s"
+               );
+               f_VARARGSn = nrargs;
+       }
+       OutDef.od_nrargs = nrargs;
+}
+
+output_use(idf)
+       struct idf *idf;
+{
+/* Output the usage-definition of the variable described by idf.
+ */
+       OutDef.od_name = idf->id_text;
+       OutDef.od_statnr = (idf->id_def->df_sc == STATIC ? stat_number : 0);
+       OutDef.od_class = VU;
+       OutDef.od_file = FileName;
+       OutDef.od_line = LineNumber;
+       OutDef.od_type = idf->id_def->df_type;
+       outdef();
+}
+
+outdef()
+{
+       output_def(&OutDef);
+}
+
+outcall()
+{
+       output_def(&OutCall);
+}
+
+PRIVATE
+output_def(od)
+       struct outdef *od;
+{
+/* As the types are output the tp_entries are removed, because they
+ * are then not needed anymore.
+ */
+       if (od->od_class == XXDF)
+               return;
+
+       if (LINTLIB) {
+               switch (od->od_class) {
+               case EFDF:
+                       od->od_class = LFDF;
+                       break;
+               case EVDF:
+                       od->od_class = LVDF;
+                       break;
+               case SFDF:
+                       /* remove tp_entries */
+                       while (od->od_arg) {
+                               register struct argument *tmp = od->od_arg;
+                               od->od_arg = od->od_arg->next;
+                               free_argument(tmp);
+                       }
+                       return;
+               default:
+                       return;
+               }
+       }
+       printf("%s:%d:%c", od->od_name, od->od_statnr, od->od_class);
+       switch (od->od_class) {
+       case EFDF:
+       case SFDF:
+       case LFDF:
+               if (f_VARARGSn != -1) {
+                       printf(":%d", -1 - f_VARARGSn);
+                       outargs(od->od_arg, f_VARARGSn);
+               }
+               else {
+                       printf(":%d", od->od_nrargs);
+                       outargs(od->od_arg, od->od_nrargs);
+               }
+               od->od_arg = 0;
+               printf(":%d", od->od_valreturned);
+               break;
+       case FC:
+               printf(":%d", od->od_nrargs);
+               outargs(od->od_arg, od->od_nrargs);
+               od->od_arg = 0;
+               printf(":%d", od->od_valused);
+               break;
+       case EVDF:
+       case SVDF:
+       case LVDF:
+       case EFDC:
+       case EVDC:
+       case IFDC:
+       case VU:
+               break;
+       default:
+               NOTREACHED();
+               /*NOTREACHED*/
+       }
+       printf(":");
+       outargtype(od->od_type);
+       printf(":%u:%s\n", od->od_line, od->od_file);
+}
+
+PRIVATE
+outargs(arg, n)
+       struct argument *arg;
+{
+/* Output the n arguments in the argument list and remove them */
+
+       register struct argument *tmp;
+
+       while (n--) {
+               ASSERT(arg);
+               outarg(arg);
+               tmp = arg;
+               arg = arg->next;
+               free_argument(tmp);
+       }
+       /* remove the remaining entries */
+       while (arg) {
+               tmp = arg;
+               arg = arg->next;
+               free_argument(tmp);
+       }
+}
+
+PRIVATE
+outarg(arg)
+       struct argument *arg;
+{
+       printf(":");
+       switch (arg->ar_class) {
+       case ArgConst:
+               if (arg->CAA_VALUE >= 0) {
+                       /* constant non-negative actual parameter */
+                       printf("+");
+               }
+               outargtype(arg->ar_type);
+               break;
+
+       case ArgString:
+               outargstring(arg);
+               break;
+
+       case ArgFormal:
+       case ArgExpr:
+               outargtype(arg->ar_type);
+               if (arg->ar_type->tp_fund == FUNCTION) {
+                       /* UGLY PATCH !!! ??? */
+                       /*      function names as operands are sometimes
+                               FUNCTION and sometimes POINTER to FUNCTION,
+                               depending on opaque circumstances.  E.g., in
+                                       f(main, main);
+                               the first main is PtF and the second is F.
+                       */
+                       printf("*");
+               }
+               break;
+
+       default:
+               NOTREACHED();
+               /*NOTREACHED*/
+       }
+}
+
+PRIVATE
+outargstring(arg)
+       struct argument *arg;
+{
+       char buff[1000];
+       register char *p;
+
+       bts2str(arg->CAS_VALUE, arg->CAS_LEN, buff);
+       for (p = &buff[0]; *p; p++) {
+               if (*p == '"' || *p == ':')
+                       *p = ' ';
+       }
+       printf("\"%s\"", buff);
+}
+
+PRIVATE
+outargtype(tp)
+       struct type *tp;
+{
+       switch (tp->tp_fund) {
+       case POINTER:
+               outargtype(tp->tp_up);
+               printf("*");
+               break;
+
+       case ARRAY:
+               outargtype(tp->tp_up);
+               printf("*");    /* compatible with [] */
+               break;
+
+       case FUNCTION:
+               outargtype(tp->tp_up);
+               printf("()");
+               break;
+
+       case STRUCT:
+       case UNION:
+       case ENUM:
+               printf("%s %s", symbol2str(tp->tp_fund), tp->tp_idf->id_text);
+               break;
+
+       case CHAR:
+       case INT:
+       case SHORT:
+       case LONG:
+       case FLOAT:
+       case DOUBLE:
+       case VOID:
+       case ERRONEOUS:
+               if (tp->tp_unsigned)
+                       printf("unsigned ");
+               printf("%s", symbol2str(tp->tp_fund));
+               break;
+       default:
+               NOTREACHED();
+               /*NOTREACHED*/
+       }
+}
+
+PRIVATE
+implicit_func_decl(idf, file, line)
+       struct idf *idf;
+       char *file;
+       unsigned int line;
+{
+       struct outdef od;
+
+       od.od_class = IFDC;
+       od.od_statnr = 0;
+       od.od_name = idf->id_text;
+       od.od_file = file;
+       od.od_line = line;
+       od.od_type = idf->id_def->df_type->tp_up;
+       output_def(&od);
+       /* The other fields are not used for this class. */
+}
+
+fill_outcall(ex, used)
+       struct expr *ex;
+       int used;
+{
+       register struct idf *idf = ex->OP_LEFT->VL_IDF;
+       register struct def *def = idf->id_def;
+
+       if (def->df_sc == IMPLICIT && !idf->id_def->df_used) {
+               /* IFDC, first time */
+               implicit_func_decl(idf, ex->ex_file, ex->ex_line);
+       }
+
+       OutCall.od_type = def->df_type->tp_up;
+       OutCall.od_statnr = (def->df_sc == STATIC ? stat_number : 0);
+       OutCall.od_class = FC;
+       OutCall.od_name = idf->id_text;
+       OutCall.od_file = ex->ex_file;
+       OutCall.od_line = ex->ex_line;
+       OutCall.od_arg = (struct argument *)0;
+       OutCall.od_nrargs = 0;
+
+       if ((ex = ex->OP_RIGHT) != 0) { /* function call with arguments */
+               /* store types of argument expressions in tp_entries */
+               while (ex->ex_class == Oper && ex->OP_OPER == PARCOMMA) {
+                       fill_arg(ex->OP_RIGHT);
+                       ex = ex->OP_LEFT;
+               }
+               fill_arg(ex);
+       }
+       OutCall.od_valused = used;      /* USED, IGNORED or VOIDED */
+}
+
+PRIVATE
+fill_arg(e)
+       struct expr *e;
+{
+       register struct argument *arg;
+
+       arg = new_argument();
+       arg->ar_type = e->ex_type;
+       if (is_cp_cst(e)) {
+               arg->ar_class = ArgConst;
+               arg->CAA_VALUE = e->VL_VALUE;
+       }
+       else if (e->ex_class == Value && e->VL_CLASS == Label) {
+               /* it may be a string; let's look it up */
+               register struct string_cst *sc = str_list;
+
+               while (sc) {
+                       if (sc->sc_dlb == e->VL_LBL)
+                               break;
+                       sc = sc->next;
+               }
+               if (sc) {
+                       /* it was a string */
+                       arg->ar_class = ArgString;
+                       arg->CAS_VALUE = sc->sc_value;
+                       arg->CAS_LEN = sc->sc_len - 1;  /* included the \0 */
+               }
+               else {
+                       arg->ar_class = ArgExpr;
+               }
+       }
+       else {
+               arg->ar_class = ArgExpr;
+       }
+       arg->next = OutCall.od_arg;
+       OutCall.od_arg = arg;
+       OutCall.od_nrargs++;
+}
+
+#endif LINT
diff --git a/lang/cem/cemcom.ansi/l_outdef.str b/lang/cem/cemcom.ansi/l_outdef.str
new file mode 100644 (file)
index 0000000..541fbcd
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint output definition  */
+
+/* Values for ar_class */
+#define        ArgFormal       0
+#define        ArgExpr         1               /* actual */
+#define        ArgConst        2               /* integer constant */
+#define        ArgString       3               /* string */
+
+struct argument {
+       struct argument *next;
+       struct type *ar_type;
+       int ar_class;                   /* for constant parameters */
+       union const_arg {
+               arith ca_value;
+               struct {
+                       char *cas_value;
+                       int cas_len;
+               } ca_string;
+       } ar_object;
+};
+
+#define        CAA_VALUE       ar_object.ca_value
+#define        CAS_VALUE       ar_object.ca_string.cas_value
+#define        CAS_LEN         ar_object.ca_string.cas_len
+
+/* ALLOCDEF "argument" 10 */
+
+struct outdef {
+       char od_class;
+       int od_statnr;
+       char *od_name;
+       char *od_file;
+       unsigned int od_line;
+       int od_nrargs;
+       struct argument *od_arg;        /* a list of the types of the
+                                        * formal parameters */
+       int od_valreturned;
+               /* NOVALRETURNED, VALRETURNED, NORETURN; see l_lint.h */
+       int od_valused;
+               /* USED, IGNORED, SET, VOIDED; see l_lint.h */
+       struct type *od_type;
+};
diff --git a/lang/cem/cemcom.ansi/l_state.str b/lang/cem/cemcom.ansi/l_state.str
new file mode 100644 (file)
index 0000000..2ef9191
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint state stack        */
+
+/* These datastructures are used to implement a stack on which the
+ * state of automatic variables (including register variables) is
+ * kept.
+ * In this way it is possible to account for the flow of
+ * control of the program.
+ */
+
+
+struct switch_states {
+       struct state *sws_case;
+       struct state *sws_break;
+       int sws_default_met;
+};
+
+struct lint_stack_entry {
+       struct lint_stack_entry *next;
+       struct lint_stack_entry *ls_previous;
+       short ls_class;         /* IF, WHILE, DO, FOR, SWITCH, CASE */
+       int ls_level;
+       struct state *ls_current;               /* used by all classes */
+       union {
+               struct state *u_if_state;       /* used for IF-class */
+               struct state *u_end;            /* used for loop-classes */
+               struct switch_states u_switch;
+       } ls_states;    /* not used for CASE-class */
+};
+
+/* macros to access the union */
+#define LS_IF_STATE    ls_states.u_if_state
+#define LS_END         ls_states.u_end
+#define LS_CASE                ls_states.u_switch.sws_case
+#define LS_BREAK       ls_states.u_switch.sws_break
+#define LS_DEFAULT_MET ls_states.u_switch.sws_default_met
+
+/* ALLOCDEF "lint_stack_entry" 10 */
+
+struct state {
+       struct state *next;             /* only used by memory allocator */
+       struct auto_def *st_auto_list;
+       int st_notreached;              /* set if not reached */
+       int st_warned;                  /* set if warning issued */
+};
+
+/* ALLOCDEF "state" 15 */
+
+struct auto_def {
+       struct auto_def *next;
+       struct idf *ad_idf;
+       struct def *ad_def;
+       int ad_used;
+       int ad_set;
+       int ad_maybe_set;
+};
+
+/* ALLOCDEF "auto_def" 20 */
+
+struct expr_state {
+       struct expr_state *next;
+       struct idf *es_idf;
+       arith es_offset;
+       int es_used;
+       int es_referred;
+       int es_set;
+};
+
+/* ALLOCDEF "expr_state" 20 */
+
diff --git a/lang/cem/cemcom.ansi/l_states.c b/lang/cem/cemcom.ansi/l_states.c
new file mode 100644 (file)
index 0000000..ad47b97
--- /dev/null
@@ -0,0 +1,1131 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     Lint status checking    */
+
+#include       "lint.h"
+
+#ifdef LINT
+
+#include       <alloc.h>       /* for st_free */
+#include       "interface.h"
+#include       "assert.h"
+#include       "debug.h"
+#include       "arith.h"       /* definition arith */
+#include       "label.h"       /* definition label */
+#include       "expr.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "code.h"        /* RVAL etc */
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "stack.h"
+#include       "type.h"
+#include       "level.h"
+#include       "nofloat.h"
+#include       "l_lint.h"
+#include       "l_brace.h"
+#include       "l_state.h"
+#include       "l_comment.h"
+#include       "l_outdef.h"
+
+#define min(a, b) ((a) < (b) ? (a) : (b))
+
+extern char *symbol2str();
+extern char *func_name;
+extern struct type *func_type;
+extern int func_notypegiven;
+extern char loptions[];
+
+/* global variables for the lint_stack */
+PRIVATE struct lint_stack_entry stack_bottom;
+PRIVATE struct lint_stack_entry *top_ls = &stack_bottom;
+
+/* global variables for the brace stack */
+PRIVATE int brace_count;
+PRIVATE struct brace brace_bottom;
+PRIVATE struct brace *top_br = &brace_bottom;
+
+PRIVATE end_brace();
+PRIVATE lint_1_local();
+PRIVATE lint_1_global();
+PRIVATE check_autos();
+PRIVATE struct auto_def *copy_st_auto_list();
+PRIVATE free_st_auto_list();
+PRIVATE struct state *copy_state();
+PRIVATE Free_state();
+PRIVATE remove_settings();
+PRIVATE struct auto_def *merge_autos();
+PRIVATE merge_states();
+PRIVATE struct lint_stack_entry *find_wdf(), *find_wdfc(), *find_cs();
+PRIVATE cont_break_merge();
+PRIVATE lint_push();
+PRIVATE lint_pop();
+
+lint_init_stack()
+{
+/* Allocate some memory for the global stack_bottom
+ */
+       stack_bottom.ls_current = new_state();
+}
+
+lint_start_local()
+{
+       register struct brace *br = new_brace();
+
+       brace_count++;
+       br->br_count = brace_count;
+       br->br_level = level;
+       br->next = top_br;
+       top_br = br;
+}      
+
+lint_local_level(stl)
+       struct stack_level *stl;
+{
+       if (s_NOTREACHED) {
+               top_ls->ls_current->st_notreached = 1;
+               s_NOTREACHED = 0;
+       }
+
+       if (top_ls->ls_class == CASE && level == top_ls->ls_level) {
+               lint_break_stmt();
+                       /* To prevent a warning for the case
+                        *      switch (cond) {
+                        *      int i;
+                        *      case 0:
+                        *              i = 0;
+                        *              use(i);
+                        *      }
+                        */
+       }
+
+       check_autos();
+       end_brace(stl);
+}
+
+PRIVATE
+end_brace(stl)
+       struct stack_level *stl;
+{
+       /*      Check if static variables and labels are used and/or set.
+       */
+       register struct stack_entry *se = stl->sl_entry;
+       register struct brace *br;
+
+       while (se) {
+               register struct idf *idf = se->se_idf;
+               register struct def *def = idf->id_def;
+
+               if (def) {
+                       lint_1_local(idf, def);
+               }
+               se = se->next;
+       }
+
+       br = top_br;
+       top_br = br->next;
+       free_brace(br);
+}
+
+PRIVATE
+lint_1_local(idf, def)
+       struct idf *idf;
+       struct def *def;
+{
+       register int sc = def->df_sc;
+
+       if (    (sc == STATIC || sc == LABEL)
+       &&      !def->df_used
+       ) {
+               def_warning(def, "%s %s declared but not used in function %s",
+                       symbol2str(sc), idf->id_text, func_name);
+       }
+
+       if (    loptions['h']
+       &&      sc == AUTO
+       &&      !def->df_initialized
+       &&      def->df_firstbrace != 0
+       &&      def->df_minlevel != level
+       ) {
+               register int diff = def->df_minlevel - level;
+
+               def_warning(def,
+                       "local %s could be declared %d level%s deeper",
+                       idf->id_text, diff, (diff == 1 ? "" : "s")
+               );
+       }
+}
+
+lint_global_level(stl)
+       struct stack_level *stl;
+{
+       register struct stack_entry *se = stl->sl_entry;
+
+       ASSERT(level == L_GLOBAL);
+       while (se) {
+               register struct idf *idf = se->se_idf;
+               register struct def *def = idf->id_def;
+
+               if (def) {
+                       lint_1_global(idf, def);
+               }
+               se = se->next;
+       }
+}
+
+PRIVATE
+lint_1_global(idf, def)
+       struct idf *idf;
+       struct def *def;
+{
+       register int sc = def->df_sc;
+       register int fund = def->df_type->tp_fund;
+
+       switch (sc) {
+       case STATIC:
+       case EXTERN:
+       case GLOBAL:
+       case IMPLICIT:
+               if (fund == ERRONEOUS)
+                       break;
+
+               if (def->df_set || def->df_used) {
+                       /* Output a line to the intermediate file for
+                        * used external variables (including functions)
+                        */
+                       output_use(idf);
+               }
+               else {
+                       if (sc == STATIC) {
+                               if (def->df_set) {
+                                       def_warning(def,
+                                               "%s %s %s set but not used",
+                                               symbol2str(sc),
+                                               symbol2str(fund),
+                                               idf->id_text);
+                               }
+                               else {
+                                       def_warning(def,
+                                               "%s %s %s not used anywhere",
+                                               symbol2str(sc),
+                                               symbol2str(fund),
+                                               idf->id_text);
+                               }
+                       }
+                       if (loptions['x']) {
+                               register char *fn = def->df_file;
+
+                               if (    (sc == EXTERN || sc == GLOBAL)
+                               &&      def->df_alloc == 0
+                               &&      !def->df_set
+                               &&      !def->df_initialized
+                               &&      strcmp(&fn[strlen(fn)-2], ".c") == 0
+                               ) {
+                                       def_warning(def,
+                                               "%s %s %s not used anywhere",
+                                               symbol2str(sc),
+                                               symbol2str(fund),
+                                               idf->id_text);
+                               }
+                       }
+               }
+               break;
+       }
+}
+
+change_state(idf, to_state)
+       struct idf *idf;
+       int to_state;                   /* SET or USED */
+{
+/* Changes the state of the variable identified by idf in the current state
+ * on top of the stack.
+ * For non-automatic variables, the fields in the def-descriptor are set too.
+ */
+       register struct def *def = idf->id_def;
+       register struct auto_def *a = top_ls->ls_current->st_auto_list;
+
+       if (def) {
+               switch (to_state) {
+               case SET:
+                       def->df_set = 1;
+                       break;
+               case USED:
+                       def->df_used = 1;
+                       break;
+               }
+
+               if (def->df_firstbrace == 0) {
+                       def->df_firstbrace = brace_count;
+                       def->df_minlevel = level;
+               }
+               else {
+                       register struct brace *br = top_br;
+
+                       /*      find the smallest brace range from which
+                               firstbrace is visible
+                       */
+                       while (br && br->br_count > def->df_firstbrace) {
+                               br = br->next;
+                       }
+                       ASSERT(br && def->df_minlevel >= br->br_level);
+                       def->df_minlevel = br->br_level;
+               }
+       }
+
+       while(a && a->ad_idf != idf)
+               a = a->next;
+       if (a == 0)     /* identifier not in list */
+               return;
+
+       switch (to_state) {
+       case SET:
+               a->ad_maybe_set = 0;
+               a->ad_set = 1;
+               break;
+       case USED:
+               if (!a->ad_set) {
+                       warning("%s%s uninitialized", idf->id_text,
+                               (a->ad_maybe_set ? " possibly" : "")
+                       );
+                       a->ad_maybe_set = 0;
+                       a->ad_set = 1;  /* one warning */
+               }
+               a->ad_used = 1;
+               break;
+       }
+}
+
+extern struct stack_level *local_level;
+
+add_auto(idf)  /* to current state on top of lint_stack */
+       struct idf *idf;
+{
+/* Check if idf's definition is really an auto (or register).
+ * It could be a static or extern too.
+ * Watch out for register formal parameters.
+ */
+       register struct def *def = idf->id_def;
+       register struct auto_def *a;
+
+       if (!def)
+               return;
+       switch (def->df_sc) {
+       case AUTO:
+       case REGISTER:
+               if (def->df_level < L_LOCAL)
+                       return;         /* a register formal */
+               a = new_auto_def();
+               a->ad_idf = idf;
+               a->ad_def = idf->id_def;
+               a->ad_used = def->df_used;
+               a->ad_set = def->df_set;
+               a->next = top_ls->ls_current->st_auto_list;
+               top_ls->ls_current->st_auto_list = a;
+       }
+}
+
+PRIVATE
+check_autos()
+{
+/* Before leaving a block remove the auto_defs of the automatic
+ * variables on this level and check if they are used
+ */
+       register struct auto_def *a1 = top_ls->ls_current->st_auto_list;
+       register struct auto_def *a2;
+
+       ASSERT(!(a1 && a1->ad_def->df_level > level));
+       while (a1 && a1->ad_def->df_level == level) {
+               a2 = a1;
+               a1 = a1->next;
+               if (!a2->ad_used) {
+                       if (a2->ad_set || a2->ad_maybe_set) {
+                               def_warning(a2->ad_def,
+                                       "%s set but not used in function %s",
+                                       a2->ad_idf->id_text, func_name);
+                       }
+                       else {
+                               def_warning(a2->ad_def,
+                                       "%s neither set nor used in function %s",
+                                       a2->ad_idf->id_text, func_name);
+                       }
+               }
+               free_auto_def(a2);
+       }
+       top_ls->ls_current->st_auto_list = a1;
+}
+
+check_args_used()
+{
+       register struct stack_entry *se = local_level->sl_entry;
+
+       ASSERT(level == L_FORMAL1);
+       while (se) {
+               register struct def *def = se->se_idf->id_def;
+
+               if (    (def && !def->df_used)
+               &&      !(f_ARGSUSED || LINTLIB)
+               ) {
+                       def_warning(def, "argument %s not used in function %s",
+                                       se->se_idf->id_text, func_name);
+               }
+               se = se->next;
+       }
+}
+
+PRIVATE struct auto_def *
+copy_st_auto_list(from_al, lvl)
+       struct auto_def *from_al;
+{
+       struct auto_def *start = 0;
+       register struct auto_def **hook = &start;
+
+       while (from_al && from_al->ad_def->df_level > lvl) {
+               from_al = from_al->next;
+       }
+       while (from_al) {
+               register struct auto_def *a = new_auto_def();
+
+               *hook = a;
+               *a = *from_al;
+               hook = &a->next;
+               from_al = from_al->next;
+       }
+
+       return start;
+}
+
+PRIVATE
+free_st_auto_list(au)
+       register struct auto_def *au;
+{
+       register struct auto_def *a;
+
+       while (au) {
+               a = au;
+               au = au->next;
+               free_auto_def(a);
+       }
+}
+
+PRIVATE struct state *
+copy_state(from_st, lvl)
+       struct state *from_st;
+{
+/* Memory for the struct state and the struct auto_defs is allocated
+ * by this function
+ */
+       register struct state *st = new_state();
+
+       st->st_auto_list = copy_st_auto_list(from_st->st_auto_list, lvl);
+       st->st_notreached = from_st->st_notreached;
+       st->st_warned = from_st->st_warned;
+       return st;
+}
+
+PRIVATE
+Free_state(stp)
+       struct state **stp;
+{
+/* This function also frees the list of auto_defs
+ */
+       free_st_auto_list((*stp)->st_auto_list);
+       free_state(*stp);
+       *stp = 0;
+}
+
+PRIVATE
+remove_settings(state, lvl)
+       struct state *state;
+{
+/* The state of all variables on this level are set to 'not set' and
+ * 'not maybe set'. (I think you have to read this twice.)
+ */
+       register struct auto_def *a = state->st_auto_list;
+
+       while (a && a->ad_def->df_level == lvl) {
+               a->ad_set = a->ad_maybe_set = 0;
+               a = a->next;
+       }
+}
+
+
+/******** M E R G E ********/
+
+/* modes for merging */
+#define        NORMAL          0
+#define        CASE_BREAK      1
+#define        USE_ONLY        2
+
+PRIVATE struct auto_def *
+merge_autos(a1, a2, lvl, mode)
+       struct auto_def *a1, *a2;
+       int mode;
+{
+/* Returns a pointer to the result.
+ * a1 is left unchanged.
+ * a2 is used to create this result.
+ * The fields are set as follows:
+ *     a1_set + a2_set         -> set
+ *             + a?_maybe_set  -> maybe set
+ *             ELSE            -> NOT set && NOT maybe set
+ *     *       + a?_used       -> used
+ *
+ * For mode == CASE_BREAK:
+ * First a2 is taken as the result, then
+ * variables NOT set in a2 and set or maybe set in a1 become 'maybe set'
+ *
+ * For mode == USE_ONLY:
+ * Start with a2 as the result.
+ * Variables used in a1 become used in a2.
+ * The rest of the result is not changed.
+ */
+       register struct auto_def *a;
+
+       while (a1 && a1->ad_def->df_level > lvl) {
+               a1 = a1->next;
+       }
+       while (a2 && a2->ad_def->df_level > lvl) {
+               a = a2;
+               a2 = a2->next;
+               free_auto_def(a);
+       }
+       a = a2; /* pointer to the result */
+       while (a1) {
+               ASSERT(a2);
+               ASSERT(a1->ad_idf == a2->ad_idf);
+               if (a1->ad_used)
+                       a2->ad_used = 1;
+
+               if (mode != USE_ONLY) {
+                       if (    (       !a2->ad_set
+                               &&      (a1->ad_set || a1->ad_maybe_set)
+                               )
+                       ||      (       mode == NORMAL
+                               &&      !a1->ad_set
+                               &&      (a2->ad_set || a2->ad_maybe_set)
+                               )
+                       ) {
+                               a2->ad_set = 0;
+                               a2->ad_maybe_set = 1;
+                       }
+               }
+
+               a1 = a1->next;
+               a2 = a2->next;
+       }
+       ASSERT(!a2);
+       return a;
+}
+
+PRIVATE
+merge_states(st1, st2, lvl, mode)
+       struct state *st1, *st2;
+       int mode;
+{
+/* st2 becomes the result.
+ * st1 is left unchanged.
+ * The resulting state is the state the program gets in if st1 OR st2
+ * becomes the state. (E.g. the states at the end of an if-part and an
+ * end-part are merged by this function.)
+ */
+       if (st1->st_notreached) {
+               if (mode == NORMAL || st2->st_notreached) {
+                       st2->st_auto_list =
+                               merge_autos(st1->st_auto_list,
+                                       st2->st_auto_list, lvl, USE_ONLY);
+               }
+       }
+       else if (st2->st_notreached) {
+               register struct auto_def *tmp = st2->st_auto_list;
+
+               st2->st_auto_list = copy_st_auto_list(st1->st_auto_list, lvl);
+               st2->st_notreached = 0;
+               st2->st_warned = 0;
+               st2->st_auto_list = merge_autos(tmp, st2->st_auto_list,
+                                                       lvl, USE_ONLY);
+               free_st_auto_list(tmp);
+       }
+       else {
+               st2->st_auto_list =
+                       merge_autos(st1->st_auto_list, st2->st_auto_list,
+                               lvl, mode);
+       }
+}
+
+
+/******** L I N T   S T A C K   S E A R C H I N G ********/
+
+/* The next four find-functions search the lint_stack for an entry.
+ * The letters mean : w: WHILE; d: DO; f: FOR; s: SWITCH; c: CASE.
+ */
+
+PRIVATE struct lint_stack_entry *
+find_wdf()
+{
+       register struct lint_stack_entry *lse = top_ls;
+
+       while (lse != &stack_bottom) {
+               switch (lse->ls_class) {
+               case WHILE:
+               case DO:
+               case FOR:
+                       return lse;
+               }
+               lse = lse->ls_previous;
+       }
+       return 0;
+}
+
+PRIVATE struct lint_stack_entry *
+find_wdfc()
+{
+       register struct lint_stack_entry *lse = top_ls;
+
+       while (lse != &stack_bottom) {
+               switch (lse->ls_class) {
+               case WHILE:
+               case DO:
+               case FOR:
+               case CASE:
+                       return lse;
+               }
+               lse = lse->ls_previous;
+       }
+       return 0;
+}
+
+PRIVATE struct lint_stack_entry *
+find_cs()
+{
+       register struct lint_stack_entry *lse = top_ls;
+
+       while (lse != &stack_bottom) {
+               switch (lse->ls_class) {
+               case CASE:
+               case SWITCH:
+                       return lse;
+               }
+               lse = lse->ls_previous;
+       }
+       return 0;
+}
+
+/******** A C T I O N S ********/
+
+start_if_part(const)
+{
+/* Push a new stack entry on the lint_stack with class == IF
+ * copy the ls_current to the top of this stack
+ */
+       register struct lint_stack_entry *lse = new_lint_stack_entry();
+
+       if (const)
+               hwarning("condition in if statement is constant");
+
+       lse->ls_class = IF;
+       lse->ls_current = copy_state(top_ls->ls_current, level);
+       lse->ls_level = level;
+       lint_push(lse);
+}
+
+start_else_part()
+{
+/* Move ls_current to LS_IF_STATE
+ * ls_current of the stack entry one below is copied to ls_current.
+ */
+       if (s_NOTREACHED) {
+               top_ls->ls_current->st_notreached = 1;
+               s_NOTREACHED = 0;
+       }
+       top_ls->LS_IF_STATE = top_ls->ls_current;
+       /* this is the reason why ls_current is a pointer */
+       top_ls->ls_current = copy_state(top_ls->ls_previous->ls_current,
+                                                               level);
+       top_ls->ls_level = level;
+}
+
+end_if_else_stmt()
+{
+       Free_state(&top_ls->ls_previous->ls_current);
+       merge_states(top_ls->LS_IF_STATE, top_ls->ls_current,
+                                       top_ls->ls_level, NORMAL);
+       Free_state(&top_ls->LS_IF_STATE);
+       top_ls->ls_previous->ls_current = top_ls->ls_current;
+       lint_pop();
+}
+
+end_if_stmt()
+{
+/* No else-part met; merge ls_current with ls_current of previous
+ * stack entry
+ */
+       merge_states(top_ls->ls_current, top_ls->ls_previous->ls_current,
+                                               top_ls->ls_level, NORMAL);
+       Free_state(&top_ls->ls_current);
+       lint_pop();
+}
+
+start_loop_stmt(looptype, const, cond)
+{
+/* If const, the condition is constant and given in cond */
+       register struct lint_stack_entry *lse = new_lint_stack_entry();
+
+       lse->ls_class = looptype;
+       lse->ls_current = copy_state(top_ls->ls_current, level);
+       lse->ls_level = level;
+       if (const && !cond) {
+               /* while (0) | for (;0;) */
+               hwarning("condition in %s statement is constant",
+                                               symbol2str(looptype));
+               lse->ls_current->st_notreached = 1;
+       }
+       if (const && cond) {
+               /* while (1) | for (;;) | do */
+               /*      omitting the copy for LS_END will force this loop
+                       to be treated as a do loop
+               */
+               top_ls->ls_current->st_notreached = 1;
+       }
+       else {
+               lse->LS_END = copy_state(top_ls->ls_current, level);
+       }
+       lint_push(lse);
+}
+
+end_loop_stmt()
+{
+       register struct lint_stack_entry *prev_ls = top_ls->ls_previous;
+
+       lint_continue_stmt();
+       top_ls->LS_END->st_notreached = prev_ls->ls_current->st_notreached;
+       top_ls->LS_END->st_warned = prev_ls->ls_current->st_warned;
+       Free_state(&top_ls->ls_current);
+       Free_state(&prev_ls->ls_current);
+       prev_ls->ls_current = top_ls->LS_END;
+       lint_pop();
+}
+
+end_do_stmt(const, cond)
+{
+       end_loop_stmt();
+       if (const)
+               hwarning("condition in do-while statement is constant");
+       if (const && cond && top_ls->ls_current->st_notreached) {
+               /* no break met; this is really an endless loop */
+       }
+       else {
+               top_ls->ls_current->st_notreached = 0;
+       }
+}
+
+PRIVATE
+cont_break_merge(lse)
+       struct lint_stack_entry *lse;
+{
+       /* merge for continue and break statements */
+       if (lse->LS_END) {
+               merge_states(top_ls->ls_current, lse->LS_END,
+                                               lse->ls_level, NORMAL);
+       }
+       else {
+               lse->LS_END = copy_state(top_ls->ls_current, lse->ls_level);
+       }
+}
+
+lint_continue_stmt()
+{
+       register struct lint_stack_entry *lse = find_wdf();
+
+       if (!lse)
+               return;         /* not inside a loop statement */
+
+       cont_break_merge(lse);
+       top_ls->ls_current->st_notreached = 1;
+}
+
+start_switch_part(expr)
+       struct expr *expr;
+{
+/* ls_current of a SWITCH entry has different meaning from ls_current of
+ * other entries. It keeps track of which variables are used in all
+ * following case parts. (Needed for variables declared in a compound
+ * switch-block.)
+ */
+       register struct lint_stack_entry *lse = new_lint_stack_entry();
+
+       if (is_cp_cst(expr))
+               hwarning("value in switch statement is constant");
+
+       lse->ls_class = SWITCH;
+       lse->ls_current = copy_state(top_ls->ls_current, level);
+       lse->ls_level = level;
+       lse->LS_CASE = copy_state(top_ls->ls_current, level);
+       lse->ls_current->st_notreached = 1;
+       top_ls->ls_current->st_notreached = 1;
+       lint_push(lse);
+}
+
+end_switch_stmt()
+{
+       if (top_ls->ls_class == CASE) {
+               /* no break after last case or default */
+               lint_break_stmt();      /* introduce break */
+       }
+
+       if (!top_ls->LS_DEFAULT_MET) {
+               top_ls->ls_current->st_notreached = 0;
+               if (top_ls->LS_BREAK) {
+                       merge_states(top_ls->ls_current, top_ls->LS_BREAK,
+                                               top_ls->ls_level, NORMAL);
+                       Free_state(&top_ls->ls_current);
+               }
+               else {
+                       top_ls->LS_BREAK = top_ls->ls_current;
+               }
+       }
+       else {
+               Free_state(&top_ls->ls_current);
+       }
+
+       if (top_ls->LS_BREAK) {
+               merge_states(top_ls->LS_CASE, top_ls->LS_BREAK,
+                                               top_ls->ls_level, CASE_BREAK);
+               Free_state(&top_ls->LS_CASE);
+       }
+       else {
+               top_ls->LS_BREAK = top_ls->LS_CASE;
+       }
+
+       top_ls->LS_BREAK->st_notreached =
+                       top_ls->ls_previous->ls_current->st_notreached;
+                               /* yack */
+       Free_state(&top_ls->ls_previous->ls_current);
+
+       if (!top_ls->LS_DEFAULT_MET)
+               top_ls->LS_BREAK->st_notreached = 0;
+       top_ls->ls_previous->ls_current = top_ls->LS_BREAK;
+
+       lint_pop();
+}
+
+lint_case_stmt(dflt)
+{
+/* A default statement is just a special case statement */
+
+       register struct lint_stack_entry *lse;
+       register struct lint_stack_entry *cs_entry = find_cs();
+
+       if (!cs_entry)
+               return;         /* not inside switch */
+       if (cs_entry != top_ls) {
+               warning("%s statement in strange context",
+                       dflt ? "default" : "case");
+               return;
+       }
+       if (cs_entry->ls_class == SWITCH) {
+               if (dflt) {
+                       cs_entry->LS_DEFAULT_MET = 1;
+               }
+               lse = new_lint_stack_entry();
+               lse->ls_class = CASE;
+               lse->ls_current = copy_state(top_ls->ls_current, level);
+               remove_settings(lse->ls_current, level);
+               lse->ls_level = level;
+               lint_push(lse);
+       }
+       else {
+               ASSERT(cs_entry->ls_class == CASE);
+               if (dflt) {
+                       cs_entry->ls_previous->LS_DEFAULT_MET = 1;
+               }
+               merge_states(top_ls->ls_current, top_ls->ls_previous->LS_CASE,
+                               top_ls->ls_previous->ls_level, NORMAL);
+               merge_states(top_ls->ls_current,
+                               top_ls->ls_previous->ls_current,
+                               top_ls->ls_previous->ls_level, NORMAL);
+               Free_state(&top_ls->ls_current);
+               top_ls->ls_current =
+                       copy_state(top_ls->ls_previous->ls_current,
+                                       top_ls->ls_previous->ls_level);
+               remove_settings(top_ls->ls_current, top_ls->ls_level);
+       }
+}
+
+lint_break_stmt()
+{
+       register struct lint_stack_entry *lse = find_wdfc();
+
+       if (!lse)
+               return;
+
+       switch (lse->ls_class) {
+       case WHILE:
+       case FOR:
+       case DO:
+               /* loop break */
+               lse->ls_previous->ls_current->st_notreached = 0;
+               cont_break_merge(lse);
+               break;
+
+       case CASE:
+               /* case break */
+               if (!top_ls->ls_current->st_notreached) {
+                       lse->ls_previous->ls_previous->ls_current->st_notreached = 0;
+               }
+               merge_states(lse->ls_current, lse->ls_previous->ls_current,
+                                       lse->ls_previous->ls_level, NORMAL);
+               if (lse->ls_previous->LS_BREAK) {
+                       merge_states(top_ls->ls_current, lse->ls_previous->LS_BREAK,
+                                       lse->ls_previous->ls_level, NORMAL);
+               }
+               else {
+                       lse->ls_previous->LS_BREAK = copy_state(top_ls->ls_current,
+                                                lse->ls_previous->ls_level);
+               }
+               if (lse == top_ls) {
+                       Free_state(&lse->ls_current);
+                       lint_pop();
+               }
+               break;
+       default:
+               NOTREACHED();
+               /*NOTREACHED*/
+       }
+       top_ls->ls_current->st_notreached = 1;
+}
+
+lint_start_function()
+{
+       lint_return_stmt(-1);   /* initialization */
+       lint_comment_function();
+}
+
+lint_end_function()
+{
+       extern struct outdef OutDef;
+       register int fund = func_type->tp_fund;
+
+       if (    OutDef.od_valreturned == NOVALRETURNED
+       &&      !func_notypegiven
+       &&      fund != VOID
+       ) {
+               warning("function %s declared %s%s but no value returned",
+                       func_name,
+                       (func_type->tp_unsigned && fund != POINTER) ?
+                               "unsigned " : "",
+                        symbol2str(fund)
+               );
+       }
+       /* write the function definition record */
+       outdef();
+
+       /* At this stage it is possible that stack_bottom.ls_current is
+        * pointing to a state with a list of auto_defs.
+        * These auto_defs must be freed and the state must be filled
+        * with zeros.
+        */
+       ASSERT(top_ls == &stack_bottom);
+       if (top_ls->ls_current->st_auto_list != 0)
+               free_st_auto_list(top_ls->ls_current->st_auto_list);
+       top_ls->ls_current->st_auto_list = 0;
+       top_ls->ls_current->st_notreached = 0;
+       top_ls->ls_current->st_warned = 0;
+}
+
+lint_return_stmt(e)
+       int e;
+{
+/* The statics of this function are initialized by calling it with e = -1. */
+
+       static int ret_e;
+                               /*-1    no return met yet
+                                * 0    return; met
+                                * 1    return with expression met
+                                */
+       static int warned;
+
+       switch (e) {
+       case -1:
+               ret_e = -1;
+               warned = 0;
+               return;
+       case 0:
+               if (top_ls->ls_current->st_notreached)
+                       break;
+               if (ret_e == 1 && !warned) {
+                       warning("function %s does not always return a value",
+                               func_name);
+                       warned = 1;
+               }
+               else
+                       ret_e = 0;
+               break;
+       case 1:
+               if (top_ls->ls_current->st_notreached)
+                       break;
+               if (ret_e == 0 && !warned) {
+                       warning("function %s does not always return a value",
+                               func_name);
+                       warned = 1;
+               }
+               else
+                       ret_e = 1;
+               break;
+       }
+       if (!top_ls->ls_current->st_notreached)
+               set_od_valreturned(e);
+       top_ls->ls_current->st_notreached = 1;
+}
+
+lint_jump_stmt(idf)
+       struct idf *idf;
+{
+       top_ls->ls_current->st_notreached = 1;
+       if (!idf->id_def)
+               return;
+       idf->id_def->df_used = 1;
+}
+
+lint_label()
+{
+/*     When meeting a label, we should take the intersection of all
+       settings at all goto's leading this way, but this cannot reasonably
+       be done.  So we assume that the user knows what he is doing and set
+       all automatic variables to set.
+*/
+       register struct auto_def *a = top_ls->ls_current->st_auto_list;
+
+       while (a) {
+               a->ad_maybe_set = 0;
+               a->ad_set = 1;
+               a = a->next;
+       }
+}
+
+lint_statement()
+{
+/* Check if this statement can be reached
+ */
+       if (s_NOTREACHED) {
+               top_ls->ls_current->st_notreached = 1;
+               s_NOTREACHED = 0;
+       }
+       if (DOT == '{' || DOT == ';')
+               return;
+       if (top_ls->ls_current->st_warned)
+               return;
+       if (top_ls->ls_current->st_notreached) {
+               if (DOT != CASE && DOT != DEFAULT && AHEAD != ':') {
+                       if (DOT != BREAK || loptions['b'])
+                               warning("statement cannot be reached");
+                       top_ls->ls_current->st_warned = 1;
+               }
+               else {
+                       top_ls->ls_current->st_notreached = 0;
+                       top_ls->ls_current->st_warned = 0;
+               }
+       }
+}
+
+PRIVATE
+lint_push(lse)
+       struct lint_stack_entry *lse;
+{
+       lse->ls_previous = top_ls;
+       top_ls->next = lse;
+       top_ls = lse;
+}
+
+PRIVATE
+lint_pop()
+{
+       top_ls = top_ls->ls_previous;
+       free_lint_stack_entry(top_ls->next);
+}
+
+#ifdef DEBUG
+/* FOR DEBUGGING */
+
+print_lint_stack()
+{
+       register struct lint_stack_entry *lse = top_ls;
+
+       while (lse) {
+               print("  |-------------- level %d ------------\n",
+                                       lse->ls_level);
+               print("  |cur: ");
+               if (lse->ls_current) {
+                       print_autos(lse->ls_current->st_auto_list);
+                       print("  |st_notreached == %d\n",
+                               lse->ls_current->st_notreached);
+               }
+               else
+                       print("\n");
+               print("  |class == %s\n",
+                       lse->ls_class ? symbol2str(lse->ls_class) : "{");
+               switch (lse->ls_class) {
+               case SWITCH:
+                       print("  |LS_BREAK: ");
+                       if (lse->LS_BREAK) {
+                               print_autos(lse->LS_BREAK->st_auto_list);
+                               print("  |st_notreached == %d\n",
+                                       lse->LS_BREAK->st_notreached);
+                       }
+                       else
+                               print("\n");
+                       print("  |LS_CASE:  ");
+                       if (lse->LS_CASE) {
+                               print_autos(lse->LS_CASE->st_auto_list);
+                               print("  |st_notreached == %d\n",
+                                       lse->LS_CASE->st_notreached);
+                       }
+                       else
+                               print("\n");
+                       break;
+               case DO:
+               case WHILE:
+               case FOR:
+                       print("  |LS_END:  ");
+                       if (lse->LS_END) {
+                               print_autos(lse->LS_END->st_auto_list);
+                               print("  |st_notreached == %d\n",
+                                       lse->LS_END->st_notreached);
+                       }
+                       else
+                               print("\n");
+                       break;
+               case IF:
+                       print("  |LS_IF_STATE: ");
+                       if (lse->LS_IF_STATE) {
+                               print_autos(lse->LS_IF_STATE->st_auto_list);
+                               print("  |st_notreached == %d\n",
+                                       lse->LS_IF_STATE->st_notreached);
+                       }
+                       else
+                               print("\n");
+                       break;
+               default:
+                       break;
+               }
+               lse = lse->ls_previous;
+       }
+       print("  |--------------\n\n");
+}
+
+print_autos(a)
+       register struct auto_def *a;
+{
+       while (a) {
+               print("%s", a->ad_idf->id_text);
+               print("(l=%d)", a->ad_def->df_level);
+               print("(U%dS%dM%d) ", a->ad_used, a->ad_set, a->ad_maybe_set);
+               a = a->next;
+       }
+       print("\n");
+}
+#endif DEBUG
+
+#endif LINT
diff --git a/lang/cem/cemcom.ansi/label.c b/lang/cem/cemcom.ansi/label.c
new file mode 100644 (file)
index 0000000..984a433
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*             L A B E L   H A N D L I N G             */
+
+#include       "Lpars.h"
+#include       "level.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "arith.h"
+#include       "def.h"
+#include       "type.h"
+#include       "noRoption.h"
+
+extern char options[];
+
+enter_label(idf, defining)
+       register struct idf *idf;
+{
+       /*      The identifier idf is entered as a label. If it is new,
+               it is entered into the idf list with the largest possible
+               scope, i.e., on the lowest possible level.
+               If defining, the label comes from a label statement.
+       */
+       if (idf->id_def)        {
+               register struct def *def = idf->id_def;
+               
+               if (def->df_sc == LABEL)        {
+                       if (defining && def->df_initialized)
+                               error("redeclaration of label %s",
+                                                               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);
+                       }
+               }
+       }
+       else    {
+               add_def(idf, LABEL, label_type, L_LOCAL);
+       }
+       if (idf->id_def->df_address == 0)
+               idf->id_def->df_address = (arith) text_label();
+       if (defining)
+               idf->id_def->df_initialized = 1;
+}
+
+unstack_label(idf)
+       register struct idf *idf;
+{
+       /*      The scope in which the label idf occurred is left.
+       */
+       if (!idf->id_def->df_initialized && !is_anon_idf(idf))
+               error("label %s not defined", idf->id_text);
+}
diff --git a/lang/cem/cemcom.ansi/label.h b/lang/cem/cemcom.ansi/label.h
new file mode 100644 (file)
index 0000000..16e1bf7
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*             L A B E L   D E F I N I T I O N                         */
+
+#include <em_label.h>          /* obtain definition of "label" */
+
+#define        NO_LABEL        (label) 0
+
+extern label lab_count;
+#define        text_label()    (lab_count++)           /* returns a new text label */
+
+extern label datlab_count;
+#define        data_label()    (datlab_count++)        /* returns a new data label */
+
+#define define_label(idf) enter_label(idf, 1);
+       /*      The identifier idf is defined as a label. If it is new,
+               it is entered into the idf list with the largest possible
+               scope, i.e., on the lowest possible level.
+       */
+
+#define apply_label(idf) enter_label(idf, 0);
+       /*      The identifier idf is applied as a label. It may or may
+               not be there, and if it is there, it may be from a
+               declaration or another application.
+       */
diff --git a/lang/cem/cemcom.ansi/level.h b/lang/cem/cemcom.ansi/level.h
new file mode 100644 (file)
index 0000000..9cf119e
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*  LEVEL DEFINITIONS */
+
+/*     The level of the top-most stack_level is kept in a global variable
+       with the obvious name 'level'. Although this variable is consulted
+       by a variety of routines, it turns out that its actual value is of
+       importance in only a very few files. Therefore the names of the
+       values are put in a separate include-file.
+       The L_PROTO level is a dummy level, which only occurs within
+       prototype declarations. When the declaration is really declared
+       the level is turned into L_FORMAL2.
+*/
+
+#define        L_PROTO         (-1)            /* prototype declaration */
+#define        L_UNIVERSAL     0
+#define        L_GLOBAL        1
+#define        L_FORMAL1       2               /* formal declaration */
+#define        L_FORMAL2       3               /* formal definition */
+#define        L_LOCAL         4               /* and up */
diff --git a/lang/cem/cemcom.ansi/macro.str b/lang/cem/cemcom.ansi/macro.str
new file mode 100644 (file)
index 0000000..39476d6
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* PREPROCESSOR: DEFINITION OF MACRO DESCRIPTOR */
+
+#include       "nopp.h"
+
+#ifndef NOPP
+/*     The flags of the mc_flag field of the macro structure. Note that
+       these flags can be set simultaneously.
+*/
+#define NOFLAG         0               /* no special flags     */
+#define        FUNC            01              /* function attached    */
+#define NOREPLACE      02              /* don't replace        */
+
+#define        FORMALP 0200    /* mask for creating macro formal parameter     */
+
+/*     The macro descriptor is very simple, except the fact that the
+       mc_text, which points to the replacement text, contains the
+       non-ascii characters \201, \202, etc, indicating the position of a
+       formal parameter in this text.
+*/
+struct macro   {
+       struct macro *next;
+       char *  mc_text;        /* the replacement text         */
+       int     mc_nps;         /* number of formal parameters  */
+       int     mc_length;      /* length of replacement text   */
+       int     mc_count;       /* # of "concurrent" invocations*/
+       char    mc_flag;        /* marking this macro           */
+};
+
+/* ALLOCDEF "macro" 20 */
+
+struct mlist {
+       struct mlist *next;
+       struct macro *m_mac;
+       char *m_repl;
+       char m_unstack;
+};
+
+/* ALLOCDEF "mlist" 20 */
+
+/* `token' numbers of keywords of command-line processor
+*/
+#define        K_UNKNOWN       0
+#define        K_DEFINE        1
+#define        K_ELIF          2
+#define        K_ELSE          3
+#define        K_ENDIF         4
+#define        K_ERROR         5
+#define        K_IF            6
+#define        K_IFDEF         7
+#define        K_IFNDEF        8
+#define        K_INCLUDE       9
+#define        K_LINE          10
+#define        K_PRAGMA        11
+#define        K_UNDEF         12
+#endif NOPP
diff --git a/lang/cem/cemcom.ansi/main.c b/lang/cem/cemcom.ansi/main.c
new file mode 100644 (file)
index 0000000..9757ac0
--- /dev/null
@@ -0,0 +1,406 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* MAIN PROGRAM */
+
+#include       "lint.h"
+#include       "nofloat.h"
+#include       <system.h>
+#include       "nopp.h"
+#include       "target_sizes.h"
+#include       "debug.h"
+#include       "use_tmp.h"
+#include       "inputtype.h"
+#include       "input.h"
+#include       "level.h"
+#include       "idf.h"
+#include       "arith.h"
+#include       "type.h"
+#include       "proto.h"
+#include       "declar.h"
+#include       "tokenname.h"
+#include       "Lpars.h"
+#include       "LLlex.h"
+#include       <alloc.h>
+#include       "specials.h"
+#include       "noRoption.h"
+#include       "nocross.h"
+#include       "sizes.h"
+#include       "align.h"
+
+extern struct tokenname tkidf[];
+extern char *symbol2str();
+extern char options[128];
+
+#ifndef NOPP
+int inc_pos = 1;                       /* place where next -I goes */
+int inc_total = 0;
+int inc_max;
+char **inctable;
+
+extern char *getwdir();
+#endif NOPP
+
+struct sp_id special_ids[] =   {
+       {"setjmp", SP_SETJMP},  /* non-local goto's are registered      */
+       {0, 0}
+};
+
+#ifndef NOCROSS
+arith
+       short_size = SZ_SHORT,
+       word_size = SZ_WORD,
+       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
+       short_align = AL_SHORT,
+       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;
+#endif NOCROSS
+
+#ifndef NOPP
+arith ifval;   /* ifval will contain the result of the #if expression  */
+#endif NOPP
+
+char *prog_name;
+
+main(argc, argv)
+       char *argv[];
+{
+       /* parse and interpret the command line options */
+       prog_name = argv[0];
+
+       init_hmask();
+#ifndef NOPP
+       inctable = (char **) Malloc(10 * sizeof(char *));
+       inctable[0] = ".";
+       inctable[1] = "/usr/include";
+       inctable[2] = 0;
+       inc_total = 2;
+       inc_max = 10;
+
+       init_pp();      /* initialise the preprocessor macros   */
+#endif NOPP
+
+       /*      Note: source file "-" indicates that the source is supplied
+               as standard input.  This is only allowed if INP_READ_IN_ONE is
+               not defined!
+       */
+#ifdef INP_READ_IN_ONE
+       while (argc > 1 && *argv[1] == '-')
+#else INP_READ_IN_ONE
+       while (argc > 1 && *argv[1] == '-' && argv[1][1] != '\0')
+#endif INP_READ_IN_ONE
+       {
+               char *par = &argv[1][1];
+
+               do_option(par, 1);
+               argc--, argv++;
+       }
+#ifdef LINT
+       lint_init();
+#endif LINT
+       compile(argc - 1, &argv[1]);
+
+#ifdef DEBUG
+       hash_stat();
+#endif DEBUG
+
+       sys_stop(err_occurred ? S_EXIT : S_END);
+       /*NOTREACHED*/
+}
+
+char *source = 0;
+
+char *nmlist = 0;
+
+compile(argc, argv)
+       char *argv[];
+{
+       char *result;
+#ifndef        LINT
+       register char *destination = 0;
+#endif LINT
+
+#ifdef DEBUG
+#ifndef NOPP
+       int pp_only = options['E'] || options['P'] || options['C'];
+#endif NOPP
+#endif
+
+       switch (argc) {
+       case 1:
+#ifndef        LINT
+#ifdef DEBUG
+#ifndef NOPP
+               if (!pp_only)
+#endif NOPP
+#endif
+                       fatal("%s: destination file not specified", prog_name);
+#endif LINT
+               break;
+
+#ifndef        LINT
+       case 2:
+               destination = argv[1];
+               break;
+       case 3:
+               nmlist = argv[2];
+               destination = argv[1];
+               break;
+#endif LINT
+
+       default:
+#ifndef        LINT
+               fatal("use: %s source destination [namelist]", prog_name);
+#else  LINT
+               fatal("use: %s source", prog_name);
+#endif LINT
+               break;
+       }
+
+       if (strcmp(argv[0], "-"))
+               FileName = source = argv[0];
+       else {
+               source = 0;
+               FileName = "standard input";
+       }
+
+       if (!InsertFile(source, (char **) 0, &result)) /* read the source file  */
+               fatal("%s: no source file %s\n", prog_name, FileName);
+       File_Inserted = 1;
+       init();
+       LineNumber = 0;
+       nestlow = -1;
+#ifndef NOPP
+       WorkingDir = getwdir(source);
+#endif NOPP
+       PushLex();                      /* initialize lex machine */
+
+#ifdef DEBUG
+#ifndef NOPP
+       if (pp_only) /* run the preprocessor as if it is stand-alone    */
+               preprocess();
+       else
+#endif NOPP
+#endif DEBUG
+       {
+#ifndef        LINT
+               init_code(destination && strcmp(destination, "-") != 0 ?
+                                       destination : 0);
+#endif LINT
+
+               /* compile the source text                      */
+               C_program();
+
+#ifdef PREPEND_SCOPES
+               prepend_scopes();
+#endif PREPEND_SCOPES
+               end_code();
+
+#ifdef DEBUG
+               if (options['u'])       {
+                       unstack_level();        /* unstack L_GLOBAL */
+               }
+               if (options['f'] || options['t'])
+                       dumpidftab("end of main", options['f'] ? 7 : 0);
+#endif DEBUG
+       }
+       PopLex();
+}
+
+init()
+{
+       init_cst();     /* initialize variables of "cstoper.c"          */
+       reserve(tkidf);         /* mark the C reserved words as such    */
+       init_specials(special_ids);     /* mark special ids as such     */
+
+       /*      Treat the type generic as int, having the same size and
+               alignment requirements.
+               This type is used as top type for void pointers, and is
+               transparent to the user.
+       */
+       gen_type = standard_type(GENERIC, 0, 1, (arith)1);
+       char_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);
+       ushort_type = standard_type(SHORT, UNSIGNED, short_align, short_size);
+
+       /*      Treat type `word' as `int', having its own size and
+               alignment requirements.
+               This type is transparent to the user.
+       */
+       word_type = standard_type(INT, 0, word_align, word_size);
+       uword_type = standard_type(INT, UNSIGNED, word_align, word_size);
+
+       int_type = standard_type(INT, 0, int_align, int_size);
+       uint_type = standard_type(INT, UNSIGNED, int_align, int_size);
+
+       long_type = standard_type(LONG, 0, long_align, long_size);
+       ulong_type = standard_type(LONG, UNSIGNED, long_align, long_size);
+
+#ifndef NOFLOAT
+       float_type = standard_type(FLOAT, 0, float_align, float_size);
+       double_type = standard_type(DOUBLE, 0, double_align, double_size);
+       lngdbl_type = standard_type(LNGDBL, 0, lngdbl_align, lngdbl_size);
+#endif NOFLOAT
+       void_type = standard_type(VOID, 0, 1, (arith)0);
+       label_type = standard_type(LABEL, 0, 0, (arith)0);
+       error_type = standard_type(ERRONEOUS, 0, 1, (arith)1);
+
+       /*      Pointer Arithmetic type: all arithmetics concerning
+               pointers is supposed to be performed in the
+               pointer arithmetic type which is equal to either
+               int_type or long_type, depending on the pointer_size
+       */
+       if ((int)pointer_size == (int)word_size)
+               pa_type = word_type;
+       else
+       if ((int)pointer_size == (int)short_size)
+               pa_type = short_type;
+       else
+       if ((int)pointer_size == (int)int_size)
+               pa_type = int_type;
+       else
+       if ((int)pointer_size == (int)long_size)
+               pa_type = long_type;
+       else
+               fatal("pointer size incompatible with any integral size");
+
+       if ((int)int_size != (int)word_size)
+               fatal("int_size and word_size are not equal");
+       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 */
+       funint_type = construct_type(FUNCTION, int_type, 0, (arith)0, NO_PROTO);
+       string_type = construct_type(POINTER, char_type, 0, (arith)0, NO_PROTO);
+
+       /* Define the standard type identifiers. */
+       add_def(str2idf("char"), TYPEDEF, char_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();
+}
+
+init_specials(si)
+       register struct sp_id *si;
+{
+       while (si->si_identifier)       {
+               struct idf *idf = str2idf(si->si_identifier);
+               
+               if (idf->id_special)
+                       fatal("maximum identifier length insufficient");
+               idf->id_special = si->si_flag;
+               si++;
+       }
+}
+
+#ifdef DEBUG
+#ifndef NOPP
+preprocess()
+{
+       /*      preprocess() is the "stand-alone" preprocessor which
+               consecutively calls the lexical analyzer LLlex() to get
+               the tokens and prints them in a suitable way.
+       */
+       static unsigned int lastlineno = 0;
+       static char *lastfilenm = "";
+
+       while (LLlex() !=  EOI) {
+               if (lastlineno != dot.tk_line)  {
+                       if (strcmp(lastfilenm, dot.tk_file) == 0)       {
+                               if (dot.tk_line - lastlineno <= 1)      {
+                                       lastlineno++;
+                                       print("\n");
+                               }
+                               else    {
+                                       lastlineno = dot.tk_line;
+                                       if (!options['P'])
+                                               print("\n#line %ld \"%s\"\n",
+                                                       lastlineno,
+                                                       lastfilenm
+                                               );
+                               }
+                       }
+                       else    {
+                               lastfilenm = dot.tk_file;
+                               lastlineno = dot.tk_line;
+                               if (!options['P'])
+                                       print("\n#line %ld \"%s\"\n",
+                                               lastlineno, lastfilenm);
+                       }
+               }
+               else
+               if (strcmp(lastfilenm, dot.tk_file) != 0)       {
+                       lastfilenm = dot.tk_file;
+                       if (!options['P'])
+                               print("\n#line %ld \"%s\"\n",
+                                       lastlineno, lastfilenm);
+               }
+               switch (DOT)    {
+               case IDENTIFIER:
+               case TYPE_IDENTIFIER:
+                       print("%s ", dot.tk_idf->id_text);
+                       break;
+               case STRING:
+               {
+                       char sbuf[1024];        /* a transient buffer */
+                       char *bts2str();
+
+                       print("\"%s\" ", bts2str(dot.tk_bts, dot.tk_len, 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;
+               default:        /* very expensive...    */
+                       print("%s ", symbol2str(DOT));
+               }
+       }
+}
+#endif NOPP
+#endif DEBUG
+
+No_Mem()                               /* called by alloc package */
+{
+       fatal("out of memory");
+}
+
+C_failed()                             /* called by EM_code module */
+{
+       fatal("write failed");
+}
+
diff --git a/lang/cem/cemcom.ansi/make.allocd b/lang/cem/cemcom.ansi/make.allocd
new file mode 100755 (executable)
index 0000000..08492fa
--- /dev/null
@@ -0,0 +1,8 @@
+sed -e '
+s:^.*[         ]ALLOCDEF[      ].*"\(.*\)"[    ]*\([0-9][0-9]*\).*$:\
+/* allocation definitions of struct \1 */\
+extern char *st_alloc();\
+extern struct \1 *h_\1;\
+#define        new_\1() ((struct \1 *) st_alloc((char **)\&h_\1, sizeof(struct \1), \2))\
+#define        free_\1(p) st_free(p, \&h_\1, sizeof(struct \1))\
+:'
diff --git a/lang/cem/cemcom.ansi/make.hfiles b/lang/cem/cemcom.ansi/make.hfiles
new file mode 100755 (executable)
index 0000000..2132dd6
--- /dev/null
@@ -0,0 +1,35 @@
+: Update Files from database
+
+PATH=/bin:/usr/bin
+
+case $# in
+1) ;;
+*)     echo use: $0 file >&2
+       exit 1
+esac
+
+(
+IFCOMMAND="if (<\$FN) 2>/dev/null;\
+       then    if cmp -s \$FN \$TMP;\
+               then    rm \$TMP;\
+               else    mv \$TMP \$FN;\
+                       echo update \$FN;\
+               fi;\
+       else    mv \$TMP \$FN;\
+               echo create \$FN;\
+       fi"
+echo 'TMP=.uf$$'
+echo 'FN=$TMP'
+echo 'cat >$TMP <<\!EOF!'
+sed -n '/^!File:/,${
+/^$/d
+/^!File:[       ]*\(.*\)$/s@@!EOF!\
+'"$IFCOMMAND"'\
+FN=\1\
+cat >$TMP <<\\!EOF!@
+p
+}' $1
+echo '!EOF!'
+echo $IFCOMMAND
+) |
+sh
diff --git a/lang/cem/cemcom.ansi/make.next b/lang/cem/cemcom.ansi/make.next
new file mode 100755 (executable)
index 0000000..be69d8d
--- /dev/null
@@ -0,0 +1,3 @@
+sed -n '
+s:^.*ALLOCDEF.*"\(.*\)".*$:struct \1 *h_\1 = 0;:p
+' $*
diff --git a/lang/cem/cemcom.ansi/make.tokcase b/lang/cem/cemcom.ansi/make.tokcase
new file mode 100755 (executable)
index 0000000..90205c6
--- /dev/null
@@ -0,0 +1,38 @@
+cat <<'--EOT--'
+/* Generated by make.tokcase */
+/* $Header: */
+#include "Lpars.h"
+
+char *
+symbol2str(tok)
+       int tok;
+{
+       static char buf[2] = { '\0', '\0' };
+
+       if (040 <= tok && tok < 0177) {
+               buf[0] = tok;
+               buf[1] = '\0';
+               return buf;
+       }
+       switch (tok) {
+--EOT--
+
+sed '
+/{[A-Z]/!d
+s/.*{\(.*\),.*\(".*"\).*$/     case \1 :\
+               return \2;/
+'
+
+cat <<'--EOT--'
+       case '\n':
+       case '\f':
+       case '\v':
+       case '\r':
+       case '\t':
+               buf[0] = tok;
+               return buf;
+       default:
+               return "bad token";
+       }
+}
+--EOT--
diff --git a/lang/cem/cemcom.ansi/make.tokfile b/lang/cem/cemcom.ansi/make.tokfile
new file mode 100755 (executable)
index 0000000..74a7c44
--- /dev/null
@@ -0,0 +1,11 @@
+cat <<'--EOT--'
+/* Generated by make.tokfile */
+/* $Header: */
+--EOT--
+
+sed '
+/{[A-Z]/!d
+s/.*{//
+s/,.*//
+s/.*/%token    &;/
+'
diff --git a/lang/cem/cemcom.ansi/mcomm.c b/lang/cem/cemcom.ansi/mcomm.c
new file mode 100644 (file)
index 0000000..c811685
--- /dev/null
@@ -0,0 +1,246 @@
+/* $Header$ */
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/*     mcomm.c -- change ".lcomm name" into ".comm name" where "name"
+       is specified in a list.
+*/
+#include <stdio.h>
+
+#define IDFSIZE 4096
+
+char *readfile();
+
+struct node {
+       char *name;
+       struct node *left, *right;
+};
+
+char *
+Malloc(n)
+       unsigned n;
+{
+       char *space;
+       char *malloc();
+
+       if ((space = malloc(n)) == 0) {
+               fprintf(stderr, "out of memory\n");
+               exit(1);
+       }
+       return space;
+}
+
+struct node *make_tree();
+
+#define new_node() ((struct node *) Malloc(sizeof (struct node)))
+
+main(argc, argv)
+       char *argv[];
+{
+       char *nl_file, *as_file;
+       char *nl_text, *as_text;
+       struct node *nl_tree = 0;
+       int nl_siz, as_siz;
+
+       if (argc != 3) {
+               fprintf(stderr, "use: %s namelist assembler_file\n", argv[0]);
+               exit(1);
+       }
+       nl_file = argv[1];
+       as_file = argv[2];
+
+       if ((nl_text = readfile(nl_file, &nl_siz)) == 0) {
+               fprintf(stderr, "%s: cannot read namelist %s\n",
+                       argv[0], nl_file);
+               exit(1);
+       }
+
+       if ((as_text = readfile(as_file, &as_siz)) == 0) {
+               fprintf(stderr, "%s: cannot read assembler file %s\n",
+                       argv[0], as_file);
+               exit(1);
+       }
+
+       nl_tree = make_tree(nl_text);
+       edit(as_text, nl_tree);
+
+       if (writefile(as_file, as_text, as_siz) == 0) {
+               fprintf(stderr, "%s: cannot write to %s\n", argv[0], as_file);
+               exit(1);
+       }
+       return 0;
+}
+
+#include <sys/types.h>
+#include <stat.h>
+
+char *
+readfile(filename, psiz)
+       char *filename;
+       int *psiz;
+{
+       struct stat stbuf;      /* for `stat' to get filesize           */
+       register int fd;        /* filedescriptor for `filename'        */
+       register char *cbuf;    /* pointer to buffer to be returned     */
+
+       if (((fd = open(filename, 0)) < 0) || (fstat(fd, &stbuf) != 0))
+               return 0;
+       cbuf = Malloc(stbuf.st_size + 1);
+       if (read(fd, cbuf, stbuf.st_size) != stbuf.st_size)
+               return 0;
+       cbuf[stbuf.st_size] = '\0';
+       close(fd);              /* filedes no longer needed     */
+       *psiz = stbuf.st_size;
+       return cbuf;
+}
+
+int
+writefile(filename, text, size)
+       char *filename, *text;
+{
+       register fd;
+
+       if ((fd = open(filename, 1)) < 0)
+               return 0;
+       if (write(fd, text, size) != size)
+               return 0;
+       close(fd);
+       return 1;
+}
+
+struct node *
+make_tree(nl)
+       char *nl;
+{
+       char *id = nl;
+       struct node *tree = 0;
+
+       while (*nl) {
+               if (*nl == '\n') {
+                       *nl = '\0';
+                       insert(&tree, id);
+                       id = ++nl;
+               }
+               else {
+                       ++nl;
+               }
+       }
+       return tree;
+}
+
+insert(ptree, id)
+       struct node **ptree;
+       char *id;
+{
+       register cmp;
+
+       if (*ptree == 0) {
+               register struct node *nnode = new_node();
+
+               nnode->name = id;
+               nnode->left = nnode->right = 0;
+               *ptree = nnode;
+       }
+       else
+       if ((cmp = strcmp((*ptree)->name, id)) < 0)
+               insert(&((*ptree)->right), id);
+       else
+       if (cmp > 0)
+               insert(&((*ptree)->left), id);
+}
+
+struct node *
+find(tree, id)
+       struct node *tree;
+       char *id;
+{
+       register cmp;
+
+       if (tree == 0)
+               return 0;
+       if ((cmp = strcmp(tree->name, id)) < 0)
+               return find(tree->right, id);
+       if (cmp > 0)
+               return find(tree->left, id);
+       return tree;
+}
+
+edit(text, tree)
+       char *text;
+       struct node *tree;
+{
+       register char *ptr = text;
+       char idbuf[IDFSIZE];
+       register char *id;
+       register char *save_ptr;
+
+       while (*ptr) {
+               if (
+                       *ptr   == '.' &&
+                       *++ptr == 'l' &&
+                       *++ptr == 'c' &&
+                       *++ptr == 'o' &&
+                       *++ptr == 'm' &&
+                       *++ptr == 'm' &&
+                       (*++ptr == ' ' || *ptr == '\t')
+               )
+               {
+                       save_ptr = ptr - 6;
+                       while (*++ptr == ' ' || *ptr == '\t')
+                               ;
+                       if (*ptr == '_')
+                               ++ptr;
+                       if (InId(*ptr)) {
+                               id = &idbuf[0];
+                               *id++ = *ptr++;
+                               while (InId(*ptr))
+                                       *id++ = *ptr++;
+                               *id = '\0';
+                               if (find(tree, idbuf) != 0) {
+                                       *save_ptr++ = ' ';
+                                       *save_ptr++ = '.';
+                               }
+                       }
+               }
+               while (*ptr && *ptr++ != '\n')
+                       ;
+       }
+}
+
+InId(c)
+{
+       switch (c) {
+
+       case 'a': case 'b': case 'c': case 'd': case 'e':
+       case 'f': case 'g': case 'h': case 'i': case 'j':
+       case 'k': case 'l': case 'm': case 'n': case 'o':
+       case 'p': case 'q': case 'r': case 's': case 't':
+       case 'u': case 'v': case 'w': case 'x': case 'y':
+       case 'z':
+       case 'A': case 'B': case 'C': case 'D': case 'E':
+       case 'F': case 'G': case 'H': case 'I': case 'J':
+       case 'K': case 'L': case 'M': case 'N': case 'O':
+       case 'P': case 'Q': case 'R': case 'S': case 'T':
+       case 'U': case 'V': case 'W': case 'X': case 'Y':
+       case 'Z':
+       case '_':
+       case '.':
+       case '0': case '1': case '2': case '3': case '4':
+       case '5': case '6': case '7': case '8': case '9':
+               return 1;
+       
+       default:
+               return 0;
+       }
+}
+
+puttree(nd)
+       struct node *nd;
+{
+       if (nd) {
+               puttree(nd->left);
+               printf("%s\n", nd->name);
+               puttree(nd->right);
+       }
+}
diff --git a/lang/cem/cemcom.ansi/mes.h b/lang/cem/cemcom.ansi/mes.h
new file mode 100644 (file)
index 0000000..49b856b
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* MESSAGE ADMINISTRATION */
+
+extern int fp_used;    /* code.c       */
diff --git a/lang/cem/cemcom.ansi/nmclash.c b/lang/cem/cemcom.ansi/nmclash.c
new file mode 100644 (file)
index 0000000..e820442
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* Accepted if many characters of long names are significant */
+/* $Header$ */
+abcdefghijklmnopr() { }
+abcdefghijklmnopq() { }
+main() { }
diff --git a/lang/cem/cemcom.ansi/options b/lang/cem/cemcom.ansi/options
new file mode 100644 (file)
index 0000000..0dce7fa
--- /dev/null
@@ -0,0 +1,28 @@
+User options:
+C      while running preprocessor, copy comment
+D      see identifier following as a macro
+E      run preprocessor only
+I      expand include table with directory name following
+M      set identifier length
+n      don't generate register messages
+p      generate linenumbers and filename indications
+       while generating EM code
+P      in running the preprocessor do not output '# line' lines
+R      restricted C
+T      take path following as directory for storing temporary file(s)
+U      undefine predefined name
+V      set objectsize and alignment requirements
+w      suppress warning diagnostics
+
+
+Debug options:
+
+d      perform a small dataflow analysis
+f      dump whole identifier table, including macros and reserved words
+h      supply hash table statistics
+i      print name of include files
+m      supply memory allocation statistics
+r      right-adjust bitfield
+t      dump table of identifiers
+u      unstack L_UNIVERSAL
+x      dump expressions
diff --git a/lang/cem/cemcom.ansi/options.c b/lang/cem/cemcom.ansi/options.c
new file mode 100644 (file)
index 0000000..c96cef6
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     U S E R   O P T I O N - H A N D L I N G         */
+
+#include       "lint.h"
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "nofloat.h"
+#include       "nopp.h"
+#include       "idfsize.h"
+#include       "nobitfield.h"
+#include       "class.h"
+#include       "macro.h"
+#include       "idf.h"
+#include       "arith.h"
+#include       "sizes.h"
+#include       "align.h"
+#include       "use_tmp.h"
+#include       "dataflow.h"
+#include       "noRoption.h"
+
+#ifndef NOPP
+extern char **inctable;
+extern int inc_pos;
+extern int inc_max;
+extern int inc_total;
+#endif NOPP
+
+char options[128];                     /* one for every char   */
+#ifdef LINT
+char loptions[128];                    /* one for every char   */
+#endif LINT
+
+extern int idfsize;
+
+static int txt2int();
+
+do_option(text)
+       char *text;
+{
+       register char opt;
+
+next_option:                   /* to allow combined one-char options */
+       switch (opt = *text++)  {
+
+       case 0:                 /* to end the goto next_option loop */
+               break;
+
+       default:
+#ifndef        LINT
+               fatal("illegal option: %c", opt);
+#else  LINT
+               warning("illegal option: %c", opt);
+#endif LINT
+               break;
+
+       case '-':
+               options[*text++] = 1;   /* flags, debug options etc.    */
+               goto next_option;
+
+#ifndef        LINT
+#ifdef DATAFLOW
+       case 'd':
+#endif DATAFLOW
+       case 'p':                       /* procentry/procexit */
+       case 'L' :                      /* no fil/lin */
+       case 'n':                       /* use no registers */
+       case 'w':                       /* no warnings will be given */
+       case 's':                       /* no stricts will be given */
+               options[opt] = 1;
+               goto next_option;
+#endif LINT
+
+#ifdef LINT
+       case 'h':       /* heuristic tests */
+       case 'v':       /* no complaints about unused arguments */
+       case 'a':       /* check long->int int->long conversions */
+       case 'b':       /* don't report unreachable break-statements */
+       case 'x':       /* complain about unused extern declared variables */
+       case 'u':       /* no "used but not defined"; for pass 2 */
+       case 'L':       /* lintlibrary */
+               loptions[opt] = 1;
+               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            */
+#ifndef        NOPP
+               options['E'] = 1;
+               warning("-C: comment is not output");
+#else NOPP
+               warning("-C option ignored");
+#endif NOPP
+               break;
+#endif ___XXX___
+
+       case 'D' :      {       /* -Dname :     predefine name          */
+#ifndef NOPP
+               register char *cp = text, *name, *mactext;
+
+               if (class(*cp) != STIDF && class(*cp) != STELL) {
+                       error("identifier missing in -D%s", text);
+                       break;
+               }
+
+               name = cp;
+
+               while (*cp && in_idf(*cp)) {
+                       ++cp;
+               }
+
+               if (!*cp) {                     /* -Dname */
+                       mactext = "1";
+               }
+               else
+               if (*cp == '=') {               /* -Dname=text  */
+                       *cp++ = '\0';           /* end of name  */
+                       mactext = cp;
+               }
+               else    {                       /* -Dname?? */
+                       error("malformed option -D%s", text);
+                       break;
+               }
+
+               macro_def(str2idf(name), mactext, -1, strlen(mactext),
+                       NOFLAG);
+#else NOPP
+               warning("-D option ignored");
+#endif NOPP
+               break;
+       }
+
+#ifdef ___XXX___
+deleted, is now a debug-flag
+       case 'E' :      /* run preprocessor only, with #<int>   */
+#ifndef NOPP
+               options['E'] = 1;
+#else NOPP
+               warning("-E option ignored");
+#endif NOPP
+               break;
+#endif ___XXX___
+
+       case 'I' :      /* -Ipath : insert "path" into include list     */
+#ifndef NOPP
+               if (*text)      {
+                       int i;
+                       register char *new = text;
+                       
+                       if (++inc_total > inc_max) {
+                               char **n = (char **)
+                                  Malloc((10+inc_max)*sizeof(char *));
+                               for (i = 0; i < inc_max; i++) {
+                                       n[i] = inctable[i];
+                               }
+                               free((char *) inctable);
+                               inctable = n;
+                               inc_max += 10;
+                       }
+                               
+                       i = inc_pos++;
+                       while (new)     {
+                               char *tmp = inctable[i];
+                               
+                               inctable[i++] = new;
+                               new = tmp;
+                       }
+               }
+               else inctable[inc_pos] = 0;
+#else NOPP
+               warning("-I option ignored");
+#endif NOPP
+               break;
+
+       case 'M':       /* maximum identifier length */
+               idfsize = txt2int(&text);
+               if (*text || idfsize <= 0)
+                       fatal("malformed -M option");
+               if (idfsize > IDFSIZE)
+                       fatal("maximum identifier length is %d", IDFSIZE);
+               break;
+
+#ifdef ___XXX___
+deleted, is now a debug-flag
+       case 'P' :      /* run preprocessor stand-alone, without #'s    */
+#ifndef NOPP
+               options['E'] = 1;
+               options['P'] = 1;
+#else NOPP
+               warning("-P option ignored");
+#endif NOPP
+               break;
+#endif ___XXX___
+
+#ifdef LINT
+       case 'S' : {            /* -Sint :      static scope number for lint */
+               extern int stat_number;
+               stat_number = txt2int(&text);
+               break;
+       }
+#endif LINT
+
+       case 'T' : {
+#ifdef USE_TMP
+               extern char *C_tmpdir;
+               if (*text)
+                       C_tmpdir = text;
+               else
+                       C_tmpdir = ".";
+#else USE_TMP
+               warning("-T option ignored");
+#endif USE_TMP
+               break;
+       }
+               
+       case 'U' :      {       /* -Uname :     undefine predefined     */
+#ifndef NOPP
+               register struct idf *idef;
+
+               if (*text)      {
+                       if ((idef = str2idf(text))->id_macro) {
+                               free_macro(idef->id_macro);
+                               idef->id_macro = (struct macro *) 0;
+                       }
+               }
+#else NOPP
+               warning("-U option ignored");
+#endif NOPP
+               break;
+       }
+
+#ifndef        LINT
+       case 'V' :      /* set object sizes and alignment requirements  */
+#ifdef NOCROSS
+               warning("-V option ignored");
+               break;
+#else NOCROSS
+       {
+               register arith sz, algn;
+               char c;
+
+               while (c = *text++)     {
+                       sz = txt2int(&text);
+                       algn = 0;
+                       if (*text == '.')       {
+                               text++;
+                               algn = txt2int(&text);
+                       }
+                       switch (c)      {
+                       case 's':       /* short        */
+                               if (sz != (arith)0)
+                                       short_size = sz;
+                               if (algn != 0)
+                                       short_align = algn;
+                               break;
+                       case 'w':       /* word         */
+                               if (sz != (arith)0)
+                                       dword_size = (word_size = sz) << 1;
+                               if (algn != 0)
+                                       word_align = algn;
+                               break;
+                       case 'i':       /* int          */
+                               if (sz != (arith)0)
+                                       int_size = sz;
+                               if (algn != 0)
+                                       int_align = algn;
+                               break;
+                       case 'l':       /* long         */
+                               if (sz != (arith)0)
+                                       long_size = sz;
+                               if (algn != 0)
+                                       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)
+                                       pointer_size = sz;
+                               if (algn != 0)
+                                       pointer_align = algn;
+                               break;
+                       case 'r':       /* adjust bitfields right       */
+#ifndef NOBITFIELD
+                               options['r'] = 1;
+#else NOBITFIELD
+                               warning("bitfields are not implemented");
+#endif NOBITFIELD
+                               break;
+                       case 'S':       /* initial struct alignment     */
+                               if (sz != (arith)0)
+                                       struct_align = sz;
+                               break;
+                       case 'U':       /* initial union alignment      */
+                               if (sz != (arith)0)
+                                       union_align = sz;
+                               break;
+                       default:
+                               error("-V: bad type indicator %c\n", c);
+                       }
+               }
+               break;
+       }
+#endif NOCROSS
+#endif LINT
+       }
+}
+
+static int
+txt2int(tp)
+       register char **tp;
+{
+       /*      the integer pointed to by *tp is read, while increasing
+               *tp; the resulting value is yielded.
+       */
+       register int val = 0, ch;
+       
+       while (ch = **tp, ch >= '0' && ch <= '9')       {
+               val = val * 10 + ch - '0';
+               (*tp)++;
+       }
+       return val;
+}
diff --git a/lang/cem/cemcom.ansi/pragma.c b/lang/cem/cemcom.ansi/pragma.c
new file mode 100644 (file)
index 0000000..83edebb
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* PREPROCESSOR: PRAGMA INTERPRETER */
+
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "debug.h"
+#include       "idf.h"
+#include       "input.h"
+#include       "nopp.h"
+
+#ifndef NOPP
+#include       "ifdepth.h"     
+#include       "botch_free.h"  
+#include       "nparams.h"     
+#include       "parbufsize.h"  
+#include       "textsize.h"    
+#include       "idfsize.h"     
+#include       "assert.h"
+#include       <alloc.h>
+#include       "class.h"
+#include       "macro.h"
+
+#define P_UNKNOWN      0
+#define P_FLAGS                1
+
+struct pkey {
+       char *pk_name;
+       int pk_key;
+} pragmas[] = {
+       {"flags",       P_FLAGS},
+       {0,             P_UNKNOWN}
+};
+
+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) {
+               /*      Lineair search - why bother ?
+               */
+               for (pkp = &pragmas[0]; pkp->pk_key != P_UNKNOWN; pkp++)
+                       if (strcmp(pkp->pk_name, id->id_text) == 0)
+                               break;
+
+               switch (pkp->pk_key) {
+               case P_FLAGS:
+                       if (GetToken(&tk) == STRING)
+                               do_option(tk.tk_bts);
+                       break;
+
+               case P_UNKNOWN:
+                       strict("unknown pragma directive %s", id->id_text);
+                       break;
+
+               default:
+                       strict("unimplemented pragma directive");
+                       break;
+               }
+       }
+       SkipToNewLine(0);
+
+}
+#endif
diff --git a/lang/cem/cemcom.ansi/program.g b/lang/cem/cemcom.ansi/program.g
new file mode 100644 (file)
index 0000000..658af39
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* PROGRAM PARSER */
+
+/*     The presence of typedef declarations renders it impossible to
+       make a context-free grammar of C. Consequently we need
+       context-sensitive parsing techniques, the simplest one being
+       a subtle cooperation between the parser and the lexical scanner.
+       The lexical scanner has to know whether to return IDENTIFIER
+       or TYPE_IDENTIFIER for a given tag, and it obtains this information
+       from the definition list, as constructed by the parser.
+       The present grammar is essentially LL(2), and is processed by
+       a parser generator which accepts LL(1) with tie breaking rules
+       in C, of the form %if(cond) and %while(cond). To solve the LL(1)
+       ambiguities, the lexical scanner does a one symbol look-ahead.
+       This symbol, however, cannot always be correctly assessed, since
+       the present symbol may cause a change in the definition list
+       which causes the identification of the look-ahead symbol to be
+       invalidated.
+       The lexical scanner relies on the parser (or its routines) to
+       detect this situation and then update the look-ahead symbol.
+       An alternative approach would be to reassess the look-ahead symbol
+       in the lexical scanner when it is promoted to dot symbol. This
+       would be more beautiful but less correct, since then for a short
+       while there would be a discrepancy between the look-ahead symbol
+       and the definition list; I think it would nevertheless work in
+       correct programs.
+       A third solution would be to enter the identifier as soon as it
+       is found; its storage class is then known, although its full type
+       isn't. We would have to fill that in afterwards.
+
+       At block exit the situation is even worse. Upon reading the
+       closing brace, the names declared inside the function are cleared
+       from the name list. This action may expose a type identifier that
+       is the same as the identifier in the look-ahead symbol. This
+       situation certainly invalidates the third solution, and casts
+       doubts upon the second.
+*/
+
+%lexical       LLlex;
+%start         C_program, program;
+%start         If_expr, control_if_expression;
+
+{
+#include       "lint.h"
+#include       "nopp.h"
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "type.h"
+#include       "declar.h"
+#include       "decspecs.h"
+#include       "code.h"
+#include       "expr.h"
+#include       "def.h"
+#ifdef LINT
+#include       "l_state.h"
+#endif LINT
+
+#ifndef NOPP
+extern arith ifval;
+#endif NOPP
+
+extern error();
+}
+
+control_if_expression
+       {
+               struct expr *exprX;
+       }
+:
+       constant_expression(&exprX)
+               {
+#ifndef NOPP
+                       register struct expr *expr = exprX;
+                       if (expr->ex_flags & EX_SIZEOF)
+                               expr_error(expr,
+                                       "sizeof not allowed in preprocessor");
+                       ifval = expr->VL_VALUE;
+                       free_expression(expr);
+#endif NOPP
+               }
+;
+
+/* 10 */
+program:
+       [%persistent external_definition]*
+       {unstack_world();}
+;
+
+/*     A C identifier definition is remarkable in that it formulates
+       the declaration in a way different from most other languages:
+       e.g., rather than defining x as a pointer-to-integer, it defines
+       *x as an integer and lets the compiler deduce that x is actually
+       pointer-to-integer.  This has profound consequences, both for the
+       structure of an identifier definition and for the compiler.
+       
+       A definition starts with a decl_specifiers, which contains things
+       like
+               typedef int
+       which is implicitly repeated for every definition in the list, and
+       then for each identifier a declarator is given, of the form
+               *a()
+       or so.  The decl_specifiers is kept in a struct decspecs, to be
+       used again and again, while the declarator is stored in a struct
+       declarator, only to be passed to declare_idf together with the
+       struct decspecs.
+*/
+
+external_definition
+       {       struct decspecs Ds;
+               struct  declarator Dc;
+       }
+:
+       {       Ds = null_decspecs;
+               Dc = null_declarator;
+       }
+       [ %if (DOT != IDENTIFIER || AHEAD == IDENTIFIER)
+               decl_specifiers(&Ds)
+               [
+                       declarator(&Dc)
+                       {
+                               declare_idf(&Ds, &Dc, level);
+#ifdef LINT
+                               lint_ext_def(Dc.dc_idf, Ds.ds_sc);
+#endif LINT
+                       }
+                       [
+                               function(&Ds, &Dc)
+                       |
+                               non_function(&Ds, &Dc)
+                       ]
+               |
+                       ';'
+               ]
+       |
+               empty
+               {do_decspecs(&Ds);}
+               declarator(&Dc)
+               {
+                       declare_idf(&Ds, &Dc, level);
+#ifdef LINT
+                       lint_ext_def(Dc.dc_idf, Ds.ds_sc);
+#endif LINT
+               }
+               function(&Ds, &Dc)
+       ]
+       {remove_declarator(&Dc);}
+;
+
+non_function(register struct decspecs *ds; register struct declarator *dc;)
+:
+       {       reject_params(dc);
+               def_proto(dc);
+       }
+       [
+               initializer(dc->dc_idf, ds->ds_sc)
+       |
+               { code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); }
+       ]
+       {
+#ifdef LINT
+               if (dc->dc_idf->id_def->df_type->tp_fund == FUNCTION)
+                       def2decl(ds->ds_sc);
+               if (dc->dc_idf->id_def->df_sc != TYPEDEF)
+                       outdef();
+#endif LINT
+       }
+       [
+               ','
+               init_declarator(ds)
+       ]*
+       ';'
+;
+
+/* 10.1 */
+function(struct decspecs *ds; struct declarator *dc;)
+       {
+               arith fbytes;
+       }
+:
+       {       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);
+       }
+       declaration*
+       {
+               declare_formals(&fbytes);
+#ifdef LINT
+               lint_formals();
+#endif LINT
+       }
+       compound_statement
+       {
+               end_proc(fbytes);
+#ifdef LINT
+               lint_return_stmt(0);    /* implicit return at end of function */
+#endif LINT
+               unstack_level();        /* L_FORMAL2 declarations */
+#ifdef LINT
+               check_args_used();
+#endif LINT
+               unstack_level();        /* L_FORMAL1 declarations */
+#ifdef LINT
+               lint_end_function();
+#endif LINT
+       }
+;
diff --git a/lang/cem/cemcom.ansi/proto.c b/lang/cem/cemcom.ansi/proto.c
new file mode 100644 (file)
index 0000000..a99bf3b
--- /dev/null
@@ -0,0 +1,442 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*  P R O T O T Y P E   F I D D L I N G  */
+
+#include       "lint.h"
+#include       "debug.h"
+#include       "idfsize.h"
+#include       "nparams.h"
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "Lpars.h"
+#include       "level.h"
+#include       "arith.h"
+#include       "align.h"
+#include       "stack.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "type.h"
+#include       "struct.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "declar.h"
+#include       "decspecs.h"
+#include       "proto.h"
+#include       "assert.h"
+
+extern char options[];
+
+add_proto(pl, ds, dc, level)
+       struct proto *pl;
+       struct decspecs *ds;
+       struct declarator *dc;
+       int level;
+{
+       /*      The full typed identifier or abstract type, described
+               by the structures decspecs and declarator are turned
+               a into parameter type list structure.
+               The parameters will be declared at level L_FORMAL2,
+               later on it's decided whether they were prototypes
+               or actual declarations.
+       */
+       register struct idf *idf;
+       register struct def *def = (struct def *)0;
+       register int sc = ds->ds_sc;
+       register struct type *type;
+       char formal_array = 0;
+
+       ASSERT(ds->ds_type != (struct type *)0);
+
+       pl->pl_flag = FORMAL;
+       if ((idf = dc->dc_idf) != (struct idf *)0)
+               def = idf->id_def;
+       type = declare_type(ds->ds_type, dc);
+       if (type->tp_size < (arith)0 && actual_declaration(sc, type)) {
+               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");
+       }
+
+       /*      Perform some special conversions for parameters.
+       */
+       if (type->tp_fund == FUNCTION) {
+               if (type->tp_proto)
+                       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);
+               formal_array = 1;
+       }
+
+       /*      According to the standard we should ignore the storage
+               class of a parameter, unless it's part of a function
+               definition.
+               However, in the routine declare_protos we don't know decspecs,
+               and therefore we can't complain up there. So we build up the
+               storage class, and keep quiet until we reach declare_protos.
+       */
+       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)) {
+               /* redeclaration at the same level */
+               error("parameter %s redeclared", idf->id_text);
+       } else if (idf != (struct idf *)0) {
+               /*      New definition, redefinition hides earlier one
+               */
+               register struct def *newdef = new_def();
+               
+               newdef->next = def;
+               newdef->df_level = level;
+               newdef->df_sc = sc;
+               newdef->df_type = type;
+               newdef->df_formal_array = formal_array;
+               newdef->df_file = idf->id_file;
+               newdef->df_line = idf->id_line;
+#ifdef LINT
+               newdef->df_set = (type->tp_fund == ARRAY);
+               newdef->df_firstbrace = 0;
+#endif
+               /*      We can't put the idf onto the stack, since these kinds
+                       of declaration may occurs at any level, and the idf
+                       does not necessarily go at this level. E.g.
+
+                       f() {
+                       ...
+                               { 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.
+                       However, in
+
+                       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
+                       definition. So, this process is postponed.
+               */
+               idf->id_def = newdef;
+               update_ahead(idf);
+       }
+
+       pl->pl_idf = idf;
+       pl->pl_type = type;
+}
+
+declare_protos(idf, dc)
+       register struct idf *idf;
+       register struct declarator *dc;
+{
+       /*      At this points we know that the idf's in protolist are formal
+               parameters. So it's time to declare them at level L_FORMAL2.
+       */
+       struct stack_level *stl = stack_level_of(L_FORMAL1);
+       register struct decl_unary *du;
+       register struct type *type;
+       register struct proto *pl;
+       register struct def *def;
+
+#ifdef DEBUG
+       if (options['t'])
+               dumpidftab("start declare_protos", 0);
+#endif DEBUG
+       du = dc->dc_decl_unary;
+       while (du && du->du_fund != FUNCTION)
+               du = du->next;
+       pl = du ? du->du_proto : NO_PROTO;
+       if (pl) {
+               idf->id_proto = 0;
+               do {
+                       type = pl->pl_type;
+
+                       /* `...' only for type checking */
+                       if (pl->pl_flag == ELLIPSIS) {
+                               pl = pl->next;
+                               continue;
+                       }
+
+                       /* special case: int f(void) { ; } */
+                       if (type->tp_fund == VOID)
+                               break;
+
+                       if (!pl->pl_idf || !(def = pl->pl_idf->id_def)) {
+                               error("no parameter supplied");
+                               pl = pl->next;
+                               continue;
+                       }
+
+                       /*      Postponed storage class checking.
+                       */
+                       if (def->df_sc == 0)
+                               error("illegal storage class in parameter declaration");
+
+                       def->df_level = L_FORMAL2;
+                       stack_idf(pl->pl_idf, stl);
+                       pl = pl->next;
+               } while (pl);
+       }
+#ifdef DEBUG
+       if (options['t'])
+               dumpidftab("end declare_protos", 0);
+#endif DEBUG
+}
+
+
+def_proto(dc)
+       register struct declarator *dc;
+{
+       /*      Prototype declarations may have arguments, but the idf's
+               in the parameter type list can be ignored.
+       */
+       register struct decl_unary *du = dc->dc_decl_unary;
+
+       while (du) {
+               if (du->du_fund == FUNCTION)
+                       remove_proto_idfs(du->du_proto);
+               du = du->next;
+       }
+}
+
+update_proto(tp, otp)
+       register struct type *tp, *otp;
+{
+       /*      This routine performs the proto type updates.
+               Consider the following code:
+
+               int f(double g());
+               int f(double g(int f(), int));
+               int f(double g(int f(long double), int));
+
+               The most accurate definition is the third line.
+               This routine will silently update all lists,
+               and removes the redundant occupied space.
+       */
+       register struct proto *pl, *opl;
+
+#if 0
+       /*      THE FOLLOWING APPROACH IS PRESUMABLY WRONG.
+               THE ONLY THING THIS CODE IS SUPPOSED TO DO
+               IS TO UPDATE THE PROTOTYPELISTS, I HAVEN'T
+               EVEN CONSIDERED THE DISPOSAL OF REDUNDANT
+               SPACE !!.
+               THIS ROUTINE DUMPS CORE. SORRY, BUT IT'S 10
+               P.M. AND I'M SICK AN TIRED OF THIS PROBLEM.
+       */
+       print("Entering\n");
+       if (tp == otp) {
+               print("OOPS - they are equal\n");
+               return;
+       }
+       if (!tp || !otp) {
+               print("OOPS - Nil pointers tp=@%o otp=@%o\n", tp, otp);
+               return;
+       }
+
+       print("Search function\n");
+       while (tp && tp->tp_fund != FUNCTION) {
+               if (!(tp->tp_up)) {
+                       print("TP is NIL\n");
+                       return;
+               }
+               tp = tp->tp_up;
+               if (!(otp->tp_up)) {
+                       print("OTP is NIL\n");
+                       return;
+               }
+               otp = otp->tp_up;
+               if (!tp) return;
+       }
+
+       print("Do it\n");
+       pl = tp->tp_proto;
+       opl = otp->tp_proto;
+       if (pl && opl) {
+               /* both have prototypes */
+               print("Both have proto type\n");
+               print("New proto type list\n");
+               dump_proto(pl);
+               print("Old proto type list\n");
+               dump_proto(opl);
+               while (pl && opl) {
+                       update_proto(pl->pl_type, opl->pl_type);
+                       pl = pl->next;
+                       opl = pl->next;
+               }
+               /*free_proto_list(tp->tp_proto);*/
+               tp->tp_proto = otp->tp_proto;
+       } else if (opl) {
+               /* old decl has type */
+               print("Old decl has type\n");
+               print("Old proto type list\n");
+               dump_proto(opl);
+               tp->tp_proto = opl;
+       } else if (pl) {
+               /* new decl has type */
+               print("New decl has type\n");
+               print("New proto type list\n");
+               dump_proto(pl);
+               print("otp = @%o\n", otp);
+               otp->tp_proto = pl;
+               print("after assign\n");
+       } else
+               print("none has prototype\n");
+
+       print("Going for another top type\n");
+       update_proto(tp->tp_up, otp->tp_up);
+# endif
+}
+
+free_proto_list(pl)
+       register struct proto *pl;
+{
+       while (pl) {
+               register struct proto *tmp = pl->next;
+               free_proto(pl);
+               pl = tmp;
+       }
+}
+
+remove_proto_idfs(pl)
+       register struct proto *pl;
+{
+       /*      Remove all the identifier definitions from the
+               prototype list. Keep in account the recursive
+               function definitions.
+       */
+       register struct def *def;
+
+       while (pl) {
+               if (pl->pl_idf) {
+#ifdef DEBUG
+                       if (options['t'])
+                               print("Removing idf %s from list\n",
+                                       pl->pl_idf->id_text);
+#endif
+                       /*      Remove all the definitions made within
+                               a prototype.
+                       */
+                       if (pl->pl_flag == 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);
+                       }
+                       def = pl->pl_idf->id_def;
+                       if (def && def->df_level <= L_PROTO){
+                               pl->pl_idf->id_def = def->next;
+                               free_def(def);
+                       }
+                       pl->pl_idf = (struct idf *) 0;
+               }
+               pl = pl->next;
+       }
+}
+
+call_proto(expp)
+       register struct expr **expp;
+{
+       /*      If the function specified by (*expp)->OP_LEFT has a prototype,
+               the parameters are converted according the rules specified in
+               par. 3.3.2.2. E.i. the parameters are converted to the prototype
+               counter parts as if by assignment. For the parameters falling
+               under ellipsis clause the old parameters conversion stuff
+               applies.
+       */
+       register struct expr *left = (*expp)->OP_LEFT;
+       register struct expr *right = (*expp)->OP_RIGHT;
+       register struct proto *pl = NO_PROTO;
+
+       if (left != NILEXPR) {  /* in case of an error */
+               register struct type *tp = left->ex_type;
+
+               while (tp && tp->tp_fund != FUNCTION)
+                       tp = tp->tp_up;
+               pl = (tp && tp->tp_proto) ? tp->tp_proto : NO_PROTO;
+       }
+
+       if (right != NILEXPR) { /* function call with parameters */
+               register struct expr *ex = right;
+               register struct expr **ep = &((*expp)->OP_RIGHT);
+               register int ecnt = 0, pcnt = 0;
+               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");
+                               return;
+                       }
+                       if ((idf = left->VL_IDF)->id_proto)
+                               return;
+                       strict("'%s' no prototype supplied", idf->id_text);
+                       idf->id_proto++;
+                       return;
+               }
+
+               /* stack up the parameter expressions */
+               while (ex->ex_class == Oper && ex->OP_OPER == PARCOMMA) {
+                       if (ecnt == STDC_NPARAMS)
+                               strict("number of parameters exceeds ANSI limit");
+                       if (ecnt >= NPARAMS-1) {
+                               error("too many parameters");
+                               return;
+                       }
+                       estack[ecnt++] = &(ex->OP_RIGHT);
+                       ep = &(ex->OP_LEFT);
+                       ex = ex->OP_LEFT;
+               }
+               estack[ecnt++] = ep;
+
+               /*      Declarations like int f(void) do not expect any
+                       parameters.
+               */
+               if (pl && pl->pl_flag == VOID) {
+                       strict("no parameters expected");
+                       return;
+               }
+
+               /* stack up the prototypes */
+               while (pl) {
+                       /* stack prototypes */
+                       pstack[pcnt++] = pl;
+                       pl = pl->next;
+               }
+               pcnt--;
+
+               for (--ecnt; ecnt >= 0; ecnt--) {
+                       /*      Only the parameters specified in the prototype
+                               are checked and converted. The parameters that
+                               fall under the ellipsis clause are neither
+                               checked nor converted !
+                       */
+                       if (pcnt < 0) {
+                               error("more parameters than specified in prototype");
+                               break;
+                       }
+                       if (pstack[pcnt]->pl_flag != ELLIPSIS) {
+                               ch7cast(estack[ecnt],CASTAB,pstack[pcnt]->pl_type);
+                               pcnt--;
+                       } else
+                               break;  /* against unnecessary looping */
+               }
+               if (pcnt >= 0 && pstack[0]->pl_flag != ELLIPSIS)
+                       error("less parameters than specified in prototype");
+
+       } else {
+               if (pl && pl->pl_flag != VOID)
+                       error("less parameters than specified in prototype");
+       }
+}
+
diff --git a/lang/cem/cemcom.ansi/proto.str b/lang/cem/cemcom.ansi/proto.str
new file mode 100644 (file)
index 0000000..614a5c9
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* PARAMETER TYPE LIST DEFINITION */
+
+struct proto {
+       struct proto *next;
+       struct type *pl_type;   /* parameter type */
+       struct idf *pl_idf;     /* parameter identifier */
+       short pl_flag;          /* ELLIPSIS or FORMAL */
+};
+
+#define NO_PROTO       ((struct proto *)0)
+
+/* ALLOCDEF "proto" 10 */
diff --git a/lang/cem/cemcom.ansi/replace.c b/lang/cem/cemcom.ansi/replace.c
new file mode 100644 (file)
index 0000000..f907db7
--- /dev/null
@@ -0,0 +1,677 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*  M A C R O   R E P L A C E M E N T */
+#include       "nopp.h"
+
+#ifndef NOPP
+
+#include       "debug.h"
+#include       "pathlength.h"
+#include       "strsize.h"
+#include       "nparams.h"
+#include       "idfsize.h"
+#include       "numsize.h"
+#include       <alloc.h>
+#include       "idf.h"
+#include       "input.h"
+#include       "macro.h"
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "class.h"
+#include       "assert.h"
+#include       "static.h"
+#include       "lapbuf.h"
+#include       "argbuf.h"
+#include       "replace.h"
+
+struct repl    *ReplaceList;   /* list of currently active macros */
+
+int
+replace(idf)
+       register struct idf *idf;
+{
+       /*      replace is called by the lexical analyzer to perform
+               macro replacement. The routine actualy functions as a
+               higher interface to the real thing: expand_macro().
+       */
+       struct repl *repl;
+       int size;
+       
+       repl = new_repl();
+       repl->r_ptr = repl->r_text;
+       repl->r_args = new_args();
+       if (!expand_macro(repl, idf, (struct idf *)0))
+               return 0;
+       free_args(repl->r_args);
+       InsertText(repl->r_text, repl->r_ptr - repl->r_text);
+       repl->next = ReplaceList;
+       ReplaceList = repl;
+       return 1;
+}
+
+unstackrepl()
+{
+       struct repl *repl = ReplaceList;
+
+#ifdef PERSONAL_TOUCH
+       if (repl == NO_REPL) {
+               print("Leendert, you don't understand the principle yet\n");
+               return;
+       }
+#else
+       ASSERT(repl != NO_REPL);
+#endif
+       ReplaceList = repl->next;
+       free_repl(repl);
+}
+
+expand_macro(repl, idf, previdf)
+       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
+               caused the replacement.
+               If the identifier represents a function-like macro
+               call, the number of actual parameters is checked
+               against the number of formal parameters. Note that
+               in ANSI C the parameters are expanded first;
+               this is done by calling getactuals().
+               When the possible parameters are expanded, the replace-
+               ment list associated with "idf" is expanded.
+               expand_macro() returns 1 if the replacement succeeded
+               and 0 if some error occurred.
+       */
+       register struct macro *mac = idf->id_macro;
+       struct args *args = repl->r_args;
+       register int ch;
+
+       if (mac->mc_nps != -1) {        /* with parameter list  */
+               if (mac->mc_flag & FUNC) {
+                       /* the following assertion won't compile:
+                       ASSERT(!strcmp("defined", idf->id_text));
+                       */
+                       if (!AccDefined) return 0;
+               }
+
+               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.
+                       lexwarning("macro %s needs arguments", idf->id_text);
+                       */
+                       UnGetChar();
+                       return 0;
+               } else
+                       getactuals(args, 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);
+
+       /*      According to the ANSI definition:
+
+                       #define a +
+                       a+b; --> + + b ;
+               
+               'a' must be substituded, but the result should be
+               three tokens: + + ID. Because this preprocessor is
+               character based, we have a problem.
+               For now: just insert a space after all tokens,
+               until ANSI fixes this flaw.
+       */
+       *repl->r_ptr++ = ' ';
+       *repl->r_ptr = '\0';
+
+       if (idf != previdf)
+               maccount(repl, idf);
+       return 1;
+}
+
+getactuals(args, idf)
+       register struct args *args;
+       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 int nps = idf->id_macro->mc_nps;
+       register int argcnt;
+       register int ch;
+
+       argcnt = 0;
+       args->a_expvec[0] = args->a_expptr = &args->a_expbuf[0];
+       args->a_rawvec[0] = args->a_rawptr = &args->a_rawbuf[0];
+       if ((ch = GetChar()) != ')') {
+               PushBack();
+               while ((ch = actual(args, idf)) != ')' ) {
+                       if (ch != ',') {
+                               lexerror("illegal macro call");
+                               return;
+                       }
+                       stash(args, '\0');
+                       ++argcnt;
+                       args->a_expvec[argcnt] = args->a_expptr;
+                       args->a_rawvec[argcnt] = args->a_rawptr;
+                       if (argcnt == STDC_NPARAMS)
+                               strict("number of parameters exceeds ANSI standard");
+                       if (argcnt >= NPARAMS)
+                               fatal("argument vector overflow");
+               }
+               stash(args, '\0');
+               ++argcnt;
+       }
+       if (argcnt < nps)
+               lexerror("too few macro arguments");
+       if (argcnt > nps)
+               lexerror("too many macro arguments");
+}
+
+int
+actual(args, idf)
+       register struct args *args;
+       register struct idf *idf;
+{
+       /*      This routine deals with the scanning of an actual parameter.
+               It keeps in account the openning and clossing brackets,
+               preprocessor numbers, strings and character constants.
+       */
+       register int ch;
+       register int level = 0;
+
+       while (1) {
+               ch = GetChar();
+
+               if (class(ch) == STIDF || class(ch) == STELL) {
+                       /*      Scan a preprocessor identifier token. If the
+                               token is a macro, it is expanded first.
+                       */
+                       char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
+                       register char *p = buf;
+                       register struct idf *idef;
+                       register int pos = -1;
+                       register int hash;
+                       extern int idfsize;
+                       int size;
+
+                       hash = STARTHASH();
+                       do {
+                               if (++pos < idfsize) {
+                                       *p++ = ch;
+                                       hash = ENHASH(hash, ch, pos);
+                               }
+                               ch = GetChar();
+                       } while (in_idf(ch));
+                       hash = STOPHASH(hash);
+                       *p++ = '\0';
+                       UnGetChar();
+
+                       /*      When the identifier has an associated macro
+                               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
+                               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][+-]}}*
+                       */
+                       do {
+                               stash(args, ch);
+                               if ((ch = GetChar()) == 'e' || ch == 'E') {
+                                       ch = GetChar();
+                                       if (ch == '+' || ch == '-') {
+                                               stash(args, ch);
+                                               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);
+               } else if (ch == ')' || ch == ']' || ch == '}') {
+                       level--;
+                       /* clossing parenthesis of macro call */
+                       if (ch == ')' && level < 0)
+                               return ')';
+                       stash(args, ch);
+               } else if (ch == ',') {
+                       if (level <= 0) { /* comma separator for next argument */
+                               if (level)
+                                       lexerror("unbalanced parenthesis");
+                               return ',';
+                       }
+                       stash(args, ch);
+               } else if (ch == '\n') {
+                       /* newlines are accepted as white spaces */
+                       LineNumber++;
+                       while ((ch = GetChar()), class(ch) == STSKIP)
+                               /* VOID */;
+
+                       /*      This piece of code needs some explanation:
+                               consider the call of a macro defined as:
+                                       #define sum(a,b) (a+b)
+                               in the following form:
+                                       sum(
+                                       #include phone_number
+                                       ,2);
+                               in which case the include must be handled
+                               interpreted as such.
+                       */
+                       if (ch == '#')
+                               domacro();
+                       UnGetChar();
+                       stash(args, ' ');
+               } else if (ch == '/') {
+                       /* comments are treated as one white space token */
+                       if ((ch = GetChar()) == '*') {
+                               skipcomment();
+                               stash(args, ' ');
+                       } else {
+                               UnGetChar();
+                               stash(args, '/');
+                       }
+               } else if (ch == '\'' || ch == '"') {
+                       /*      Strings are considered as ONE token, thus no
+                               replacement within strings.
+                       */
+                       register int match = ch;
+
+                       stash(args, ch);
+                       while ((ch = GetChar()) != EOI) {
+                               if (ch == match)
+                                       break;
+                               if (ch == '\\') {
+                                       stash(args, ch);
+                                       ch = GetChar();
+                               } else if (ch == '\n') {
+                                       lexerror("newline in string");
+                                       LineNumber++;
+                                       stash(args, match);
+                                       break;
+                               }
+                               stash(args, ch);
+                       }
+                       if (ch != match) {
+                               lexerror("unterminated macro call");
+                               return ')';
+                       }
+                       stash(args, ch);
+               } 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++;
+       }
+}
+
+macro_func(idef)
+       register struct idf *idef;
+{
+       /*      macro_func() performs the special actions needed with some
+               macros.  These macros are __FILE__ and __LINE__ which
+               replacement texts must be evaluated at the time they are
+               used.
+       */
+       register struct macro *mac = idef->id_macro;
+       static char FilNamBuf[PATHLENGTH];
+       char *long2str();
+
+       switch (idef->id_text[2]) {
+       case 'F':                       /* __FILE__     */
+               FilNamBuf[0] = '"';
+               strcpy(&FilNamBuf[1], FileName);
+               strcat(FilNamBuf, "\"");
+               mac->mc_text = FilNamBuf;
+               mac->mc_length = strlen(FilNamBuf);
+               break;
+       case 'L':                       /* __LINE__     */
+               mac->mc_text = long2str((long)LineNumber, 10);
+               mac->mc_length = 1;
+               break;
+       default:
+               crash("(macro_func)");
+               /*NOTREACHED*/
+       }
+}
+
+macro2buffer(repl, idf, args)
+       register struct repl *repl;
+       register struct idf *idf;
+       register struct args *args;
+{
+       /*      macro2buffer expands the replacement list and places the
+               result onto the replacement buffer. It deals with the #
+               and ## operators, and inserts the actual parameters.
+               The argument buffer contains the raw argument (needed
+               for the ## operator), and the expanded argument (for
+               all other parameter substitutions).
+
+               The grammar of the replacement list is:
+
+                       repl_list:      TOKEN repl_list
+                               |       PARAMETER repl_list
+                               |       '#' PARAMETER
+                               |       TOKEN '##' TOKEN
+                               |       PARAMETER '##' TOKEN
+                               |       TOKEN '##' PARAMETER
+                               |       PARAMETER '##' PARAMETER
+                               ;
+               
+               As the grammar indicates, we could make a DFA and
+               use this finite state machine for the replacement
+               list parsing (inserting the arguments, etc.).
+
+               Currently we go through the replacement list in a
+               linear fashion. This is VERY expensive, something
+               smarter should be done (but even a DFA is O(|s|)).
+       */
+       register char *ptr = idf->id_macro->mc_text;
+       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 */
+                       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];
+
+                       while (*q)
+                               *repl->r_ptr++ = *q++;
+
+                       *repl->r_ptr++ = ' ';
+               } 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");
+       return;
+}
+
+char *
+stringify(repl, ptr, args)
+       register struct repl *repl;
+       register char *ptr;
+       register struct args *args;
+{
+       /*      If a parameter is immediately preceded by a # token
+               both are replaced by a single string literal that
+               contains the spelling of the token sequence for the
+               corresponding argument.
+               Each occurrence of white space between the argument's
+               tokens become a single space character in the string
+               literal. White spaces before the first token and after
+               the last token comprising the argument are deleted.
+               To retain the original spelling we insert backslashes
+               as appropriate. We only escape backslashes if they
+               occure within string tokens.
+       */
+       register int space = 1;         /* skip leading spaces */
+       register int delim = 0;         /* string or character constant delim */
+       register int backslash = 0;     /* last character was a \ */
+
+       /* skip spaces macro replacement list */
+       while ((*ptr & FORMALP) == 0 && is_wsp(*ptr))
+               ptr++;
+
+       if (*ptr & FORMALP) {
+               register int n = *ptr++ & 0177;
+               register char *p;
+               
+               ASSERT(n != 0);
+               p = args->a_expvec[n-1];
+               *repl->r_ptr++ = '"';
+               while (*p) {
+                       if (is_wsp(*p)) {
+                               if (!space) {
+                                       space = 1;
+                                       *repl->r_ptr++ = ' ';
+                               }
+                               p++;
+                               continue;
+                       }
+                       space = 0;
+
+                       if (!delim && (*p == '"' || *p == '\''))
+                               delim = *p;
+                       else if (*p == delim && !backslash)
+                               delim = 0;
+                       backslash = *p == '\\';
+                       if (*p == '"' || (delim && *p == '\\'))
+                               *repl->r_ptr++ = '\\';
+                       *repl->r_ptr++ = *p++;
+               }
+
+               /* trim spaces in the replacement list */
+               for (--repl->r_ptr; is_wsp(*repl->r_ptr); repl->r_ptr--)
+                       /* VOID */;
+               *++repl->r_ptr = '"';
+               ++repl->r_ptr;  /* oops, one to far */
+       } else
+               error("illegal use of # operator");
+       return ptr;
+}
+
+stash(args, ch)
+       register struct args *args;
+       register int ch;
+{
+       /*      Stash characters into the macro expansion buffer.
+       */
+       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;
+
+                       
+}
+#endif NOPP
diff --git a/lang/cem/cemcom.ansi/replace.str b/lang/cem/cemcom.ansi/replace.str
new file mode 100644 (file)
index 0000000..f4eccae
--- /dev/null
@@ -0,0 +1,39 @@
+struct repl {
+       struct  repl *next;
+       struct  args *r_args;           /* replacement parameters */
+       char    r_text[LAPBUF];         /* replacement text */
+       char    *r_ptr;                 /* replacement text pointer */
+};
+
+/* ALLOCDEF "repl" 4 */
+
+#define NO_REPL                (struct repl *)0
+
+/*     The implementation of the ## operator is currently very clumsy.
+       When the the ## operator is used the arguments are taken from
+       the raw buffer; this buffer contains a precise copy of the
+       original argument. The fully expanded copy is in the arg buffer.
+       The two copies are here explicitely because:
+
+               #define ABC     f()
+               #define ABCD    2
+               #define g(x, y) x ## y + h(x)
+
+               g(ABC, D);
+
+       In this case we need two copies: one raw copy for the pasting
+       operator, and an expanded one as argument for h().
+*/
+struct args {
+       char    *a_expptr;              /* expanded argument pointer */
+       char    *a_expvec[NPARAMS];     /* expanded argument vector */
+       char    a_expbuf[ARGBUF];       /* expanded argument buffer space */
+       char    *a_rawptr;              /* raw argument pointer */
+       char    *a_rawvec[NPARAMS];     /* raw argument vector */
+       char    a_rawbuf[ARGBUF];       /* raw argument buffer space */
+};
+
+/* ALLOCDEF "args" 2 */
+
+#define NO_ARGS                (struct args *)0
+
diff --git a/lang/cem/cemcom.ansi/scan.c b/lang/cem/cemcom.ansi/scan.c
new file mode 100644 (file)
index 0000000..6e89228
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* PREPROCESSOR: SCANNER FOR THE ACTUAL PARAMETERS OF MACROS   */
+
+#include       "nopp.h"
+
+#ifndef NOPP
+/*     This file contains the function getactuals() which scans an actual
+       parameter list and splits it up into a list of strings, each one
+       representing an actual parameter.
+*/
+
+#include       "lapbuf.h"      /* UF */
+#include       "nparams.h"     /* UF */
+
+#include       "input.h"
+#include       "class.h"
+#include       "idf.h"
+#include       "macro.h"
+#include       "interface.h"
+#include       "file_info.h"
+
+#define        EOS             '\0'
+#define        overflow()      (fatal("actual parameter buffer overflow"))
+
+PRIVATE char apbuf[LAPBUF]; /* temporary storage for actual parameters */
+PRIVATE char *actparams[NPARAMS]; /* pointers to the text of the actuals */
+PRIVATE char *aptr;    /* pointer to last inserted character in apbuf  */
+
+#define        copy(ch)        ((aptr < &apbuf[LAPBUF]) ? (*aptr++ = ch) : overflow())
+
+PRIVATE int nr_of_params;      /* number of actuals read until now     */
+
+PRIVATE char **
+getactuals(idef)
+       register struct idf *idef;
+{
+       /*      getactuals() collects the actual parameters and turns them
+               into a list of strings, a pointer to which is returned.
+       */
+       register acnt = idef->id_macro->mc_nps;
+
+       nr_of_params = 0;
+       actparams[0] = aptr = &apbuf[0];
+       copyact('(', ')', 0);   /* read the actual parameters   */
+       copy(EOS);              /* mark the end of it all       */
+
+       if (!nr_of_params++)    {               /* 0 or 1 parameter     */
+               /* there could be a ( <spaces, comment, ...> )
+               */
+               register char *p = actparams[0];
+
+               while ((class(*p) == STSKIP) || (*p == '\n')) {
+                               ++p;
+               }
+
+               if (!*p) {      /* the case () : 0 parameters   */
+                       nr_of_params--;
+               }
+       }
+
+       if (nr_of_params != acnt)       {
+               /*      argument mismatch: too many or too few
+                       actual parameters.
+               */
+               lexwarning("argument mismatch, %s", idef->id_text);
+
+               while (nr_of_params < acnt) {
+                       /*      too few paraeters: remaining actuals are ""
+                       */
+                       actparams[nr_of_params] = "";
+                       nr_of_params++;
+               }
+       }
+
+       return actparams;
+}
+
+PRIVATE
+copyact(ch1, ch2, lvl)
+       char ch1, ch2;
+       int lvl;
+{
+       /*      copyact() is taken from Ceriel Jacobs' LLgen, with
+               permission.  Its task is to build a list of actuals
+               parameters, which list is surrounded by '(' and ')' and in
+               which the parameters are separated by ',' if there are
+               more than 1. The balancing of '(',')' and '[',']' and
+               '{','}' is taken care of by calling this function
+               recursively. At each level lvl, copyact() reads the input,
+               upto the corresponding closing bracket.
+
+               Opening bracket is ch1, closing bracket is ch2. If
+               lvl != 0, copy opening and closing parameters too.
+       */
+       register int ch;                /* Current char */
+       register int match;             /* used to read strings */
+
+       if (lvl) {
+               copy(ch1);
+       }
+
+       for (;;)        {
+               LoadChar(ch);
+
+               if (ch == ch2)  {
+                       if (lvl) {
+                               copy(ch);
+                       }
+                       return;
+               }
+
+               switch(ch)      {
+
+#ifdef __MATCHING_PAR__
+               case ')':
+               case '}':
+               case ']':
+                       lexerror("unbalanced parenthesis");
+                       break;
+#endif __MATCHING_PAR__
+
+               case '(':
+                       copyact('(', ')', lvl+1);
+                       break;
+
+#ifdef __MATCHING_PAR__
+               case '{':
+                       /*      example:
+                                       #define declare(v, t)   t v
+                                       declare(v, union{int i, j; float r;});
+                       */
+                       copyact('{', '}', lvl+1);
+                       break;
+
+               case '[':
+                       copyact('[', ']', lvl+1);
+                       break;
+#endif __MATCHING_PAR__
+
+               case '\n':
+                       LineNumber++;
+                       while (LoadChar(ch), ch == '#') {
+                               /*      This piece of code needs some
+                                       explanation: consider the call of
+                                       the macro defined as:
+                                               #define sum(b,c) (b + c)
+                                       in the following form:
+                                               sum(
+                                               #include my_phone_number
+                                               ,2)
+                                       in which case the include must be
+                                       interpreted as such.
+                               */
+                               domacro();      /* has read nl, vt or ff */
+                               /* Loop, for another control line */
+                       }
+
+                       PushBack();
+                       copy(' ');
+                       break;
+
+               case '/':
+                       LoadChar(ch);
+
+                       if (ch == '*')  {       /* skip comment */
+                               skipcomment();
+                               continue;
+                       }
+
+                       PushBack();
+                       copy('/');
+                       break;
+
+               case ',':
+                       if (!lvl)       {
+                               /* next parameter encountered */
+                               copy(EOS);
+
+                               if (++nr_of_params >= NPARAMS) {
+                                       fatal("too many actual parameters");
+                               }
+
+                               actparams[nr_of_params] = aptr;
+                       }
+                       else    {
+                               copy(ch);
+                       }
+                       break;
+
+               case '\'':
+               case '"' :
+                       /*      watch out for brackets in strings, they do
+                               not count !
+                       */
+                       match = ch;
+                       copy(ch);
+                       while (LoadChar(ch), ch != EOI) {
+                               if (ch == match) {
+                                       break;
+                               }
+
+                               if (ch == '\\') {
+                                       copy(ch);
+                                       LoadChar(ch);
+                               }
+                               else
+                               if (ch == '\n') {
+                                       lexerror("newline in string");
+                                       LineNumber++;
+                                       copy(match);
+                                       break;
+                               }
+
+                               copy(ch);
+                       }
+
+                       if (ch == match)        {
+                               copy(ch);
+                               break;
+                       }
+                       /* Fall through */
+
+               case EOI :
+                       lexerror("unterminated macro call");
+                       return;
+
+               default:
+                       copy(ch);
+                       break;
+               }
+       }
+}
+#endif NOPP
diff --git a/lang/cem/cemcom.ansi/sizes.h b/lang/cem/cemcom.ansi/sizes.h
new file mode 100644 (file)
index 0000000..7508a27
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* VARIOUS TARGET MACHINE SIZE DESCRIPTORS */
+
+#include "nofloat.h"
+#include "nocross.h"
+#include "target_sizes.h"
+
+#ifndef NOCROSS
+extern arith
+       short_size, word_size, dword_size, int_size, long_size,
+#ifndef NOFLOAT
+       float_size, double_size, lngdbl_size,
+#endif NOFLOAT
+       pointer_size;
+#else NOCROSS
+#define short_size     (SZ_SHORT)
+#define word_size      (SZ_WORD)
+#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
+
+extern arith max_int, max_unsigned;    /* cstoper.c    */
diff --git a/lang/cem/cemcom.ansi/skip.c b/lang/cem/cemcom.ansi/skip.c
new file mode 100644 (file)
index 0000000..36ca38c
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* PREPROCESSOR: INPUT SKIP FUNCTIONS */
+
+#include       "nopp.h"
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "class.h"
+#include       "input.h"
+
+#ifndef NOPP
+int
+skipspaces(ch, skipnl)
+       register int ch;
+{
+       /*      skipspaces() skips any white space and returns the first
+               non-space character.
+       */
+       for (;;) {
+               while (class(ch) == STSKIP)
+                       ch = GetChar();
+               if (skipnl && class(ch) == STNL) {
+                       ch = GetChar();
+                       ++LineNumber;
+                       continue;
+               }
+
+               /* \\\n are handled by trigraph */
+
+               if (ch == '/') {
+                       ch = GetChar();
+                       if (ch == '*') {
+                               skipcomment();
+                               ch = GetChar();
+                       }
+                       else    {
+                               UnGetChar();
+                               return '/';
+                       }
+               }
+               else
+                       return ch;
+       }
+}
+#endif NOPP
+
+SkipToNewLine(garbage)
+       int garbage;
+{
+       register int ch;
+       register int pstrict = 0;
+
+       UnGetChar();
+       while ((ch = GetChar()) != '\n') {
+               if (ch == '/') {
+                       if ((ch = GetChar()) == '*') {
+                               skipcomment();
+                               continue;
+                       }
+               }
+               if (garbage && !is_wsp(ch))
+                       pstrict = 1;
+       }
+       ++LineNumber;
+       return pstrict;
+}
diff --git a/lang/cem/cemcom.ansi/specials.h b/lang/cem/cemcom.ansi/specials.h
new file mode 100644 (file)
index 0000000..f086845
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* OCCURANCES OF SPECIAL IDENTIFIERS */
+
+#define        SP_SETJMP       1
+
+#define        SP_TOTAL        1
+
+struct sp_id   {
+       char *si_identifier;    /* its name                     */
+       int si_flag;            /* index into sp_occurred array */
+};
+
+extern char sp_occurred[];             /* idf.c        */
+extern struct sp_id special_ids[];     /* main.c       */
diff --git a/lang/cem/cemcom.ansi/stack.c b/lang/cem/cemcom.ansi/stack.c
new file mode 100644 (file)
index 0000000..3be2dec
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     S T A C K / U N S T A C K  R O U T I N E S      */
+
+#include       "lint.h"
+#include       "nofloat.h"
+#include       <system.h>
+#include       <em.h>
+#include       "debug.h"
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "Lpars.h"
+#include       "arith.h"
+#include       "stack.h"
+#include       "type.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "struct.h"
+#include       "level.h"
+#include       "mes.h"
+#include       "noRoption.h"
+
+/* #include    <em_reg.h> */
+
+extern char options[];
+
+static struct stack_level UniversalLevel;
+struct stack_level *local_level = &UniversalLevel;
+/*     The main reason for having this secondary stacking
+       mechanism besides the linked lists pointed to by the idf's
+       is efficiency.
+       To remove the idf's of a given level, one could scan the
+       hash table and chase down the idf chains; with a hash
+       table size of 100 this is feasible, but with a size of say
+       100000 this becomes painful. Therefore all idf's are also
+       kept in a stack of sets, one set for each level.
+*/
+
+int level;     /* Always equal to local_level->sl_level. */
+
+stack_level()  {
+       /*      A new level is added on top of the identifier stack.
+       */
+       register struct stack_level *stl = new_stack_level();
+       register struct stack_level *loclev = local_level;
+       
+       loclev->sl_next = stl;
+       stl->sl_previous = loclev;
+       stl->sl_level = ++level;
+       stl->sl_max_block = loclev->sl_max_block;
+       local_level = stl;
+#ifdef LINT
+       lint_start_local();
+#endif LINT
+}
+
+stack_idf(idf, stl)
+       struct idf *idf;
+       register struct stack_level *stl;
+{
+       /*      The identifier idf is inserted in the stack on level stl.
+       */
+       register struct stack_entry *se = new_stack_entry();
+
+       /* link it into the stack level */
+       se->next = stl->sl_entry;
+       se->se_idf = idf;
+       stl->sl_entry = se;
+}
+
+struct stack_level *
+stack_level_of(lvl)
+{
+       /*      The stack_level corresponding to level lvl is returned.
+               The stack should probably be an array, to be extended with
+               realloc where needed.
+       */
+       register struct stack_level *stl;
+
+       if (lvl == level)
+               return local_level;
+       stl = &UniversalLevel;
+               
+       while (stl->sl_level != lvl)
+               stl = stl->sl_next;
+       return stl;
+}
+
+unstack_level()
+{
+       /*      The top level of the identifier stack is removed.
+       */
+       struct stack_level *lastlvl;
+
+#ifdef DEBUG
+       if (options['t'])
+               dumpidftab("before unstackidfs", 0);
+#endif DEBUG
+
+#ifdef LINT
+       lint_local_level(local_level);
+#endif LINT
+
+       /*      The implementation below is more careful than strictly
+               necessary. Optimists may optimize it afterwards.
+       */
+       while (local_level->sl_entry)   {
+               register struct stack_entry *se = local_level->sl_entry;
+               register struct idf *idf = se->se_idf;
+               register struct def *def;
+               register struct sdef *sdef;
+               register struct tag *tag;
+
+               /* unlink it from the local stack level */
+               local_level->sl_entry = se->next;
+               free_stack_entry(se);
+
+               while ((def = idf->id_def) && def->df_level >= level)   {
+                       /* unlink it from the def list under the idf block */
+                       if (def->df_sc == LABEL)
+                               unstack_label(idf);
+                       else if (def->df_sc == REGISTER || def->df_sc == AUTO)
+                               FreeLocal(def->df_address);
+                       idf->id_def = def->next;
+                       free_def(def);
+                       update_ahead(idf);
+               }
+               while ( (sdef = idf->id_sdef)
+               &&      sdef->sd_level >= level
+               )       {
+                       /* unlink it from the sdef list under the idf block */
+                       idf->id_sdef = sdef->next;
+                       free_sdef(sdef);
+               }
+               while ( (tag = idf->id_struct)
+               &&      tag->tg_level >= level
+               )       {
+                       /* unlink it from the struct list under the idf block */
+                       idf->id_struct = tag->next;
+                       free_tag(tag);
+               }
+               while ((tag = idf->id_enum) && tag->tg_level >= level)  {
+                       /* unlink it from the enum list under the idf block */
+                       idf->id_enum = tag->next;
+                       free_tag(tag);
+               }
+       }
+       /*      Unlink the local stack level from the stack.
+       */
+       lastlvl = local_level;
+       local_level = local_level->sl_previous;
+       if (level >= L_LOCAL)   {
+               local_level->sl_max_block = lastlvl->sl_max_block;
+       }
+       free_stack_level(lastlvl);
+       local_level->sl_next = (struct stack_level *) 0;
+       level = local_level->sl_level;
+
+#ifdef DEBUG
+       if (options['t'])
+               dumpidftab("after unstackidfs", 0);
+#endif DEBUG
+}
+
+unstack_world()
+{
+       /*      The global level of identifiers is scanned, and final
+               decisions are taken about such issues as
+               extern/static/global and un/initialized.
+               Effects on the code generator: initialised variables
+               have already been encoded while the uninitialised ones
+               are not and have to be encoded at this moment.
+       */
+       register struct stack_entry *se = local_level->sl_entry;
+
+#ifdef LINT
+       lint_global_level(local_level);
+#endif LINT
+
+       open_name_list();
+
+       while (se)      {
+               register struct idf *idf = se->se_idf;
+               register struct def *def = idf->id_def;
+               
+               if (!def)       {
+                       /* global selectors, etc. */
+                       se = se->next;
+                       continue;
+               }
+               
+#ifdef DEBUG
+               if (options['a']) {
+                       char *symbol2str();
+
+                       print("\"%s\", %s, %s, %s, %s\n",
+                               idf->id_text,
+                               (def->df_alloc == 0) ? "no alloc" :
+                               (def->df_alloc == ALLOC_SEEN) ? "alloc seen" :
+                               (def->df_alloc == ALLOC_DONE) ? "alloc done" :
+                               "illegal alloc info",
+                               symbol2str(def->df_sc),
+                               def->df_initialized ? "init" : "no init",
+                               def->df_used ? "used" : "not used");
+               }
+#endif DEBUG
+               /*
+               /_* find final storage class *_/
+               if (def->df_sc == GLOBAL || def->df_sc == IMPLICIT)
+                       /_* even now we still don't know *_/
+                       def->df_sc = EXTERN;
+               */
+               
+               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
+                       def->df_sc = EXTERN;
+               }
+               
+               if (
+                       def->df_alloc == ALLOC_SEEN &&
+                       !def->df_initialized
+               )       {
+                       /* space must be allocated */
+                       bss(idf);
+                       if (def->df_sc != STATIC)
+                               namelist(idf->id_text); /* may be common */
+                       def->df_alloc = ALLOC_DONE;     /* see Note below */
+               }
+               se = se->next;
+       }
+       /*      Note:
+               df_alloc must be set to ALLOC_DONE because the idf entry
+               may occur several times in the list.
+               The reason for this is that the same name may be used
+               for different purposes on the same level, e.g.
+                       struct s {int s;} s;
+               is a legal definition and contains 3 defining occurrences
+               of s.
+               Each definition has been entered into the identifier stack.
+               Although only one of them concerns a variable, we meet the
+               s 3 times when scanning the identifier stack.
+       */
+}
+
+/*     A list of potential common names is kept, to be fed to
+       an understanding loader.  The list is written to a file
+       the name of which is nmlist.  If nmlist == NULL, no name
+       list is generated.
+*/
+extern char *nmlist;   /* BAH! -- main.c       */
+static File *nfp = 0;
+
+open_name_list()
+{
+       if (nmlist && sys_open(nmlist, OP_WRITE, &nfp) == 0)
+               fatal("cannot create namelist %s", nmlist);
+}
+
+namelist(nm)
+       char *nm;
+{
+       if (nmlist)     {
+               sys_write(nfp, nm, strlen(nm));
+               sys_write(nfp, "\n", 1);
+       }
+}
diff --git a/lang/cem/cemcom.ansi/stack.str b/lang/cem/cemcom.ansi/stack.str
new file mode 100644 (file)
index 0000000..fc32c87
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* IDENTIFIER STACK DEFINITIONS */
+
+/*     The identifier stack is implemented as a stack of sets.
+       The stack is implemented by a doubly linked list,
+       the sets by singly linked lists.
+*/
+
+struct stack_level     {
+       struct stack_level *next;
+       struct stack_level *sl_next;            /* upward link          */
+       struct stack_level *sl_previous;        /* downward link        */
+       struct stack_entry *sl_entry;           /* sideward link        */
+       arith sl_local_offset;          /* @ for first coming object    */
+       arith sl_max_block;             /* maximum size of sub-block    */
+       int sl_level;
+};
+
+/* ALLOCDEF "stack_level" 5 */
+
+struct stack_entry     {
+       struct stack_entry *next;
+       struct idf *se_idf;
+};
+
+/* ALLOCDEF "stack_entry" 5 */
+
+extern struct stack_level *local_level;
+extern struct stack_level *stack_level_of();
+extern int level;
diff --git a/lang/cem/cemcom.ansi/statement.g b/lang/cem/cemcom.ansi/statement.g
new file mode 100644 (file)
index 0000000..b105260
--- /dev/null
@@ -0,0 +1,472 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     STATEMENT SYNTAX PARSER */
+
+{
+#include       <em.h>
+
+#include       "lint.h"
+#include       "debug.h"
+#include       "botch_free.h"
+
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "type.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "expr.h"
+#include       "code.h"
+#include       "stack.h"
+#include       "def.h"
+#ifdef LINT
+#include       "l_lint.h"
+#include       "l_state.h"
+#endif LINT
+
+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.
+*/
+
+/* 9 */
+statement
+       {
+#ifdef LINT
+               lint_statement();
+#endif LINT
+       }
+:
+%if (AHEAD != ':')
+       expression_statement
+|
+       label ':' statement
+|
+       compound_statement
+|
+       if_statement
+|
+       while_statement
+|
+       do_statement
+|
+       for_statement
+|
+       switch_statement
+|
+       case_statement
+|
+       default_statement
+|
+       BREAK
+       {
+               code_break();
+#ifdef LINT
+               lint_break_stmt();
+#endif LINT
+       }
+       ';'
+|
+       CONTINUE
+       {
+               code_continue();
+#ifdef LINT
+               lint_continue_stmt();
+#endif LINT
+       }
+       ';'
+|
+       return_statement
+|
+       jump
+|
+       ';'
+;
+
+
+expression_statement
+       {       struct expr *expr;
+       }
+:
+       expression(&expr)
+       ';'
+               {
+#ifdef DEBUG
+                       print_expr("expression_statement", expr);
+#endif DEBUG
+                       code_expr(expr, RVAL, FALSE, NO_LABEL, NO_LABEL);
+                       free_expression(expr);
+               }
+;
+
+label
+       {       struct idf *idf;
+       }
+:
+       identifier(&idf)
+       {
+               /*      This allows the following absurd case:
+
+                               typedef int grz;
+                               main()  {
+                                       grz: printf("A labelled statement\n");
+                               }
+               */
+#ifdef LINT
+               lint_label();
+#endif LINT
+               define_label(idf);
+               C_df_ilb((label)idf->id_def->df_address);
+       }
+;
+
+if_statement
+       {
+               struct expr *expr;
+               label l_true = text_label();
+               label l_false = text_label();
+               label l_end = text_label();
+       }
+:
+       IF
+       '('
+       expression(&expr)
+               {
+                       opnd2test(&expr, IF);
+                       if (is_cp_cst(expr))    {
+                               /*      The comparison has been optimized
+                                       to a 0 or 1.
+                               */
+                               if (expr->VL_VALUE == (arith)0) {
+                                       C_bra(l_false);
+                               }
+                               /* else fall through */
+#ifdef LINT
+                               start_if_part(1);
+#endif LINT
+                       }
+                       else    {
+                               code_expr(expr, RVAL, TRUE, l_true, l_false);
+                               C_df_ilb(l_true);
+#ifdef LINT
+                               start_if_part(0);
+#endif LINT
+                       }
+                       free_expression(expr);
+               }
+       ')'
+       statement
+       [%prefer
+               ELSE
+                       {
+#ifdef LINT
+                               start_else_part();
+#endif LINT
+                               C_bra(l_end);
+                               C_df_ilb(l_false);
+                       }
+               statement
+                       {       C_df_ilb(l_end);
+#ifdef LINT
+                               end_if_else_stmt();
+#endif LINT
+                       }
+       |
+               empty
+                       {       C_df_ilb(l_false);
+#ifdef LINT
+                               end_if_stmt();
+#endif LINT
+                       }
+       ]
+;
+
+while_statement
+       {
+               struct expr *expr;
+               label l_break = text_label();
+               label l_continue = text_label();
+               label l_body = text_label();
+       }
+:
+       WHILE
+               {
+                       stack_stmt(l_break, l_continue);
+                       C_df_ilb(l_continue);
+               }
+       '('
+       expression(&expr)
+               {
+                       opnd2test(&expr, WHILE);
+                       if (is_cp_cst(expr))    {
+                               if (expr->VL_VALUE == (arith)0) {
+                                       C_bra(l_break);
+                               }
+#ifdef LINT
+                               start_loop_stmt(WHILE, 1,
+                                       expr->VL_VALUE != (arith)0);
+#endif LINT
+                       }
+                       else    {
+                               code_expr(expr, RVAL, TRUE, l_body, l_break);
+                               C_df_ilb(l_body);
+#ifdef LINT
+                               start_loop_stmt(WHILE, 0, 0);
+#endif LINT
+                       }
+               }
+       ')'
+       statement
+               {
+                       C_bra(l_continue);
+                       C_df_ilb(l_break);
+                       unstack_stmt();
+                       free_expression(expr);
+#ifdef LINT
+                       end_loop_stmt();
+#endif LINT
+               }
+;
+
+do_statement
+       {       struct expr *expr;
+               label l_break = text_label();
+               label l_continue = text_label();
+               label l_body = text_label();
+       }
+:
+       DO
+               {       C_df_ilb(l_body);
+                       stack_stmt(l_break, l_continue);
+#ifdef LINT
+                       start_loop_stmt(DO, 1, 1);
+#endif LINT
+               }
+       statement
+       WHILE
+       '('
+               {       C_df_ilb(l_continue);
+               }
+       expression(&expr)
+               {
+                       opnd2test(&expr, WHILE);
+                       if (is_cp_cst(expr))    {
+                               if (expr->VL_VALUE == (arith)1) {
+                                       C_bra(l_body);
+                               }
+#ifdef LINT
+                               end_do_stmt(1, expr->VL_VALUE != (arith)0);
+#endif LINT
+                       }
+                       else    {
+                               code_expr(expr, RVAL, TRUE, l_body, l_break);
+#ifdef LINT
+                               end_do_stmt(0, 0);
+#endif LINT
+                       }
+                       C_df_ilb(l_break);
+               }
+       ')'
+       ';'
+               {
+                       unstack_stmt();
+                       free_expression(expr);
+               }
+;
+
+for_statement
+       {       struct expr *e_init = 0, *e_test = 0, *e_incr = 0;
+               label l_break = text_label();
+               label l_continue = text_label();
+               label l_body = text_label();
+               label l_test = text_label();
+#ifdef LINT
+               int const = 1, cond = 1;        /* the default case */
+#endif LINT
+       }
+:
+       FOR
+               {       stack_stmt(l_break, l_continue);
+               }
+       '('
+       [
+               expression(&e_init)
+               {       code_expr(e_init, RVAL, FALSE, NO_LABEL, NO_LABEL);
+               }
+       ]?
+       ';'
+               {       C_df_ilb(l_test);
+               }
+       [
+               expression(&e_test)
+               {
+                       opnd2test(&e_test, FOR);
+                       if (is_cp_cst(e_test))  {
+                               if (e_test->VL_VALUE == (arith)0)       {
+                                       C_bra(l_break);
+                               }
+#ifdef LINT
+                               const = 1,
+                                       cond = e_test->VL_VALUE != (arith)0;
+#endif LINT
+                       }
+                       else    {
+                               code_expr(e_test, RVAL, TRUE, l_body, l_break);
+                               C_df_ilb(l_body);
+#ifdef LINT
+                               const = 0, cond = 0;
+#endif LINT
+                       }
+               }
+       ]?
+       ';'
+       expression(&e_incr)?
+       ')'
+               {
+#ifdef LINT
+                       start_loop_stmt(FOR, const, cond);
+#endif LINT
+               }
+       statement
+               {
+#ifdef LINT
+                       end_loop_stmt();
+#endif LINT
+                       C_df_ilb(l_continue);
+                       if (e_incr)
+                               code_expr(e_incr, RVAL, FALSE,
+                                                       NO_LABEL, NO_LABEL);
+                       C_bra(l_test);
+                       C_df_ilb(l_break);
+                       unstack_stmt();
+                       free_expression(e_init);
+                       free_expression(e_test);
+                       free_expression(e_incr);
+               }
+;
+
+switch_statement
+       {
+               struct expr *expr;
+       }
+:
+       SWITCH
+       '('
+       expression(&expr)
+               {
+                       code_startswitch(&expr);
+#ifdef LINT
+                       start_switch_part(expr);
+#endif LINT
+               }
+       ')'
+       statement
+               {
+#ifdef LINT
+                       end_switch_stmt();
+#endif LINT
+                       code_endswitch();
+                       free_expression(expr);
+               }
+;
+
+case_statement
+       {
+               struct expr *expr;
+       }
+:
+       CASE
+       constant_expression(&expr)
+               {
+#ifdef LINT
+                       lint_case_stmt(0);
+#endif LINT
+                       code_case(expr);
+                       free_expression(expr);
+               }
+       ':'
+       statement
+;
+
+default_statement
+:
+       DEFAULT
+               {
+#ifdef LINT
+                       lint_case_stmt(1);
+#endif LINT
+                       code_default();
+               }
+       ':'
+       statement
+;
+
+return_statement
+       {       struct expr *expr = 0;
+       }
+:
+       RETURN
+       [
+               expression(&expr)
+               {
+#ifdef LINT
+                       lint_ret_conv(expr);
+#endif LINT
+
+                       do_return_expr(expr);
+                       free_expression(expr);
+#ifdef LINT
+                       lint_return_stmt(1);
+#endif LINT
+               }
+       |
+               empty
+               {
+                       do_return();
+#ifdef LINT
+                       lint_return_stmt(0);
+#endif LINT
+               }
+       ]
+       ';'
+;
+
+jump
+       {       struct idf *idf;
+       }
+:
+       GOTO
+       identifier(&idf)
+       ';'
+               {
+                       apply_label(idf);
+                       C_bra((label)idf->id_def->df_address);
+#ifdef LINT
+                       lint_jump_stmt(idf);
+#endif LINT
+               }
+;
+
+compound_statement:
+       '{'
+               {
+                       stack_level();
+               }
+       [%while ((DOT != IDENTIFIER && AHEAD != ':') ||
+                (DOT == IDENTIFIER && AHEAD == IDENTIFIER))
+                       /* >>> conflict on TYPE_IDENTIFIER, IDENTIFIER */
+               declaration
+       ]*
+       [%persistent
+               statement
+       ]*
+       '}'
+               {
+                       unstack_level();
+               }
+;
diff --git a/lang/cem/cemcom.ansi/stb.c b/lang/cem/cemcom.ansi/stb.c
new file mode 100644 (file)
index 0000000..ca20cfd
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* library routine for copying structs */
+
+__stb(n, f, t)
+       register char *f, *t; register n;
+{
+       if (n > 0)
+               do
+                       *t++ = *f++;
+               while (--n);
+}
diff --git a/lang/cem/cemcom.ansi/stmt.str b/lang/cem/cemcom.ansi/stmt.str
new file mode 100644 (file)
index 0000000..a5f4768
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     S T A T E M E N T - B L O C K   D E F I N I T I O N S   */
+
+struct stmt_block      {
+       struct stmt_block *next;
+       label st_break;
+       label st_continue;
+};
+
+/* ALLOCDEF "stmt_block" 5 */
diff --git a/lang/cem/cemcom.ansi/struct.c b/lang/cem/cemcom.ansi/struct.c
new file mode 100644 (file)
index 0000000..ad0cc42
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     ADMINISTRATION OF STRUCT AND UNION DECLARATIONS */
+
+#include       "nobitfield.h"
+#include       "debug.h"
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "arith.h"
+#include       "stack.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "type.h"
+#include       "proto.h"
+#include       "struct.h"
+#include       "field.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "align.h"
+#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.
+*/
+static field_busy = 0;
+
+extern char options[];
+int lcm();
+
+/*     The semantics of the identification of structure/union tags is
+       obscure.  Some highly regarded compilers are found out to accept,
+       e.g.:
+               f(xp) struct aap *xp;   {
+                       struct aap {char *za;};
+                       xp->za;
+               }
+       Equally highly regarded software uses this feature, so we shall
+       humbly oblige.
+       The rules we use are:
+       1.      A structure definition applies at the level where it is
+               found, unless there is a structure declaration without a
+               definition on an outer level, in which case the definition
+               is applied at that level.
+       2.      A selector is applied on the same level as on which its
+               structure is being defined.
+
+       If below struct is mentioned, union is implied (and sometimes enum
+       as well).
+*/
+
+add_sel(stp, tp, idf, sdefpp, szp, fd) /* this is horrible */
+       register struct type *stp;      /* type of the structure */
+       struct type *tp;                /* type of the selector */
+       register struct idf *idf;       /* idf of the selector */
+       struct sdef ***sdefpp;  /* address of hook to selector definition */
+       arith *szp;             /* pointer to struct size upto here */
+       struct field *fd;
+{
+       /*      The selector idf with type tp is added to two chains: the
+               selector identification chain starting at idf->id_sdef,
+               and to the end of the member list starting at stp->tp_sdef.
+               The address of the hook in the latest member (sdef) is
+               given in sdefpp; the hook itself must still be empty.
+       */
+       arith offset;
+#ifndef NOBITFIELD
+       extern arith add_field();
+#endif NOBITFIELD
+
+       struct tag *tg = stp->tp_idf->id_struct;        /* or union */
+       struct sdef *sdef = idf->id_sdef;
+       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     */
+                       offset = align(*szp, tp->tp_align);
+                       field_busy = 0;
+               }
+               else    {
+                       /*      if something is wrong, the type of the
+                               specified selector remains unchanged; its
+                               bitfield specifier, however, is thrown away.
+                       */
+                       offset = add_field(szp, fd, &tp, idf, stp);
+               }
+#else NOBITFIELD
+               offset = align(*szp, tp->tp_align);
+               field_busy = 0;
+#endif NOBITFIELD
+       }
+       else    {       /* (stp->tp_fund == UNION)              */
+               if (fd) {
+                       error("fields not allowed in unions");
+                       free_field(fd);
+                       fd = 0;
+               }
+               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;
+
+       /*      link into selector descriptor list of this id
+       */
+       newsdef->next = sdef;
+       idf->id_sdef = newsdef;
+
+       newsdef->sd_level = lvl;
+       newsdef->sd_idf = idf;
+       newsdef->sd_stype = stp;
+       newsdef->sd_type = tp;
+       newsdef->sd_offset = offset;
+
+#ifndef NOBITFIELD
+       if (tp->tp_fund == FIELD)
+               tp->tp_field->fd_sdef = newsdef;
+#endif NOBITFIELD
+
+       stack_idf(idf, stack_level_of(lvl));
+
+       /*      link into selector definition list of the struct/union
+       */
+       **sdefpp = newsdef;
+       *sdefpp = &newsdef->sd_sdef;
+
+       /* update the size of the struct/union upward   */
+       if (stp->tp_fund == STRUCT && fd == 0)  {
+               /*      Note: the case that a bitfield is declared is
+                       handled by add_field() !
+               */
+               *szp = offset + size_of_type(tp, "member");
+               stp->tp_align = lcm(stp->tp_align, tp->tp_align);
+       }
+       else
+       if (stp->tp_fund == UNION)      {
+               arith sel_size = size_of_type(tp, "member");
+
+               if (*szp < sel_size)
+                       *szp = sel_size;
+               stp->tp_align = lcm(stp->tp_align, tp->tp_align);
+       }
+}
+
+check_selector(idf, stp)
+       register struct idf *idf;
+       struct type *stp;       /* the type of the struct */
+{
+       /*      checks if idf occurs already as a selector in
+               struct or union *stp.
+       */
+       register struct sdef *sdef = stp->tp_sdef;
+       
+       while (sdef)    {
+               if (sdef->sd_idf == idf)
+                       error("multiple selector %s", idf->id_text);
+               sdef = sdef->sd_sdef;
+       }
+}
+
+declare_struct(fund, idf, tpp)
+       register struct idf *idf;
+       struct type **tpp;
+{
+       /*      A struct, union or enum (depending on fund) with tag (!)
+               idf is declared, and its type (incomplete as it may be) is
+               returned in *tpp.
+               The idf may be missing (i.e. idf == 0), in which case an
+               anonymous struct etc. is defined.
+       */
+       extern char *symbol2str();
+       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_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
+                       *tpp = tg->tg_type;
+               }
+       }
+       else
+       if (tg && tg->tg_level == level)        {
+               /*      There is an already defined struct/union of this name
+                       on our level!
+               */
+               error("redeclaration of struct/union %s", idf->id_text);
+               declare_struct(fund, gen_idf(), tpp);
+               /* to allow a second struct_declaration_pack */
+       }
+       else    {
+               /* The struct is new. */
+               /* Hook in a new struct tag */
+               tg = new_tag();
+               tg->next = *tgp;
+               *tgp = tg;
+               tg->tg_level = level;
+               /* and supply room for a type */
+               tg->tg_type = create_type(fund);
+               tg->tg_type->tp_align =
+                       fund == ENUM ? int_align :
+                       fund == STRUCT ? struct_align :
+                       /* fund == UNION */ union_align;
+               tg->tg_type->tp_idf = idf;
+               *tpp = tg->tg_type;
+               stack_idf(idf, local_level);
+       }
+}
+
+apply_struct(fund, idf, tpp)
+       register struct idf *idf;
+       struct type **tpp;
+{
+       /*      The occurrence of a struct, union or enum (depending on
+               fund) with tag idf is noted. It may or may not have been
+               declared before. Its type (complete or incomplete) is
+               returned in *tpp.
+       */
+       register struct tag **tgp;
+
+       tgp = (is_struct_or_union(fund) ? &idf->id_struct : &idf->id_enum);
+
+       if (*tgp)
+               *tpp = (*tgp)->tg_type;
+       else
+               declare_struct(fund, idf, tpp);
+}
+
+struct sdef *
+idf2sdef(idf, tp)
+       register struct idf *idf;
+       struct type *tp;
+{
+       /*      The identifier idf is identified as a selector, preferably
+               in the struct tp, but we will settle for any unique
+               identification.
+               If the attempt fails, a selector of type error_type is
+               created.
+       */
+       register struct sdef **sdefp = &idf->id_sdef, *sdef;
+       
+       /* Follow chain from idf, to meet tp. */
+       while ((sdef = *sdefp)) {
+               if (equal_type(sdef->sd_stype, tp))
+                       return sdef;
+               sdefp = &(*sdefp)->next;
+       }
+       
+       /* 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);
+               }
+               return sdef;
+       }
+       
+       /* No luck; create an error entry. */
+       if (!is_anon_idf(idf))
+               error("unknown selector %s", idf->id_text);
+       *sdefp = sdef = new_sdef();
+       sdef->sd_idf = idf;
+       sdef->sd_stype = sdef->sd_type = error_type;
+       return sdef;
+}
+
+int
+uniq_selector(idf_sdef)
+       register struct sdef *idf_sdef;
+{
+       /*      Returns true if idf_sdef (which is guaranteed to exist)
+               is unique for this level, i.e there is no other selector
+               on this level with the same name or the other selectors
+               with the same name have the same offset.
+               See /usr/src/cmd/sed/sed.h for an example of this absurd
+               case!
+       */
+       
+       register struct sdef *sdef = idf_sdef->next;
+       
+       while (sdef && sdef->sd_level == idf_sdef->sd_level)    {
+               if (    sdef->sd_type != idf_sdef->sd_type
+               ||      sdef->sd_offset != idf_sdef->sd_offset
+               )       {
+                       return 0;               /* ambiguity found */
+               }
+               sdef = sdef->next;
+       }
+       return 1;
+}
+
+#ifndef NOBITFIELD
+arith
+add_field(szp, fd, fdtpp, idf, stp)
+       arith *szp;                     /* size of struct upto here     */
+       register struct field *fd;      /* bitfield, containing width   */
+       register struct type **fdtpp;   /* type of selector             */
+       struct idf *idf;                /* name of selector             */
+       register struct type *stp;      /* current struct descriptor    */
+{
+       /*      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.)
+       */
+       long bits_in_type = word_size * 8;
+       static int field_offset = (arith)0;
+       static struct type *current_struct = 0;
+       static long bits_declared;      /* nr of bits used in *field_offset */
+
+       if (current_struct != stp)      {
+               /*      This struct differs from the last one
+               */
+               field_busy = 0;
+               current_struct = stp;
+       }
+
+       if (    fd->fd_width < 0 ||
+               (fd->fd_width == 0 && !is_anon_idf(idf)) ||
+               fd->fd_width > bits_in_type
+       )       {
+               error("illegal field-width specified");
+               *fdtpp = error_type;
+               return field_offset;
+       }
+
+       switch ((*fdtpp)->tp_fund)      {
+       case CHAR:
+       case SHORT:
+       case INT:
+       case ENUM:
+       case LONG:
+               /* right type; size OK? */
+               if ((*fdtpp)->tp_size > word_size) {
+                       error("bit field type %s does not fit in a word",
+                               symbol2str((*fdtpp)->tp_fund));
+                       *fdtpp = error_type;
+                       return field_offset;
+               }
+               break;
+
+       default:
+               /* wrong type altogether */
+               error("field type cannot be %s",
+                               symbol2str((*fdtpp)->tp_fund));
+               *fdtpp = error_type;
+               return field_offset;
+       }
+
+       if (field_busy == 0)    {
+               /*      align this selector on the next boundary :
+                       the previous selector wasn't a bitfield.
+               */
+               field_offset = align(*szp, int_align);
+               *szp = field_offset + int_size;
+               stp->tp_align = lcm(stp->tp_align, int_align);
+               bits_declared = (arith)0;
+               field_busy = 1;
+       }
+
+       if (fd->fd_width > bits_in_type - bits_declared)        {
+               /*      field overflow: fetch next memory unit
+               */
+               field_offset = align(*szp, int_align);
+               *szp = field_offset + int_size;
+               stp->tp_align = lcm(stp->tp_align, int_align);
+               bits_declared = fd->fd_width;
+       }
+       else
+       if (fd->fd_width == 0)
+               /*      next field should be aligned on the next boundary.
+                       This will take care that no field will fit in the
+                       space allocated upto here.
+               */
+               bits_declared = bits_in_type + 1;
+       else    /* the bitfield fits in the current field       */
+               bits_declared += fd->fd_width;
+       
+       /*      Arrived here, the place where the selector is stored in the
+               struct is computed.
+               Now we need a mask to use its value in expressions.
+       */
+       *fdtpp = construct_type(FIELD, *fdtpp, 0, (arith)0, NO_PROTO);
+       (*fdtpp)->tp_field = fd;
+
+       /*      Set the mask right shifted. This solution avoids the
+               problem of having sign extension when using the mask for
+               extracting the value from the field-int.
+               Sign extension could occur on some machines when shifting
+               the mask to the left.
+       */
+       fd->fd_mask = (1 << fd->fd_width) - 1;
+
+       if (options['r'])       /* adjust the field at the right        */
+               fd->fd_shift = bits_declared - fd->fd_width;
+       else                    /* adjust the field at the left         */
+               fd->fd_shift = bits_in_type - bits_declared;
+       
+       return field_offset;
+}
+#endif NOBITFIELD
+
+/* some utilities */
+int
+is_struct_or_union(fund)
+       register int fund;
+{
+       return fund == STRUCT || fund == UNION;
+}
+
+/*     Greatest Common Divisor
+ */
+int
+gcd(m, n)
+       register int m, n;
+{
+       register int r;
+
+       while (n)       {
+               r = m % n;
+               m = n;
+               n = r;
+       }
+       return m;
+}
+
+/*     Least Common Multiple
+ */
+int
+lcm(m, n)
+       register int m, n;
+{
+       return m * (n / gcd(m, n));
+}
diff --git a/lang/cem/cemcom.ansi/struct.str b/lang/cem/cemcom.ansi/struct.str
new file mode 100644 (file)
index 0000000..7a9c0e4
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* SELECTOR DESCRIPTOR */
+
+struct sdef    {               /* for selectors */
+       struct sdef *next;
+       int sd_level;
+       struct idf *sd_idf;     /* its name */
+       struct sdef *sd_sdef;   /* the next selector */
+       struct type *sd_stype;  /* the struct it belongs to */
+       struct type *sd_type;   /* its type */
+       arith sd_offset;
+};
+
+/* ALLOCDEF "sdef" 50 */
+
+struct tag     {               /* for struct-, union- and enum tags */
+       struct tag *next;
+       int tg_level;
+       int tg_busy;    /* non-zero during declaration of struct/union pack */
+       struct type *tg_type;
+};
+
+
+/* ALLOCDEF "tag" 50 */
+
+struct sdef *idf2sdef();
diff --git a/lang/cem/cemcom.ansi/switch.c b/lang/cem/cemcom.ansi/switch.c
new file mode 100644 (file)
index 0000000..859766c
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*     S W I T C H - S T A T E M E N T  A D M I N I S T R A T I O N    */
+
+#include       "nofloat.h"
+#include       <em.h>
+#include       "debug.h"
+#include       "botch_free.h"
+#include       <alloc.h>
+#include       "density.h"
+#include       "Lpars.h"
+#include       "idf.h"
+#include       "label.h"
+#include       "arith.h"
+#include       "switch.h"
+#include       "code.h"
+#include       "assert.h"
+#include       "expr.h"
+#include       "type.h"
+#include       "noRoption.h"
+
+extern char options[];
+
+compact(nr, low, up)
+       arith low, up;
+{
+       /*      Careful! up - low might not fit in an arith. And then,
+               the test "up-low < 0" might also not work to detect this
+               situation! Or is this just a bug in the M68020/M68000?
+       */
+       arith diff = up - low;
+
+       return (nr == 0 || (diff >= 0 && diff / nr <= (DENSITY - 1)));
+}
+
+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)
+       For simplicity, we suppose int_size == word_size.
+*/
+
+code_startswitch(expp)
+       struct expr **expp;
+{
+       /*      Check the expression, stack a new case header and
+               fill in the necessary fields.
+       */
+       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 */
+       
+       switch (fund) {
+       case LONG:
+#ifndef NOROPTION
+               if (options['R'])
+                       warning("long in switch (cast to int)");
+#endif
+               int2int(expp, int_type);
+               break;
+#ifndef NOFLOAT
+       case DOUBLE:
+               error("float/double in switch");
+               erroneous2int(expp);
+               break;
+#endif NOFLOAT
+       }
+       stack_stmt(l_break, NO_LABEL);
+       sh->sh_break = l_break;
+       sh->sh_default = 0;
+       sh->sh_table = l_table;
+       sh->sh_nrofentries = 0;
+       sh->sh_type = (*expp)->ex_type; /* the expression switched      */
+       sh->sh_lowerbd = sh->sh_upperbd = (arith)0;     /* immaterial ??? */
+       sh->sh_entries = (struct case_entry *) 0; /* case-entry list    */
+       sh->sh_expr = *expp;
+       sh->next = switch_stack;        /* push onto switch-stack       */
+       switch_stack = sh;
+       C_bra(l_table);                 /* goto start of switch_table   */
+}
+
+code_endswitch()
+{
+       register struct switch_hdr *sh = switch_stack;
+       register label tablabel;
+       register struct case_entry *ce;
+
+       if (sh->sh_default == 0)        /* no default occurred yet */
+               sh->sh_default = sh->sh_break;
+       C_bra(sh->sh_break);            /* skip the switch table now    */
+       C_df_ilb(sh->sh_table);         /* switch table entry           */
+       /* evaluate the switch expr.    */
+       code_expr(sh->sh_expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
+       tablabel = data_label();        /* the rom must have a label    */
+       C_df_dlb(tablabel);
+       C_rom_ilb(sh->sh_default);
+       if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
+               /* CSA */
+               register arith val;
+
+               C_rom_cst(sh->sh_lowerbd);
+               C_rom_cst(sh->sh_upperbd - sh->sh_lowerbd);
+               ce = sh->sh_entries;
+               if (sh->sh_nrofentries)
+                   for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
+                       ASSERT(ce);
+                       if (val == ce->ce_value) {
+                               C_rom_ilb(ce->ce_label);
+                               ce = ce->next;
+                       }
+                       else
+                               C_rom_ilb(sh->sh_default);
+               }
+               C_lae_dlb(tablabel, (arith)0); /* perform the switch    */
+               C_csa(sh->sh_type->tp_size);
+       }
+       else { /* CSB */
+               C_rom_cst((arith)sh->sh_nrofentries);
+               for (ce = sh->sh_entries; ce; ce = ce->next) {
+                       /* generate the entries: value + prog.label     */
+                       C_rom_cst(ce->ce_value);
+                       C_rom_ilb(ce->ce_label);
+               }
+               C_lae_dlb(tablabel, (arith)0); /* perform the switch    */
+               C_csb(sh->sh_type->tp_size);
+       }
+       C_df_ilb(sh->sh_break);
+       switch_stack = sh->next;        /* unstack the switch descriptor */
+       for (ce = sh->sh_entries; ce;) { /* free allocated switch structure */
+               register struct case_entry *tmp = ce->next;
+
+               free_case_entry(ce);
+               ce = tmp;
+       }
+       free_switch_hdr(sh);
+       unstack_stmt();
+}
+
+code_case(expr)
+       struct expr *expr;
+{
+       register arith val;
+       register struct case_entry *ce;
+       register struct switch_hdr *sh = switch_stack;
+       
+       ASSERT(is_cp_cst(expr));
+       if (sh == 0) {
+               error("case statement not in switch");
+               return;
+       }
+       if (expr->ex_flags & EX_ERROR) /* is probably 0 anyway */
+               return;
+       ch7cast(&expr, CASE, sh->sh_type);
+       ce = new_case_entry();
+       C_df_ilb(ce->ce_label = text_label());
+       ce->ce_value = val = expr->VL_VALUE;
+       if (sh->sh_entries == 0) { /* first case entry  */
+               ce->next = (struct case_entry *) 0;
+               sh->sh_entries = ce;
+               sh->sh_lowerbd = sh->sh_upperbd = val;
+               sh->sh_nrofentries = 1;
+       }
+       else { /* second etc. case entry; put ce into proper place */
+               register struct case_entry *c1 = sh->sh_entries, *c2 = 0;
+               
+               if (val < sh->sh_lowerbd)
+                       sh->sh_lowerbd = val;
+               else
+               if (val > sh->sh_upperbd)
+                       sh->sh_upperbd = val;
+               while (c1 && c1->ce_value < ce->ce_value) {
+                       c2 = c1;
+                       c1 = c1->next;
+               }
+               /*      At this point three cases are possible:
+                       1: c1 != 0 && c2 != 0: insert ce somewhere in the middle
+                       2: c1 != 0 && c2 == 0: insert ce right after the head
+                       3: c1 == 0 && c2 != 0: append ce to last element
+                       The case c1 == 0 && c2 == 0 cannot occur, since
+                       the list is guaranteed to be non-empty.
+               */
+               if (c1) {
+                       if (c1->ce_value == ce->ce_value) {
+                               error("multiple case entry for value %ld",
+                                       ce->ce_value);
+                               free_case_entry(ce);
+                               return;
+                       }
+                       if (c2) {
+                               ce->next = c2->next;
+                               c2->next = ce;
+                       }
+                       else {
+                               ce->next = sh->sh_entries;
+                               sh->sh_entries = ce;
+                       }
+               }
+               else {
+                       ASSERT(c2);
+                       ce->next = (struct case_entry *) 0;
+                       c2->next = ce;
+               }
+               (sh->sh_nrofentries)++;
+       }
+}
+
+code_default()
+{
+       register struct switch_hdr *sh = switch_stack;
+
+       if (sh == 0) {
+               error("default statement not in switch");
+               return;
+       }
+       if (sh->sh_default != 0) {
+               error("multiple entry for default in switch");
+               return;
+       }
+
+       C_df_ilb(sh->sh_default = text_label());
+}
diff --git a/lang/cem/cemcom.ansi/switch.str b/lang/cem/cemcom.ansi/switch.str
new file mode 100644 (file)
index 0000000..a8c118f
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/*             S W I T C H - T A B L E - S T R U C T U R E             */
+
+struct switch_hdr      {
+       struct switch_hdr *next;
+       label sh_break;
+       label sh_default;
+       label sh_table;
+       int sh_nrofentries;
+       struct type *sh_type;
+       struct expr *sh_expr;
+       arith sh_lowerbd;
+       arith sh_upperbd;
+       struct case_entry *sh_entries;
+};
+
+/* ALLOCDEF "switch_hdr" 2 */
+
+struct case_entry      {
+       struct case_entry *next;
+       label ce_label;
+       arith ce_value;
+};
+
+/* ALLOCDEF "case_entry" 20 */
diff --git a/lang/cem/cemcom.ansi/tokenname.c b/lang/cem/cemcom.ansi/tokenname.c
new file mode 100644 (file)
index 0000000..b7ea1a1
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* TOKEN NAME DEFINITIONS */
+
+#include       "idf.h"
+#include       "arith.h"
+#include       "LLlex.h"
+#include       "tokenname.h"
+#include       "Lpars.h"
+
+/*     To centralize the declaration of %tokens, their presence in this
+       file is taken as their declaration. The Makefile will produce
+       a grammar file (tokenfile.g) from this file.
+       Moreover, rather than looking up a symbol in all these lists
+       to find its printable name, a fast version of symbol2str() is
+       generated from these tables.
+       Consequenty some of these tables are not referenced explicitly
+       in the C text any more.  To save space and to avoid lint confusion,
+       these have been made pseudo-invisible by #ifdefs.
+*/
+
+#ifdef ____
+struct tokenname tkspec[] =    {       /* the names of the special tokens */
+       {IDENTIFIER, "identifier"},
+       {TYPE_IDENTIFIER, "type_identifier"},
+       {STRING, "string"},
+       {WCHAR, "wchar"},
+       {FILESPECIFIER, "filespecifier"},
+       {INTEGER, "integer"},
+       {FLOATING, "floating"},
+       {0, ""}
+};
+#endif ____
+
+#ifdef ____
+struct tokenname tkcomp[] =    {       /* names of the composite tokens */
+       {NOTEQUAL, "!="},
+       {AND, "&&"},
+       {PLUSPLUS, "++"},
+       {MINMIN, "--"},
+       {ARROW, "->"},
+       {LEFT, "<<"},
+       {LESSEQ, "<="},
+       {EQUAL, "=="},
+       {GREATEREQ, ">="},
+       {RIGHT, ">>"},
+       {OR, "||"},
+       {ELLIPSIS, "..."},
+       {0, ""}
+};
+#endif ____
+
+struct tokenname tkidf[] =     {       /* names of the identifier tokens */
+       {AUTO, "auto"},
+       {BREAK, "break"},
+       {CASE, "case"},
+       {CONST, "const"},
+       {CONTINUE, "continue"},
+       {DEFAULT, "default"},
+       {DO, "do"},
+       {ELSE, "else"},
+       {ENUM, "enum"},
+       {EXTERN, "extern"},
+       {FOR, "for"},
+       {GOTO, "goto"},
+       {IF, "if"},
+       {LONG, "long"},
+       {REGISTER, "register"},
+       {RETURN, "return"},
+       {SHORT, "short"},
+       {SIGNED, "signed"},
+       {SIZEOF, "sizeof"},
+       {STATIC, "static"},
+       {STRUCT, "struct"},
+       {SWITCH, "switch"},
+       {TYPEDEF, "typedef"},
+       {UNION, "union"},
+       {UNSIGNED, "unsigned"},
+       {VOLATILE, "volatile"},
+       {WHILE, "while"},
+       {0, ""}
+};
+
+#ifdef ____
+struct tokenname tkfunny[] =   {       /* internal keywords */
+       {CHAR, "char"},
+       {INT, "int"},
+       {FLOAT, "float"},
+       {DOUBLE, "double"},
+       {LNGDBL, "long double"},
+       {ULONG, "unsigned long"},
+       {VOID, "void"},
+       {GENERIC, "generic"},
+
+       {ARRAY, "array"},
+       {FUNCTION, "function"},
+       {POINTER, "pointer"},
+       {FIELD, "field"},
+       {NEWLINE, "newline"},
+
+       {GLOBAL, "global"},
+       {IMPLICIT, "implicit"},
+       {FORMAL, "formal"},
+       {LABEL, "label"},
+       {ERRONEOUS, "erroneous"},
+
+       {PARCOMMA, "parcomma"},
+       {INITCOMMA, "initcomma"},
+       {CAST, "cast"},
+       {CASTAB, "castab"},
+       {POSTINCR, "postfix ++"},
+       {POSTDECR, "postfix --"},
+       {PLUSAB, "+="},
+       {MINAB, "-="},
+       {TIMESAB, "*="},
+       {DIVAB, "/="},
+       {MODAB, "%="},
+       {LEFTAB, "<<="},
+       {RIGHTAB, ">>="},
+       {ANDAB, "&="},
+       {XORAB, "^="},
+       {ORAB, "|="},
+
+       {INT2INT, "int2int"},
+       {INT2FLOAT, "int2float"},
+       {FLOAT2INT, "float2int"},
+       {FLOAT2FLOAT, "float2float"},
+       {0, ""}
+};
+#endif ____
+
+reserve(resv)
+       register struct tokenname resv[];
+{
+       /*      The names of the tokens described in resv are entered
+               as reserved words.
+       */
+       while (resv->tn_symbol) {
+               struct idf *idf = str2idf(resv->tn_name);
+               
+               if (idf->id_reserved)
+                       fatal("maximum identifier length insufficient");
+               idf->id_reserved = resv->tn_symbol;
+               resv++;
+       }
+}
diff --git a/lang/cem/cemcom.ansi/tokenname.h b/lang/cem/cemcom.ansi/tokenname.h
new file mode 100644 (file)
index 0000000..bd883f1
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* TOKENNAME DEFINITION */
+
+struct tokenname       {       /*      Used for defining the name of a
+                                       token as identified by its symbol
+                               */
+       int tn_symbol;
+       char *tn_name;
+};
diff --git a/lang/cem/cemcom.ansi/type.c b/lang/cem/cemcom.ansi/type.c
new file mode 100644 (file)
index 0000000..7d39783
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $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>
+#include       "Lpars.h"
+#include       "arith.h"
+#include       "type.h"
+#include       "idf.h"
+#include       "def.h"
+#include       "proto.h"
+#include       "sizes.h"
+#include       "align.h"
+#include       "decspecs.h"
+
+extern struct type *function_of(), *array_of();
+#ifndef NOBITFIELD
+extern struct type *field_of();
+#endif NOBITFIELD
+
+/*     To be created dynamically in main() from defaults or from command
+       line parameters.
+*/
+struct type
+       *char_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;
+
+struct type *pa_type;  /* Pointer-Arithmetic type      */
+
+struct type *
+create_type(fund)
+       int fund;
+{
+       /*      A brand new struct type is created, and its tp_fund set
+               to fund.
+       */
+       register struct type *ntp = new_type();
+
+       ntp->tp_fund = fund;
+       ntp->tp_size = (arith)-1;
+
+       return ntp;
+}
+
+struct type *
+construct_type(fund, tp, qual, count, pl)
+       register struct type *tp;
+       register struct proto *pl;
+       arith count; /* for fund == ARRAY only */
+       int qual;
+{
+       /*      fund must be a type constructor: FIELD, FUNCTION, POINTER or
+               ARRAY. The pointer to the constructed type is returned.
+       */
+       register struct type *dtp;
+
+       switch (fund)   {
+#ifndef NOBITFIELD
+       case FIELD:
+               dtp = field_of(tp, qual);
+               break;
+#endif NOBITFIELD
+
+       case FUNCTION:
+               if (tp->tp_fund == FUNCTION)    {
+                       error("function cannot yield function");
+                       return error_type;
+               }
+               if (tp->tp_fund == ARRAY)       {
+                       error("function cannot yield array");
+                       return error_type;
+               }
+
+               dtp = function_of(tp, pl, qual);
+               break;
+       case POINTER:
+               if (tp->tp_fund == VOID) {
+                       /* A void pointer has the same characteristics as a
+                          character pointer. I can't make them equal, because
+                          i would like to have the type information around */
+                       tp = qualifier_type(gen_type, tp->tp_typequal);
+               }
+               dtp = pointer_to(tp, qual);
+               break;
+       case ARRAY:
+               if (count >= 0 && tp->tp_size < 0)      {
+                       error("cannot construct array of unknown type");
+                       count = (arith)-1;
+               }
+               else if (tp->tp_size == 0)      /* CJ */
+                       warning("array elements have size 0");
+               if (count >= (arith)0)
+                       count *= tp->tp_size;
+               dtp = array_of(tp, count, qual);
+               break;
+       default:
+               crash("bad constructor in construct_type");
+               /*NOTREACHED*/
+       }
+       return dtp;
+}
+
+struct type *
+function_of(tp, pl, qual)
+       register struct type *tp;
+       register struct proto *pl;
+       int qual;
+{
+       register struct type *dtp = tp->tp_function;
+
+       /* look for a type with the right qualifier */
+       while (dtp && (dtp->tp_typequal != qual || dtp->tp_proto != pl))
+               dtp = dtp->next;
+
+       if (!dtp)       {
+               dtp = create_type(FUNCTION);
+               dtp->tp_up = tp;
+               dtp->tp_size = pointer_size;
+               dtp->tp_align = pointer_align;
+               dtp->tp_typequal = qual;
+               dtp->tp_proto = pl;
+               dtp->next = tp->tp_function;
+               tp->tp_function = dtp;
+       }
+       return dtp;
+}
+
+struct type *
+pointer_to(tp, qual)
+       register struct type *tp;
+       int qual;
+{
+       register struct type *dtp = tp->tp_pointer;
+
+       /* look for a type with the right qualifier */
+       while (dtp && dtp->tp_typequal != qual)
+               dtp = dtp->next;
+
+       if (!dtp)       {
+               dtp = create_type(POINTER);
+               dtp->tp_unsigned = 1;
+               dtp->tp_up = tp;
+               dtp->tp_size = pointer_size;
+               dtp->tp_align = pointer_align;
+               dtp->tp_typequal = qual;
+               dtp->next = tp->tp_pointer;
+               tp->tp_pointer = dtp;
+       }
+       return dtp;
+}
+
+struct type *
+array_of(tp, count, qual)
+       register struct type *tp;
+       arith count;
+       int qual;
+{
+       register struct type *dtp = tp->tp_array;
+
+       /* look for a type with the right size */
+       while (dtp && (dtp->tp_size != count || dtp->tp_typequal != qual))
+               dtp = dtp->next;
+
+       if (!dtp)       {
+               dtp = create_type(ARRAY);
+               dtp->tp_up = tp;
+               dtp->tp_size = count;
+               dtp->tp_align = tp->tp_align;
+               dtp->tp_typequal = qual;
+               dtp->next = tp->tp_array;
+               tp->tp_array = dtp;
+       }
+       return dtp;
+}
+
+#ifndef NOBITFIELD
+struct type *
+field_of(tp, qual)
+       register struct type *tp;
+       int qual;
+{
+       register struct type *dtp = create_type(FIELD);
+
+       dtp->tp_up = tp;
+       dtp->tp_align = tp->tp_align;
+       dtp->tp_size = tp->tp_size;
+       dtp->tp_typequal = qual;
+       return dtp;
+}
+#endif NOBITFIELD
+
+arith
+size_of_type(tp, nm)
+       struct type *tp;
+       char nm[];
+{
+       arith sz = tp->tp_size;
+
+       if (sz < 0)     {
+               error("size of %s unknown", nm);
+               return (arith)1;
+       }
+       return sz;
+}
+
+idf2type(idf, tpp)
+       struct idf *idf;
+       struct type **tpp;
+{
+       /*      Decoding  a typedef-ed identifier: if the size is yet
+               unknown we have to make copy of the type descriptor to
+               prevent garbage at the initialisation of arrays with
+               unknown size.
+       */
+       register struct type *tp = idf->id_def->df_type;
+
+       if (    tp->tp_size < (arith)0 && tp->tp_fund == ARRAY) {
+               *tpp = new_type();
+               **tpp = *tp;
+                       /* this is really a structure assignment, AAGH!!! */
+       }
+       else    {
+               *tpp = tp;
+       }
+}
+
+arith
+align(pos, al)
+       arith pos;
+       int al;
+{
+       return ((pos + al - 1) / al) * al;
+}
+
+struct type *
+standard_type(fund, sgn, algn, sz)
+       int algn; arith sz;
+{
+       register struct type *tp = create_type(fund);
+
+       tp->tp_unsigned = sgn;
+       tp->tp_align = algn;
+       tp->tp_size = sz;
+
+       return tp;
+}
diff --git a/lang/cem/cemcom.ansi/type.str b/lang/cem/cemcom.ansi/type.str
new file mode 100644 (file)
index 0000000..b437901
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+/* $Header$ */
+/* TYPE DESCRIPTOR */
+
+#include       "nofloat.h"
+#include       "nobitfield.h"
+
+struct type    {
+       struct type *next;      /* used only with ARRAY */
+       short tp_fund;          /* fundamental type */
+       char tp_unsigned;
+       int tp_align;
+       int tp_typequal;        /* type qualifier */
+       arith tp_size;          /* -1 if declared but not defined */
+       struct idf *tp_idf;     /* name of STRUCT, UNION or ENUM */
+       struct sdef *tp_sdef;   /* to first selector */
+       struct type *tp_up;     /* from FIELD, POINTER, ARRAY
+                                       or FUNCTION to fund. */
+       struct field *tp_field; /* field descriptor if fund == FIELD    */
+       struct type *tp_pointer;/* to POINTER */
+       struct type *tp_array;  /* to ARRAY */
+       struct proto *tp_proto; /* prototype list */
+       struct type *tp_function;/* to FUNCTION */
+};
+
+
+/*     Type qualifiers. Note: TQ_VOLATILE and TQ_CONST can be
+       'ored' to specify: extern const volatile int a;
+*/
+#define        TQ_VOLATILE     01
+#define        TQ_CONST        02
+
+extern struct type
+       *create_type(), *standard_type(), *construct_type(), *pointer_to(),
+       *array_of(), *function_of();
+
+#ifndef NOBITFIELD
+extern struct type *field_of();
+#endif NOBITFIELD
+
+extern struct type
+       *char_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;
+
+extern struct type *pa_type;   /* type.c       */
+
+extern arith size_of_type(), align();
+
+/* ALLOCDEF "type" 20 */
diff --git a/lang/cem/cemcom.ansi/util.c b/lang/cem/cemcom.ansi/util.c
new file mode 100644 (file)
index 0000000..b51cf68
--- /dev/null
@@ -0,0 +1,237 @@
+/*
+ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
+ * See the copyright notice in the ACK home directory, in the file "Copyright".
+ */
+
+/* M I S C E L L A N E O U S   U T I L I T I E S */
+
+/* $Header$ */
+
+/*     Code for the allocation and de-allocation of temporary variables,
+       allowing re-use.
+*/
+
+#include       <em.h>
+#include       <em_reg.h>
+#include       <alloc.h>
+#include       <em_mes.h>
+
+#include       "lint.h"
+#include       "util.h"
+#include       "use_tmp.h"
+#include       "regcount.h"
+#include       "sizes.h"
+#include       "align.h"
+#include       "stack.h"
+#include       "Lpars.h"
+#include       "def.h"
+
+static struct localvar *FreeTmps;
+#ifdef USE_TMP
+static int     loc_id;
+#endif USE_TMP
+
+#ifdef PEEPHOLE
+#undef REGCOUNT
+#define REGCOUNT 1
+#endif
+
+extern char options[];
+
+LocalInit()
+{
+#ifdef USE_TMP
+       C_insertpart(loc_id = C_getid());
+#endif USE_TMP
+}
+
+arith
+LocalSpace(sz, al)
+       arith sz;
+{
+       register struct stack_level *stl = local_level;
+
+       stl->sl_max_block = - align(sz - stl->sl_max_block, al);
+       return stl->sl_max_block;
+}
+
+#define TABSIZ 32
+static struct localvar *regs[TABSIZ];
+
+arith
+NewLocal(sz, al, regtype, sc)
+       arith sz;
+{
+       register struct localvar *tmp = FreeTmps;
+       struct localvar *prev = 0;
+       register int index;
+
+       while (tmp) {
+               if (tmp->t_align >= al &&
+                   tmp->t_size >= sz &&
+                   tmp->t_sc == sc &&
+                   tmp->t_regtype == regtype) {
+                       if (prev) {
+                               prev->next = tmp->next;
+                       }
+                       else    FreeTmps = tmp->next;
+                       break;
+               }
+               prev = tmp;
+               tmp = tmp->next;
+       }
+       if (! tmp) {
+               tmp = new_localvar();
+               tmp->t_offset = LocalSpace(sz, al);
+               tmp->t_align = al;
+               tmp->t_size = sz;
+               tmp->t_sc = sc;
+               tmp->t_regtype = regtype;
+               tmp->t_count = REG_DEFAULT;
+       }
+       index = (int) (tmp->t_offset >> 2) & (TABSIZ - 1);
+       tmp->next = regs[index];
+       regs[index] = tmp;
+       return tmp->t_offset;
+}
+
+FreeLocal(off)
+       arith off;
+{
+       int index = (int) (off >> 2) & (TABSIZ - 1);
+       register struct localvar *tmp = regs[index];
+       struct localvar *prev = 0;
+
+       while (tmp && tmp->t_offset != off) {
+               prev = tmp;
+               tmp = tmp->next;
+       }
+       if (tmp) {
+               if (prev)       prev->next = tmp->next;
+               else            regs[index] = tmp->next;
+               tmp->next = FreeTmps;
+               FreeTmps = tmp;
+       }
+}
+
+LocalFinish()
+{
+       register struct localvar *tmp, *tmp1;
+       register int i;
+
+#ifdef USE_TMP
+       C_beginpart(loc_id);
+#endif
+       tmp = FreeTmps;
+       while (tmp) {
+               tmp1 = tmp;
+               if (tmp->t_sc == REGISTER) tmp->t_count += REG_BONUS;
+               if (! options['n'] && tmp->t_regtype >= 0) {
+                       C_ms_reg(tmp->t_offset, tmp->t_size, tmp->t_regtype, tmp->t_count);
+               }
+               tmp = tmp->next;
+               free_localvar(tmp1);
+       }
+       FreeTmps = 0;
+       for (i = 0; i < TABSIZ; i++) {
+               tmp = regs[i];
+               while (tmp) {
+                       if (tmp->t_sc == REGISTER) tmp->t_count += REG_BONUS;
+                       tmp1 = tmp;
+                       if (! options['n'] && tmp->t_regtype >= 0) {
+                               C_ms_reg(tmp->t_offset,
+                                        tmp->t_size,
+                                        tmp->t_regtype,
+                                        tmp->t_count);
+                       }
+                       tmp = tmp->next;
+                       free_localvar(tmp1);
+               }
+               regs[i] = 0;
+       }
+       if (! options['n']) {
+               C_mes_begin(ms_reg);
+               C_mes_end();
+       }
+#ifdef USE_TMP
+       C_endpart(loc_id);
+#endif
+}
+
+RegisterAccount(offset, size, regtype, sc)
+       arith offset, size;
+{
+       register struct localvar *p;
+       int index;
+
+       if (regtype < 0) return;
+
+       p = new_localvar();
+       index = (int) (offset >> 2) & (TABSIZ - 1);
+       p->t_offset = offset;
+       p->t_regtype = regtype;
+       p->t_count = REG_DEFAULT;
+       p->t_sc = sc;
+       p->t_size = size;
+       p->next = regs[index];
+       regs[index] = p;
+}
+
+static struct localvar *
+find_reg(off)
+       arith off;
+{
+       register struct localvar *p = regs[(int)(off >> 2) & (TABSIZ - 1)];
+
+       while (p && p->t_offset != off) p = p->next;
+       return p;
+}
+
+LoadLocal(off, sz)
+       arith off, sz;
+{
+       register struct localvar *p = find_reg(off);
+
+#ifdef USE_TMP
+#ifdef REGCOUNT
+       if (p) p->t_count++;
+#endif
+#endif
+       if (sz == word_size) C_lol(off);
+       else if (sz == dword_size) C_ldl(off);
+       else {
+               if (p) p->t_regtype = -1;
+               C_lal(off);
+               C_loi(sz);
+       }
+}
+
+StoreLocal(off, sz)
+       arith off, sz;
+{
+       register struct localvar *p = find_reg(off);
+
+#ifdef USE_TMP
+#ifdef REGCOUNT
+       if (p) p->t_count++;
+#endif
+#endif
+       if (sz == word_size) C_stl(off);
+       else if (sz == dword_size) C_sdl(off);
+       else {
+               if (p) p->t_regtype = -1;
+               C_lal(off);
+               C_sti(sz);
+       }
+}
+
+#ifndef        LINT
+AddrLocal(off)
+       arith off;
+{
+       register struct localvar *p = find_reg(off);
+
+       if (p) p->t_regtype = -1;
+       C_lal(off);
+}
+#endif LINT
diff --git a/lang/cem/cemcom.ansi/util.str b/lang/cem/cemcom.ansi/util.str
new file mode 100644 (file)
index 0000000..8864323
--- /dev/null
@@ -0,0 +1,11 @@
+struct localvar {
+       struct localvar *next;
+       arith           t_offset;       /* offset from LocalBase */
+       arith           t_size;
+       int             t_align;
+       int             t_regtype;
+       int             t_count;
+       int             t_sc;           /* storage class */
+};
+
+/* ALLOCDEF "localvar" 10 */