From 750a6bc6848a5c0c7b4b491c50e80fbdfa8680fe Mon Sep 17 00:00:00 2001 From: carl Date: Tue, 19 Feb 2019 00:42:15 +0800 Subject: [PATCH] Better ANSI C compatibility and portability: + Addition of function prototypes and include files. + Change function definitions to ANSI C style. + Initial support for CMake + Scripts to generate compiler header is now sed based. --- lang/cem/cemcom.ansi/BigPars | 276 ++--- lang/cem/cemcom.ansi/CMakeLists.txt | 318 ++++++ lang/cem/cemcom.ansi/LLlex.c | 34 +- lang/cem/cemcom.ansi/LLlex.h | 8 + lang/cem/cemcom.ansi/LLmessage.c | 21 +- lang/cem/cemcom.ansi/arith.c | 81 +- lang/cem/cemcom.ansi/arith.h | 31 +- lang/cem/cemcom.ansi/blocks.c | 24 +- lang/cem/cemcom.ansi/blocks.h | 20 + lang/cem/cemcom.ansi/ch3.c | 49 +- lang/cem/cemcom.ansi/ch3.h | 29 + lang/cem/cemcom.ansi/ch3bin.c | 28 +- lang/cem/cemcom.ansi/ch3bin.h | 21 + lang/cem/cemcom.ansi/ch3mon.c | 7 +- lang/cem/cemcom.ansi/ch3mon.h | 22 + lang/cem/cemcom.ansi/code.c | 92 +- lang/cem/cemcom.ansi/code.str | 47 + lang/cem/cemcom.ansi/conversion.c | 13 +- lang/cem/cemcom.ansi/conversion.h | 15 + lang/cem/cemcom.ansi/cstoper.c | 10 +- lang/cem/cemcom.ansi/cstoper.h | 17 + lang/cem/cemcom.ansi/dataflow.c | 10 +- lang/cem/cemcom.ansi/dataflow.h | 19 + lang/cem/cemcom.ansi/declar.g | 1532 +++++++++++++------------- lang/cem/cemcom.ansi/declar.str | 5 + lang/cem/cemcom.ansi/declarator.c | 25 +- lang/cem/cemcom.ansi/declarator.h | 28 + lang/cem/cemcom.ansi/decspecs.c | 154 +-- lang/cem/cemcom.ansi/decspecs.h | 10 + lang/cem/cemcom.ansi/def.str | 5 + lang/cem/cemcom.ansi/domacro.c | 13 +- lang/cem/cemcom.ansi/domacro.h | 16 + lang/cem/cemcom.ansi/error.c | 84 +- lang/cem/cemcom.ansi/error.h | 94 ++ lang/cem/cemcom.ansi/estack.str | 5 + lang/cem/cemcom.ansi/eval.c | 58 +- lang/cem/cemcom.ansi/eval.h | 37 + lang/cem/cemcom.ansi/expr.c | 301 +++--- lang/cem/cemcom.ansi/expr.str | 28 + lang/cem/cemcom.ansi/expression.g | 703 ++++++------ lang/cem/cemcom.ansi/field.c | 23 +- lang/cem/cemcom.ansi/field.str | 22 + lang/cem/cemcom.ansi/fltcstoper.c | 5 +- lang/cem/cemcom.ansi/fltcstoper.h | 15 + lang/cem/cemcom.ansi/idf.c | 545 +++++----- lang/cem/cemcom.ansi/idf.str | 31 +- lang/cem/cemcom.ansi/input.c | 5 +- lang/cem/cemcom.ansi/input.h | 2 +- lang/cem/cemcom.ansi/ival.g | 1533 +++++++++++++-------------- lang/cem/cemcom.ansi/label.c | 8 +- lang/cem/cemcom.ansi/label.h | 9 + lang/cem/cemcom.ansi/main.c | 35 +- lang/cem/cemcom.ansi/next.str | 1 + lang/cem/cemcom.ansi/options.c | 13 +- lang/cem/cemcom.ansi/options.h | 13 + lang/cem/cemcom.ansi/pragma.c | 28 +- lang/cem/cemcom.ansi/pragma.h | 13 + lang/cem/cemcom.ansi/program.g | 451 ++++---- lang/cem/cemcom.ansi/proto.c | 397 ++++--- lang/cem/cemcom.ansi/proto.str | 20 + lang/cem/cemcom.ansi/skip.c | 3 +- lang/cem/cemcom.ansi/skip.h | 13 + lang/cem/cemcom.ansi/stab.c | 234 ++-- lang/cem/cemcom.ansi/stab.h | 20 + lang/cem/cemcom.ansi/stack.c | 24 +- lang/cem/cemcom.ansi/stack.str | 28 +- lang/cem/cemcom.ansi/statement.g | 1011 +++++++++--------- lang/cem/cemcom.ansi/stb.c | 6 +- lang/cem/cemcom.ansi/stmt.str | 5 + lang/cem/cemcom.ansi/struct.c | 82 +- lang/cem/cemcom.ansi/struct.str | 34 +- lang/cem/cemcom.ansi/switch.c | 19 +- lang/cem/cemcom.ansi/switch.str | 18 + lang/cem/cemcom.ansi/tokcase.sed | 3 + lang/cem/cemcom.ansi/tokcasee.in | 16 + lang/cem/cemcom.ansi/tokcaseh.in | 12 + lang/cem/cemcom.ansi/tokenname.c | 4 +- lang/cem/cemcom.ansi/tokenname.h | 6 + lang/cem/cemcom.ansi/type.c | 203 ++-- lang/cem/cemcom.ansi/type.str | 32 +- lang/cem/cemcom.ansi/util.c | 32 +- lang/cem/cemcom.ansi/util.str | 20 + 82 files changed, 5193 insertions(+), 4091 deletions(-) create mode 100644 lang/cem/cemcom.ansi/CMakeLists.txt create mode 100644 lang/cem/cemcom.ansi/blocks.h create mode 100644 lang/cem/cemcom.ansi/ch3.h create mode 100644 lang/cem/cemcom.ansi/ch3bin.h create mode 100644 lang/cem/cemcom.ansi/ch3mon.h create mode 100644 lang/cem/cemcom.ansi/conversion.h create mode 100644 lang/cem/cemcom.ansi/cstoper.h create mode 100644 lang/cem/cemcom.ansi/dataflow.h create mode 100644 lang/cem/cemcom.ansi/declarator.h create mode 100644 lang/cem/cemcom.ansi/domacro.h create mode 100644 lang/cem/cemcom.ansi/error.h create mode 100644 lang/cem/cemcom.ansi/eval.h create mode 100644 lang/cem/cemcom.ansi/fltcstoper.h create mode 100644 lang/cem/cemcom.ansi/next.str create mode 100644 lang/cem/cemcom.ansi/options.h create mode 100644 lang/cem/cemcom.ansi/pragma.h create mode 100644 lang/cem/cemcom.ansi/skip.h create mode 100644 lang/cem/cemcom.ansi/stab.h create mode 100644 lang/cem/cemcom.ansi/tokcase.sed create mode 100644 lang/cem/cemcom.ansi/tokcasee.in create mode 100644 lang/cem/cemcom.ansi/tokcaseh.in diff --git a/lang/cem/cemcom.ansi/BigPars b/lang/cem/cemcom.ansi/BigPars index 6f4b0971d..bf92e22fe 100644 --- a/lang/cem/cemcom.ansi/BigPars +++ b/lang/cem/cemcom.ansi/BigPars @@ -1,138 +1,138 @@ -!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 ERR_SHADOW 5 /* a syntax error overshadows error messages - until ERR_SHADOW symbols have been - accepted without syntax error */ - - -!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 */ -#define STDC_NPARAMS 31 /* ANSI limit on number of parameters */ - - -!File: ifdepth.h -#define IFDEPTH 256 /* maximum number of nested if-constructions */ - - -!File: density.h -#define DENSITY 3 /* see switch.[ch] for an explanation */ - - -!File: macbuf.h -#define LAPBUF 128 /* initial size of macro replacement buffer */ -#define ARGBUF 128 /* initial size of macro parameter buffer(s) */ - - -!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: trgt_sizes.h -#define MAXSIZE 8 /* the maximum of the SZ_* constants */ - -/* target machine sizes */ -#define SZ_CHAR 1 -#define SZ_SHORT 2 -#define SZ_WORD 4 -#define SZ_INT 4 -#define SZ_LONG 4 -#define SZ_FLOAT 4 -#define SZ_DOUBLE 8 -#define SZ_LNGDBL 8 /* for now */ -#define SZ_POINTER 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 -#define AL_FLOAT SZ_WORD -#define AL_DOUBLE SZ_WORD -#define AL_LNGDBL SZ_WORD -#define AL_POINTER SZ_WORD -#define AL_STRUCT 1 -#define AL_UNION 1 - - -!File: botch_free.h -/*#define 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 -/*#define DEBUG 1 /* perform various self-tests */ -#define NDEBUG 1 /* disable assertions */ - - -!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 */ - - -!File: inputtype.h -#define INP_READ_IN_ONE 1 /* read input file in one */ - - -!File: nobitfield.h -/*#define 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: nocross.h -/*#define NOCROSS 1 /* if NOT defined, cross compiler */ - - -!File: regcount.h -/*#define REGCOUNT 1 /* count occurrences for register messages */ - - -!File: dbsymtab.h -#define DBSYMTAB 1 /* ability to produce symbol table for debugger */ - - +!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 ERR_SHADOW 5 /* a syntax error overshadows error messages + until ERR_SHADOW symbols have been + accepted without syntax error */ + + +!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 */ +#define STDC_NPARAMS 31 /* ANSI limit on number of parameters */ + + +!File: ifdepth.h +#define IFDEPTH 256 /* maximum number of nested if-constructions */ + + +!File: density.h +#define DENSITY 3 /* see switch.[ch] for an explanation */ + + +!File: macbuf.h +#define LAPBUF 128 /* initial size of macro replacement buffer */ +#define ARGBUF 128 /* initial size of macro parameter buffer(s) */ + + +!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: trgt_sizes.h +#define MAXSIZE 8 /* the maximum of the SZ_* constants */ + +/* target machine sizes */ +#define SZ_CHAR 1 +#define SZ_SHORT 2 +#define SZ_WORD 4 +#define SZ_INT 4 +#define SZ_LONG 4 +#define SZ_FLOAT 4 +#define SZ_DOUBLE 8 +#define SZ_LNGDBL 8 /* for now */ +#define SZ_POINTER 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 +#define AL_FLOAT SZ_WORD +#define AL_DOUBLE SZ_WORD +#define AL_LNGDBL SZ_WORD +#define AL_POINTER SZ_WORD +#define AL_STRUCT 1 +#define AL_UNION 1 + + +!File: botch_free.h +/*#define 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 +/*#define DEBUG 1 *//* perform various self-tests */ +#define NDEBUG 1 /* disable assertions */ + + +!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 */ + + +!File: inputtype.h +#define INP_READ_IN_ONE 1 /* read input file in one */ + + +!File: nobitfield.h +/*#define 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: nocross.h +/*#define NOCROSS 1 *//* if NOT defined, cross compiler */ + + +!File: regcount.h +/*#define REGCOUNT 1 *//* count occurrences for register messages */ + + +!File: dbsymtab.h +#define DBSYMTAB 1 /* ability to produce symbol table for debugger */ + + diff --git a/lang/cem/cemcom.ansi/CMakeLists.txt b/lang/cem/cemcom.ansi/CMakeLists.txt new file mode 100644 index 000000000..3777b042e --- /dev/null +++ b/lang/cem/cemcom.ansi/CMakeLists.txt @@ -0,0 +1,318 @@ +cmake_minimum_required (VERSION 3.0) +project(em_cemcom.ansi) + + +################################## +# Location of built scripts. +################################## +set(PROJECT_SCRIPTS_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../util/scripts) + +set(SRC_C + align.h + arith.c + arith.h + atw.h + blocks.c + blocks.h + ch3.c + ch3.h + ch3bin.c + ch3bin.h + ch3mon.c + ch3mon.h + class.h + code.c + conversion.c + conversion.h + cstoper.c + cstoper.h + dataflow.c + dataflow.h + declarator.c + declarator.h + decspecs.c + decspecs.h + domacro.c + domacro.h + dumpidf.c + error.c + error.h + eval.c + eval.h + expr.c + field.c + file_info.h + fltcstoper.c + fltcstoper.h + idf.c + input.c + input.h + interface.h + idf.c + input.c + input.h + l_class.h + l_comment.c + l_comment.h + l_em.h + l_ev_ord.c + l_lint.c + l_lint.h + l_misc.c + l_outdef.c + l_states.c + label.c + label.h + level.h + LLlex.c + LLlex.h + LLmessage.c + main.c + mes.h + options.c + options.h + pragma.c + pragma.h + proto.c + sizes.h + skip.c + skip.h + specials.h + stab.c + stab.h + stack.c + stb.c + struct.c + switch.c + tokenname.c + tokenname.h + type.c + util.c +) + +set(INCLUDE_DIRS + . + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/../include + ${CMAKE_CURRENT_SOURCE_DIR}/../../../modules/src/idf + ${CMAKE_CURRENT_SOURCE_DIR}/../../../modules/src/input +) + +############################################ +# LLgen inputs +############################################ + +set(GEN_G + ${CMAKE_CURRENT_BINARY_DIR}/tokenfile.g +) + + + +set(SRC_G + ${CMAKE_CURRENT_SOURCE_DIR}/program.g + ${CMAKE_CURRENT_SOURCE_DIR}/declar.g + ${CMAKE_CURRENT_SOURCE_DIR}/expression.g + ${CMAKE_CURRENT_SOURCE_DIR}/statement.g + ${CMAKE_CURRENT_SOURCE_DIR}/ival.g +) + + +############################################ +# LLgen outputs +############################################ + +set(GEN_SRC + ${CMAKE_CURRENT_BINARY_DIR}/program.c + ${CMAKE_CURRENT_BINARY_DIR}/declar.c + ${CMAKE_CURRENT_BINARY_DIR}/expression.c + ${CMAKE_CURRENT_BINARY_DIR}/statement.c + ${CMAKE_CURRENT_BINARY_DIR}/ival.c + ${CMAKE_CURRENT_BINARY_DIR}/tokenfile.c + ${CMAKE_CURRENT_BINARY_DIR}/Lpars.c + ${CMAKE_CURRENT_BINARY_DIR}/Lpars.h + ${CMAKE_CURRENT_BINARY_DIR}/Lncor.c +) + + + + + + +set(GFILES + ${GEN_G} + ${SRC_G} +) + + + +############################################ +# Configuration parameters generated files +############################################ + +set(GEN_H_CONFIG + ${CMAKE_CURRENT_BINARY_DIR}/parameters.h +) + +set(GEN_OTHERS + ${CMAKE_CURRENT_BINARY_DIR}/code.h + ${CMAKE_CURRENT_BINARY_DIR}/declar.h + ${CMAKE_CURRENT_BINARY_DIR}/def.h + ${CMAKE_CURRENT_BINARY_DIR}/expr.h + ${CMAKE_CURRENT_BINARY_DIR}/field.h + ${CMAKE_CURRENT_BINARY_DIR}/estack.h + ${CMAKE_CURRENT_BINARY_DIR}/util.h + ${CMAKE_CURRENT_BINARY_DIR}/proto.h + ${CMAKE_CURRENT_BINARY_DIR}/replace.h + ${CMAKE_CURRENT_BINARY_DIR}/idf.h + ${CMAKE_CURRENT_BINARY_DIR}/macro.h + ${CMAKE_CURRENT_BINARY_DIR}/stack.h + ${CMAKE_CURRENT_BINARY_DIR}/stmt.h + ${CMAKE_CURRENT_BINARY_DIR}/struct.h + ${CMAKE_CURRENT_BINARY_DIR}/switch.h + ${CMAKE_CURRENT_BINARY_DIR}/type.h + ${CMAKE_CURRENT_BINARY_DIR}/l_brace.h + ${CMAKE_CURRENT_BINARY_DIR}/l_state.h + ${CMAKE_CURRENT_BINARY_DIR}/l_outdef.h + ${CMAKE_CURRENT_BINARY_DIR}/next.c +) + + + + + + +set(CFILES + ${SRC_C} + ${GEN_SRC} + ${GEN_H_CONFIG} + ${GEN_OTHERS} + symbol2str.c + char.c +) + +set(LLGENOPTIONS + -n +) + +############################################### +# Generate the compile time configuration file +############################################### +add_custom_command( + OUTPUT ${GEN_H_CONFIG} BigPars mkparams.sed + COMMAND ${CMAKE_COMMAND} -E copy + ${PROJECT_SCRIPTS_SOURCE_DIR}/mkparams.sed + ${CMAKE_CURRENT_BINARY_DIR}/mkparams.sed + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/BigPars + ${CMAKE_CURRENT_BINARY_DIR}/BigPars + COMMAND sed -f ${PROJECT_SCRIPTS_SOURCE_DIR}/mkparams.sed ${CMAKE_CURRENT_BINARY_DIR}/BigPars>parameters.h + DEPENDS BigPars) + +############################################### +# Generate other source files +############################################### + + +add_custom_command( + OUTPUT ${GEN_OTHERS} mkalloc1.sed mkalloc2.sed mknext.sed + COMMAND ${CMAKE_COMMAND} -E copy + ${PROJECT_SCRIPTS_SOURCE_DIR}/mkalloc1.sed + ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed + COMMAND ${CMAKE_COMMAND} -E copy + ${PROJECT_SCRIPTS_SOURCE_DIR}/mkalloc2.sed + ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed + COMMAND ${CMAKE_COMMAND} -E copy + ${PROJECT_SCRIPTS_SOURCE_DIR}/mknext.sed + ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed + + + + + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/code.str>code.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/declar.str>declar.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/def.str>def.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/expr.str>expr.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/field.str>field.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/estack.str>estack.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/util.str>util.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/proto.str>proto.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/idf.str>idf.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/macro.str>macro.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/stack.str>stack.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/stmt.str>stmt.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/struct.str>struct.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/switch.str>switch.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/type.str>type.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/l_brace.str>l_brace.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/l_state.str>l_state.h + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc1.sed -f ${CMAKE_CURRENT_BINARY_DIR}/mkalloc2.sed ${CMAKE_CURRENT_SOURCE_DIR}/l_outdef.str>l_outdef.h + # Create next file from above files + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_CURRENT_SOURCE_DIR}/next.str + ${CMAKE_CURRENT_BINARY_DIR}/next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/code.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/declar.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/def.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/expr.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/field.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/estack.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/util.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/proto.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/idf.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/macro.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/stack.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/stmt.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/struct.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/switch.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/type.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/l_brace.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/l_state.str>>next.c + COMMAND sed -n -f ${CMAKE_CURRENT_BINARY_DIR}/mknext.sed ${CMAKE_CURRENT_SOURCE_DIR}/l_outdef.str>>next.c +) + + + + + +add_custom_command( + OUTPUT char.c + COMMAND ${CMAKE_CURRENT_BINARY_DIR}/../../../util/cmisc/tabgen -f${CMAKE_CURRENT_SOURCE_DIR}/char.tab >char.c +) + +############################################### +# Generate the LLGen source files +# NOTE: Order of input file is important +############################################### + +add_custom_command( + OUTPUT tokenfile.g mktkfile.sed + COMMAND ${CMAKE_COMMAND} -E copy + ${PROJECT_SCRIPTS_SOURCE_DIR}/mktkfile.sed + ${CMAKE_CURRENT_BINARY_DIR}/mktkfile.sed + COMMAND sed -f ${CMAKE_CURRENT_BINARY_DIR}/mktkfile.sed ${CMAKE_CURRENT_SOURCE_DIR}/tokenname.c>tokenfile.g +) + +add_custom_command( + OUTPUT ${GEN_SRC} + COMMAND ${CMAKE_COMMAND} -E env LLGEN_LIB_DIR=${CMAKE_CURRENT_SOURCE_DIR}/../../../util/LLgen/lib ${CMAKE_CURRENT_BINARY_DIR}/../../../util/LLgen/LLgen ${LLGENOPTIONS} ${GEN_G} ${SRC_G} + DEPENDS LLgen tokenfile.g) + + +add_custom_command( + OUTPUT symbol2str.c + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/tokcaseh.in >symbol2str.c + COMMAND sed -f ${CMAKE_CURRENT_SOURCE_DIR}/tokcase.sed ${CMAKE_CURRENT_SOURCE_DIR}/tokenname.c >>symbol2str.c + COMMAND cat ${CMAKE_CURRENT_SOURCE_DIR}/tokcasee.in >>symbol2str.c +) + + +add_executable(${PROJECT_NAME} ${CFILES}) +target_compile_definitions(${PROJECT_NAME} PUBLIC NORCSID=1) +target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDE_DIRS}) + +target_link_libraries(${PROJECT_NAME} emheaders emh flt alloc print string system em_data eme em_mes) + +install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) +install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cemcom.ansi.1 DESTINATION man OPTIONAL) + + diff --git a/lang/cem/cemcom.ansi/LLlex.c b/lang/cem/cemcom.ansi/LLlex.c index f0f5d5c24..d4be03449 100644 --- a/lang/cem/cemcom.ansi/LLlex.c +++ b/lang/cem/cemcom.ansi/LLlex.c @@ -17,6 +17,8 @@ #include "Lpars.h" #include "class.h" #include "sizes.h" +#include "error.h" +#include "domacro.h" #include "specials.h" /* registration of special identifiers */ /* Data about the token yielded */ @@ -41,7 +43,16 @@ extern arith full_mask[]; extern int lint_skip_comment; #endif -int LLlex() + +/* Internal function declarations */ +static arith char_constant(char*); +static char* string_token(char *, int , int *); +static int quoted(register int); +static int hex_val(register int); +static void strflt2tok(char [], struct token *); +static void strint2tok(char [], struct token *); + +int LLlex(void) { /* LLlex() plays the role of Lexical Analyzer for the C parser. The look-ahead and putting aside of tokens are taken into @@ -72,10 +83,8 @@ int LLlex() return DOT; } -char* string_token(); -arith char_constant(); -int GetToken(ptok) register struct token* ptok; +int GetToken(register struct token* ptok) { /* GetToken() is the actual token recognizer. It calls the control line interpreter if it encounters a "\n{w}*#" @@ -379,7 +388,7 @@ go_on: /* rescan, the following character has been read */ /*NOTREACHED*/ } -arith char_constant(nm) char* nm; +static arith char_constant(char* nm) { register arith val = 0; register int ch; @@ -413,8 +422,7 @@ arith char_constant(nm) char* nm; return val; } -char* string_token(nm, stop_char, plen) char* nm; -int* plen; +static char* string_token(char *nm, int stop_char, int *plen) { register int ch; register int str_size; @@ -447,7 +455,7 @@ int* plen; return str; } -int quoted(ch) register int ch; +static int quoted(register int ch) { /* quoted() replaces an escaped character sequence by the character meant. @@ -510,12 +518,12 @@ int quoted(ch) register int ch; return ch & 0377; } -int hex_val(ch) register int ch; +static int hex_val(register int ch) { return is_dig(ch) ? ch - '0' : is_hex(ch) ? (ch - 'a' + 10) & 017 : -1; } -int GetChar() +int GetChar(void) { /* The routines GetChar and trigraph parses the trigraph sequences and removes occurences of \\\n. @@ -529,8 +537,7 @@ int GetChar() /* strflt2tok only checks the syntax of the floating-point number and * selects the right type for the number. */ -strflt2tok(fltbuf, ptok) char fltbuf[]; -struct token* ptok; +static void strflt2tok(char fltbuf[], struct token* ptok) { register char* cp = fltbuf; int malformed = 0; @@ -584,8 +591,7 @@ struct token* ptok; } } -strint2tok(intbuf, ptok) char intbuf[]; -struct token* ptok; +static void strint2tok(char intbuf[], struct token* ptok) { register char* cp = intbuf; int base = 10; diff --git a/lang/cem/cemcom.ansi/LLlex.h b/lang/cem/cemcom.ansi/LLlex.h index 678149d9f..a52f5ed78 100644 --- a/lang/cem/cemcom.ansi/LLlex.h +++ b/lang/cem/cemcom.ansi/LLlex.h @@ -9,6 +9,8 @@ called a "symbol", but it may have other information associated to it. */ +#ifndef LLLEX_H_ +#define LLLEX_H_ #include "file_info.h" @@ -56,3 +58,9 @@ extern int err_occurred; /* "error.c" */ #define ASIDE aside.tk_symb #define EOF (-1) + +int GetChar(void); +int LLlex(void); +int GetToken(register struct token* ptok); + +#endif /* LLLEX_H_ */ diff --git a/lang/cem/cemcom.ansi/LLmessage.c b/lang/cem/cemcom.ansi/LLmessage.c index c88c5eb24..299d4a82d 100644 --- a/lang/cem/cemcom.ansi/LLmessage.c +++ b/lang/cem/cemcom.ansi/LLmessage.c @@ -10,21 +10,28 @@ #include "arith.h" #include "LLlex.h" #include "Lpars.h" +#include "error.h" extern char *symbol2str(); -LLmessage(tk) { +static void insert_token(int ); + +void LLmessage(int tk) +{ err_occurred = 1; - if (tk < 0) { + if (tk < 0) + { error("end of file expected"); } - else if (tk) { + else if (tk) + { #ifndef LLNONCORR error("%s missing before %s", symbol2str(tk), symbol2str(DOT)); #endif insert_token(tk); } - else { + else + { #ifndef LLNONCORR error("%s deleted", symbol2str(DOT)); #else @@ -34,14 +41,14 @@ LLmessage(tk) { tk_nmb_at_last_syn_err = token_nmb; } -insert_token(tk) - int tk; +static void insert_token(int tk) { aside = dot; DOT = tk; - switch (tk) { + switch (tk) + { /* The operands need some body */ case IDENTIFIER: dot.tk_idf = gen_idf(); diff --git a/lang/cem/cemcom.ansi/arith.c b/lang/cem/cemcom.ansi/arith.c index b402e4b35..10d149911 100644 --- a/lang/cem/cemcom.ansi/arith.c +++ b/lang/cem/cemcom.ansi/arith.c @@ -24,16 +24,19 @@ #include "Lpars.h" #include "field.h" #include "mes.h" +#include "cstoper.h" +#include "ch3bin.h" +#include "ch3.h" +#include "error.h" + extern char *symbol2str(); extern char options[]; extern arith flt_flt2arith(); extern label code_string(); -void -arithbalance(e1p, oper, e2p) /* 3.1.2.5 */ - register struct expr **e1p, **e2p; - int oper; +/* 3.1.2.5 */ +void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p) { /* The expressions *e1p and *e2p are balanced to be operands of the arithmetic operator oper. @@ -171,8 +174,7 @@ arithbalance(e1p, oper, e2p) /* 3.1.2.5 */ } } -relbalance(e1p, oper, e2p) - register struct expr **e1p, **e2p; +void relbalance(register struct expr **e1p, int oper, register struct expr **e2p) { /* The expressions *e1p and *e2p are balanced to be operands of the relational operator oper, or the ':'. @@ -204,9 +206,7 @@ relbalance(e1p, oper, e2p) arithbalance(e1p, oper, e2p); } -ch3pointer(expp, oper, tp) - struct expr **expp; - register struct type *tp; +void ch3pointer(struct expr **expp, int oper, register struct type *tp) { /* Checks whether *expp may be compared to tp using oper, as described in chapter 3.3.8 and 3.3.9. @@ -238,9 +238,7 @@ ch3pointer(expp, oper, tp) } int -any2arith(expp, oper) - register struct expr **expp; - register int oper; +any2arith(register struct expr **expp, register int oper) { /* Turns any expression into int_type, long_type, float_type, double_type or lngdbl_type. @@ -295,8 +293,7 @@ any2arith(expp, oper) return (*expp)->ex_type->tp_fund; } -erroneous2int(expp) - struct expr **expp; +void erroneous2int(struct expr **expp) { /* the (erroneous) expression *expp is replaced by an int expression @@ -310,11 +307,7 @@ erroneous2int(expp) *expp = exp; } -struct expr * -arith2arith(tp, oper, expr) - struct type *tp; - int oper; - register struct expr *expr; +struct expr *arith2arith(struct type *tp, int oper, register struct expr *expr) { /* arith2arith constructs a new expression containing a run-time conversion between some arithmetic types. @@ -328,10 +321,7 @@ arith2arith(tp, oper, expr) return new_oper(tp, new, oper, expr); } -int -int2int(expp, tp) - struct expr **expp; - register struct type *tp; +int int2int(struct expr **expp, register struct type *tp) { /* The expression *expp, which is of some integral type, is converted to the integral type tp. @@ -369,9 +359,7 @@ int2int(expp, tp) /* With compile-time constants, we don't set fp_used, since this is done * only when necessary in eval.c. */ -int2float(expp, tp) - register struct expr **expp; - struct type *tp; +void int2float(register struct expr **expp, struct type *tp) { /* The expression *expp, which is of some integral type, is converted to the floating type tp. @@ -390,9 +378,7 @@ int2float(expp, tp) } } -float2int(expp, tp) - struct expr **expp; - struct type *tp; +void float2int(struct expr **expp, struct type *tp) { /* The expression *expp, which is of some floating type, is converted to the integral type tp. @@ -418,9 +404,7 @@ float2int(expp, tp) } } -float2float(expp, tp) - register struct expr **expp; - struct type *tp; +void float2float(register struct expr **expp, struct type *tp) { /* The expression *expp, which is of some floating type, is converted to the floating type tp. @@ -436,8 +420,7 @@ float2float(expp, tp) } } -array2pointer(exp) - register struct expr *exp; +void array2pointer(register struct expr *exp) { /* The expression, which must be an array, is converted to a pointer. @@ -447,8 +430,7 @@ array2pointer(exp) , (arith)0, NO_PROTO); } -function2pointer(exp) - register struct expr *exp; +void function2pointer(register struct expr *exp) { /* The expression, which must be a function, is converted to a pointer to the function. @@ -457,8 +439,7 @@ function2pointer(exp) (arith)0, NO_PROTO); } -string2pointer(ex) - register struct expr *ex; +void string2pointer(register struct expr *ex) { /* The expression, which must be a string constant, is converted to a pointer to the string-containing area. @@ -472,9 +453,7 @@ string2pointer(ex) ex->VL_VALUE = (arith)0; } -opnd2integral(expp, oper) - register struct expr **expp; - int oper; +void opnd2integral(register struct expr **expp, int oper) { register int fund = (*expp)->ex_type->tp_fund; @@ -486,9 +465,7 @@ opnd2integral(expp, oper) } } -opnd2logical(expp, oper) - register struct expr **expp; - int oper; +void opnd2logical(register struct expr **expp, int oper) { int fund = (*expp)->ex_type->tp_fund; @@ -525,8 +502,7 @@ opnd2logical(expp, oper) } void -opnd2test(expp, oper) - register struct expr **expp; +opnd2test(register struct expr **expp, int oper) { opnd2logical(expp, oper); if ((*expp)->ex_class == Oper) { @@ -550,9 +526,7 @@ opnd2test(expp, oper) ch3bin(expp, NOTEQUAL, intexpr((arith)0, INT)); } -void -any2opnd(expp, oper) - register struct expr **expp; +void any2opnd(register struct expr **expp, int oper) { if (!*expp) return; @@ -584,8 +558,7 @@ any2opnd(expp, oper) } } -any2parameter(expp) - register struct expr **expp; +void any2parameter(register struct expr **expp) { /* To handle default argument promotions */ @@ -598,8 +571,7 @@ any2parameter(expp) } #ifndef NOBITFIELD -field2arith(expp) - register struct expr **expp; +void field2arith(register struct expr **expp) { /* The expression to extract the bitfield value from the memory word is put in the tree. @@ -630,8 +602,7 @@ field2arith(expp) /* switch_sign_fp() negates the given floating constant expression, * and frees the string representing the old value. */ -switch_sign_fp(expr) - register struct expr *expr; +void switch_sign_fp(register struct expr *expr) { flt_umin(&(expr->FL_ARITH)); } diff --git a/lang/cem/cemcom.ansi/arith.h b/lang/cem/cemcom.ansi/arith.h index 4bb403458..65b0003de 100644 --- a/lang/cem/cemcom.ansi/arith.h +++ b/lang/cem/cemcom.ansi/arith.h @@ -12,12 +12,15 @@ to save storage on small machines, SPECIAL_ARITHMETICS will be handy. */ +#ifndef ARITH_H_ +#define ARITH_H_ #include "parameters.h" #ifndef SPECIAL_ARITHMETICS -#include /* obtain definition of "arith" */ +#include /* obtain definition of "arith" */ +#include #else /* SPECIAL_ARITHMETICS */ @@ -27,6 +30,32 @@ #endif /* SPECIAL_ARITHMETICS */ +struct expr; +struct type; + #define arith_size (sizeof(arith)) #define arith_sign ((arith) 1 << (arith_size * 8 - 1)) #define max_arith (~arith_sign) + +void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p); +void relbalance(register struct expr **e1p, int oper, register struct expr **e2p); +void ch3pointer(struct expr **expp, int oper, register struct type *tp); +int any2arith(register struct expr **expp, register int oper); +void erroneous2int(struct expr **expp); +struct expr *arith2arith(struct type *tp, int oper, register struct expr *expr); +int int2int(struct expr **expp, register struct type *tp); +void int2float(register struct expr **expp, struct type *tp); +void float2int(struct expr **expp, struct type *tp); +void float2float(register struct expr **expp, struct type *tp); +void array2pointer(register struct expr *exp); +void function2pointer(register struct expr *exp); +void string2pointer(register struct expr *ex); +void opnd2integral(register struct expr **expp, int oper); +void opnd2logical(register struct expr **expp, int oper); +void opnd2test(register struct expr **expp, int oper); +void any2opnd(register struct expr **expp, int oper); +void any2parameter(register struct expr **expp); +void field2arith(register struct expr **expp); +void switch_sign_fp(register struct expr *expr); + +#endif /* ARITH_H_ */ diff --git a/lang/cem/cemcom.ansi/blocks.c b/lang/cem/cemcom.ansi/blocks.c index 6d75a3670..d4df8b73e 100644 --- a/lang/cem/cemcom.ansi/blocks.c +++ b/lang/cem/cemcom.ansi/blocks.c @@ -18,7 +18,10 @@ #include "label.h" #include "stack.h" #include "Lpars.h" -extern arith NewLocal(); +#include "blocks.h" +#include "macro.h" +#include "util.h" + #define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER) #define LocalIntVar() NewLocal(int_size, int_align, reg_any, REGISTER) #endif /* STB */ @@ -52,9 +55,7 @@ extern arith NewLocal(); while we need a loop to store the stack block into a memory object. */ -suitable_sz(sz, al) - arith sz; - int al; +int suitable_sz(arith sz, int al) { return ((int)sz % (int)word_size == 0 && al % word_align == 0) || ( @@ -64,9 +65,7 @@ suitable_sz(sz, al) ); } -store_block(sz, al) - arith sz; - int al; +void store_block(arith sz, int al) { if (suitable_sz(sz, al)) C_sti(sz); @@ -102,9 +101,7 @@ store_block(sz, al) } } -load_block(sz, al) - arith sz; - int al; +void load_block(arith sz, int al) { if (suitable_sz(sz, al)) @@ -138,9 +135,7 @@ load_block(sz, al) } } -copy_block(sz, al) - arith sz; - int al; +void copy_block(arith sz, int al) { if (suitable_sz(sz, al)) @@ -167,8 +162,7 @@ copy_block(sz, al) } #ifndef STB -copy_loop(sz, src, dst) - arith sz, src, dst; +void copy_loop(arith sz, arith src, arith dst) { /* generate inline byte-copy loop */ label l_cont = text_label(), l_stop = text_label(); diff --git a/lang/cem/cemcom.ansi/blocks.h b/lang/cem/cemcom.ansi/blocks.h new file mode 100644 index 000000000..45f18d491 --- /dev/null +++ b/lang/cem/cemcom.ansi/blocks.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef BLOCKS_H_ +#define BLOCKS_H_ + +#include "parameters.h" +#include "arith.h" + +int suitable_sz(arith sz, int al); +void store_block(arith sz, int al); +void load_block(arith sz, int al); +void copy_block(arith sz, int al); +void copy_loop(arith sz, arith src, arith dst); + +#endif /* BLOCKS_H_ */ diff --git a/lang/cem/cemcom.ansi/ch3.c b/lang/cem/cemcom.ansi/ch3.c index 535426937..3132ccbb9 100644 --- a/lang/cem/cemcom.ansi/ch3.c +++ b/lang/cem/cemcom.ansi/ch3.c @@ -9,6 +9,7 @@ #include "parameters.h" #include #include "arith.h" +#include "ch3.h" #include "idf.h" #include "proto.h" #include "type.h" @@ -17,23 +18,22 @@ #include "expr.h" #include "def.h" #include "Lpars.h" +#include "error.h" +#include "ch3bin.h" #include "file_info.h" extern char options[]; extern char *symbol2str(); extern struct type *qualifier_type(); -void ch3cast(); + /* Most expression-handling routines have a pointer to a (struct type *) as first parameter. The object under the pointer gets updated in the process. */ -void -ch3sel(expp, oper, idf) - struct expr **expp; - struct idf *idf; +void ch3sel(struct expr **expp, int oper, struct idf *idf) { /* The selector idf is applied to *expp; oper may be '.' or ARROW. @@ -163,8 +163,7 @@ ch3sel(expp, oper, idf) *expp = exp; } -ch3incr(expp, oper) - struct expr **expp; +void ch3incr(struct expr **expp, int oper) { /* The monadic prefix/postfix incr/decr operator oper is applied to *expp. @@ -172,10 +171,7 @@ ch3incr(expp, oper) ch3asgn(expp, oper, intexpr((arith)1, INT)); } -void -ch3cast(expp, oper, tp) - register struct expr **expp; - register struct type *tp; +void ch3cast(register struct expr **expp, int oper, register struct type *tp) { /* The expression *expp is cast to type tp; the cast is caused by the operator oper. If the cast has @@ -412,9 +408,7 @@ ch3cast(expp, oper, tp) /* Determine whether two types are equal. */ -equal_type(tp, otp, qual_lev, diag) - register struct type *tp, *otp; - int qual_lev, diag; +int equal_type(register struct type *tp,register struct type *otp, int qual_lev, int diag) { if (tp == otp) return 1; @@ -475,8 +469,7 @@ equal_type(tp, otp, qual_lev, diag) } } -check_pseudoproto(pl, opl, diag) - register struct proto *pl, *opl; +int check_pseudoproto(register struct proto *pl,register struct proto *opl, int diag) { int retval = 1; @@ -519,9 +512,7 @@ check_pseudoproto(pl, opl, diag) return retval; } -legal_mixture(tp, otp, diag) - struct type *tp, *otp; - int diag; +int legal_mixture(struct type *tp, struct type *otp, int diag) { struct proto *pl = tp->tp_proto, *opl = otp->tp_proto; int retval = 1; @@ -562,9 +553,7 @@ legal_mixture(tp, otp, diag) return retval; } -equal_proto(pl, opl, diag) - register struct proto *pl, *opl; - int diag; +int equal_proto(register struct proto *pl, register struct proto *opl, int diag) { if (pl == opl) return 1; @@ -586,9 +575,7 @@ equal_proto(pl, opl, diag) } /* check if a type has a consqualified member */ -recurqual(tp, qual) -struct type *tp; -int qual; +int recurqual(struct type *tp, int qual) { register struct sdef *sdf; @@ -610,9 +597,7 @@ int qual; return 0; } -ch3asgn(expp, oper, expr) - struct expr **expp; - struct expr *expr; +void ch3asgn(struct expr **expp, int oper, struct expr *expr) { /* The assignment operators. "f op= e" should be interpreted as @@ -687,9 +672,7 @@ ch3asgn(expp, oper, expr) /* Some interesting (?) questions answered. */ -int -is_integral_type(tp) - register struct type *tp; +int is_integral_type(register struct type *tp) { switch (tp->tp_fund) { case CHAR: @@ -707,9 +690,7 @@ is_integral_type(tp) } } -int -is_arith_type(tp) - register struct type *tp; +int is_arith_type(register struct type *tp) { switch (tp->tp_fund) { case CHAR: diff --git a/lang/cem/cemcom.ansi/ch3.h b/lang/cem/cemcom.ansi/ch3.h new file mode 100644 index 000000000..a8970f75e --- /dev/null +++ b/lang/cem/cemcom.ansi/ch3.h @@ -0,0 +1,29 @@ +/* Copyright (c) 2019 ACK Project. See the file Copyright in + * the project root directory for more information. + * + * Created on: 2019-02-06 + * + */ +#ifndef CH3_H_ +#define CH3_H_ + +/* Structure forward declarations. */ +struct expr; +struct type; +struct proto; +struct idf; + + +void ch3sel(struct expr **expp, int oper, struct idf *idf); +void ch3incr(struct expr **expp, int oper); +void ch3cast(register struct expr **expp, int oper, register struct type *tp); +int equal_type(register struct type *tp,register struct type *otp, int qual_lev, int diag); +int check_pseudoproto(register struct proto *pl,register struct proto *opl, int diag); +int legal_mixture(struct type *tp, struct type *otp, int diag); +int equal_proto(register struct proto *pl, register struct proto *opl, int diag); +int recurqual(struct type *tp, int qual); +void ch3asgn(struct expr **expp, int oper, struct expr *expr); +int is_integral_type(register struct type *tp); +int is_arith_type(register struct type *tp); + +#endif /* CH3_H_ */ diff --git a/lang/cem/cemcom.ansi/ch3bin.c b/lang/cem/cemcom.ansi/ch3bin.c index ba75c112c..e692e98fa 100644 --- a/lang/cem/cemcom.ansi/ch3bin.c +++ b/lang/cem/cemcom.ansi/ch3bin.c @@ -15,6 +15,12 @@ #include "expr.h" #include "Lpars.h" #include "sizes.h" +#include "ch3bin.h" +#include "ch3mon.h" +#include "ch3.h" +#include "error.h" +#include "cstoper.h" +#include "fltcstoper.h" extern char options[]; extern char *symbol2str(); @@ -34,10 +40,7 @@ void pntminuspnt(); #define commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 1) #define non_commutative_relop(expp, oper, expr) mk_binop(expp, oper, expr, 1) -void -ch3bin(expp, oper, expr) - register struct expr **expp; - struct expr *expr; +void ch3bin(register struct expr **expp, int oper, struct expr *expr) { /* apply binary operator oper between *expp and expr. NB: don't swap operands if op is one of the op= operators!!! @@ -295,9 +298,7 @@ ch3bin(expp, oper, expr) } } -void -pntminuspnt(expp, oper, expr) - register struct expr **expp, *expr; +void pntminuspnt(register struct expr **expp, int oper, register struct expr *expr) { /* Subtracting two pointers is so complicated it merits a routine of its own. @@ -328,8 +329,7 @@ pntminuspnt(expp, oper, expr) * when the arguments are switched. This is special for some relational * operators. */ -int -arg_switched(oper) +int arg_switched(int oper) { switch (oper) { case '<': return '>'; @@ -340,9 +340,7 @@ arg_switched(oper) } } -mk_binop(expp, oper, expr, commutative) - struct expr **expp; - register struct expr *expr; +void mk_binop(struct expr **expp, int oper, register struct expr *expr, int commutative) { /* Constructs in *expp the operation indicated by the operands. "commutative" indicates whether "oper" is a commutative @@ -366,8 +364,7 @@ mk_binop(expp, oper, expr, commutative) } } -pointer_arithmetic(expp1, oper, expp2) - register struct expr **expp1, **expp2; +void pointer_arithmetic(register struct expr **expp1, int oper, register struct expr **expp2) { int typ; /* prepares the integral expression expp2 in order to @@ -387,8 +384,7 @@ pointer_arithmetic(expp1, oper, expp2) ); } -pointer_binary(expp, oper, expr) - register struct expr **expp, *expr; +void pointer_binary(register struct expr **expp, int oper, register struct expr *expr) { /* constructs the pointer arithmetic expression out of a pointer expression, a binary operator and an integral diff --git a/lang/cem/cemcom.ansi/ch3bin.h b/lang/cem/cemcom.ansi/ch3bin.h new file mode 100644 index 000000000..bc6ea2d20 --- /dev/null +++ b/lang/cem/cemcom.ansi/ch3bin.h @@ -0,0 +1,21 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef CH3BIN_H_ +#define CH3BIN_H_ + +struct expr; + +void ch3bin(register struct expr **expp, int oper, struct expr *expr); +void pntminuspnt(register struct expr **expp, int oper, register struct expr *expr); +int arg_switched(int oper); +void mk_binop(struct expr **expp, int oper, register struct expr *expr, int commutative); +void pointer_arithmetic(register struct expr **expp1, int oper, register struct expr **expp2); +void pointer_binary(register struct expr **expp, int oper, register struct expr *expr); + + +#endif /* CH3BIN_H_ */ diff --git a/lang/cem/cemcom.ansi/ch3mon.c b/lang/cem/cemcom.ansi/ch3mon.c index 8cffc2c9d..a84a141f2 100644 --- a/lang/cem/cemcom.ansi/ch3mon.c +++ b/lang/cem/cemcom.ansi/ch3mon.c @@ -5,6 +5,7 @@ /* $Id$ */ /* SEMANTIC ANALYSIS (CHAPTER 3.3) -- MONADIC OPERATORS */ +#include "ch3mon.h" #include "parameters.h" #include #include "Lpars.h" @@ -16,13 +17,15 @@ #include "expr.h" #include "def.h" #include "sizes.h" +#include "ch3.h" +#include "error.h" + extern char options[]; extern arith full_mask[/*MAXSIZE + 1*/]; /* cstoper.c */ char *symbol2str(); -ch3mon(oper, expp) - register struct expr **expp; +void ch3mon(int oper, register struct expr **expp) { /* The monadic prefix operator oper is applied to *expp. */ diff --git a/lang/cem/cemcom.ansi/ch3mon.h b/lang/cem/cemcom.ansi/ch3mon.h new file mode 100644 index 000000000..354738c42 --- /dev/null +++ b/lang/cem/cemcom.ansi/ch3mon.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef CH3MON_H_ +#define CH3MON_H_ + +struct expr; + +void ch3mon(int oper, register struct expr **expp); +void ch3bin(register struct expr **expp, int oper, struct expr *expr); +void pntminuspnt(register struct expr **expp, int oper, register struct expr *expr); +int arg_switched(int oper); +void mk_binop(struct expr **expp, int oper, register struct expr *expr, int commutative); +void pointer_arithmetic(register struct expr **expp1, int oper, register struct expr **expp2); +void pointer_binary(register struct expr **expp, int oper, register struct expr *expr); + + +#endif /* CH3MON_H_ */ diff --git a/lang/cem/cemcom.ansi/code.c b/lang/cem/cemcom.ansi/code.c index a6a898ab7..d50700056 100644 --- a/lang/cem/cemcom.ansi/code.c +++ b/lang/cem/cemcom.ansi/code.c @@ -27,14 +27,24 @@ #include "expr.h" #include "sizes.h" #include "stack.h" +#include "blocks.h" +#include "struct.h" #include "level.h" +#include "dataflow.h" +#include "conversion.h" #include "decspecs.h" #include "declar.h" #include "Lpars.h" #include "specials.h" #include "atw.h" +#include "ch3.h" +#include "eval.h" +#include "stab.h" #include "LLlex.h" #include "align.h" +#include "util.h" +#include "error.h" + #ifdef LINT #include "l_lint.h" #endif /* LINT */ @@ -46,7 +56,10 @@ label lab_count = 1; label datlab_count = 1; int fp_used; -extern arith NewLocal(); /* util.c */ + +extern void str_cst(register char *, register int, int); /* ival.c */ + + /* global function info */ char *func_name; @@ -67,8 +80,7 @@ extern char *source; void loc_init(); #ifndef LINT -init_code(dst_file) - char *dst_file; +void init_code(char *dst_file) { /* init_code() initialises the output file on which the compact EM code is written @@ -105,10 +117,7 @@ init_code(dst_file) struct string_cst *str_list = 0; -label -code_string(val, len) - char *val; - int len; +label code_string(char* val, int len) { register struct string_cst *sc = new_string_cst(); label dlb = data_label(); @@ -122,8 +131,7 @@ code_string(val, len) return dlb; } -def_strings(sc) - register struct string_cst *sc; +void def_strings(register struct string_cst *sc) { while (sc) { struct string_cst *sc1 = sc; @@ -137,7 +145,7 @@ def_strings(sc) } /* flush_strings() is called from program.g after each external definition */ -flush_strings() { +void flush_strings(void) { if (str_list) { def_strings(str_list); str_list = 0; @@ -145,7 +153,7 @@ flush_strings() { } #ifndef LINT -end_code() +void end_code(void) { /* end_code() performs the actions to be taken when closing the output stream. @@ -160,7 +168,7 @@ end_code() #endif /* LINT */ #ifdef PREPEND_SCOPES -prepend_scopes() +void prepend_scopes(void) { /* prepend_scopes() runs down the list of global idf's and generates those exa's, exp's, ina's and inp's @@ -185,9 +193,7 @@ prepend_scopes() } #endif /* PREPEND_SCOPES */ -code_scope(text, def) - char *text; - register struct def *def; +void code_scope(char* text, register struct def *def) { /* generates code for one name, text, of the storage class as given by def, if meaningful. @@ -218,9 +224,7 @@ static int struct_return; static char *last_fn_given = (char *)0; static label file_name_label; -begin_proc(ds, idf) /* to be called when entering a procedure */ - struct decspecs *ds; - struct idf *idf; +void begin_proc(struct decspecs *ds, struct idf *idf) /* to be called when entering a procedure */ { /* begin_proc() is called at the entrance of a new function and performs the necessary code generation: @@ -317,8 +321,7 @@ begin_proc(ds, idf) /* to be called when entering a procedure */ #endif } -end_proc(fbytes) - arith fbytes; +void end_proc(arith fbytes) { /* end_proc() deals with the code to be generated at the end of a function, as there is: @@ -388,7 +391,7 @@ end_proc(fbytes) options['n'] = optionsn; } -do_return() +void do_return(void) { /* do_return handles the case of a return without expression. This version branches to the return label, which is @@ -401,8 +404,7 @@ do_return() C_bra(return2_label); } -do_return_expr(expr) - struct expr *expr; +void do_return_expr(struct expr *expr) { /* do_return_expr() generates the expression and the jump for a return statement with an expression. @@ -418,11 +420,11 @@ do_return_expr(expr) } void -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( + 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". @@ -530,10 +532,7 @@ code_declaration(idf, expr, lvl, sc) } } -void -loc_init(expr, id) - struct expr *expr; - struct idf *id; +void loc_init(struct expr *expr, struct idf *id) { /* loc_init() generates code for the assignment of expression expr to the local variable described by id. @@ -609,8 +608,7 @@ loc_init(expr, id) } } -bss(idf) - register struct idf *idf; +void bss(register struct idf *idf) { /* bss() allocates bss space for the global idf. */ @@ -640,9 +638,7 @@ bss(idf) } } -formal_cvt(hasproto,df) - int hasproto; - register struct def *df; +void formal_cvt(int hasproto, register struct def *df) { /* formal_cvt() converts a formal parameter of type char or short from int to that type. It also converts a formal @@ -672,9 +668,7 @@ formal_cvt(hasproto,df) #ifdef LINT /*ARGSUSED*/ #endif /* LINT */ -code_expr(expr, val, code, tlbl, flbl) - struct expr *expr; - label tlbl, flbl; +void code_expr(struct expr *expr, int val, int code, label tlbl, label flbl) { /* code_expr() is the parser's interface to the expression code generator. If line number trace is wanted, it generates a @@ -707,7 +701,7 @@ static struct stmt_block *stmt_stack; /* top of statement stack */ which are the only ones that are stacked, only the top of the stack is interesting. */ -code_break() +void code_break(void) { register struct stmt_block *stmt_block = stmt_stack; @@ -726,7 +720,7 @@ code_break() innermost statement in which continue has a meaning. */ void -code_continue() +code_continue(void) { register struct stmt_block *stmt_block = stmt_stack; @@ -743,8 +737,7 @@ code_continue() error("continue not inside for, while or do"); } -stack_stmt(break_label, cont_label) - label break_label, cont_label; +void stack_stmt(label break_label, label cont_label) { register struct stmt_block *stmt_block = new_stmt_block(); @@ -754,7 +747,7 @@ stack_stmt(break_label, cont_label) stmt_stack = stmt_block; } -unstack_stmt() +void unstack_stmt(void) { /* unstack_stmt() unstacks the data of a statement which may contain break or continue @@ -766,8 +759,7 @@ unstack_stmt() static label prc_name; -prc_entry(name) - char *name; +void prc_entry(char* name) { if (options['p']) { C_df_dlb(prc_name = data_label()); @@ -778,7 +770,7 @@ prc_entry(name) } } -prc_exit() +void prc_exit(void) { if (options['p']) { C_lae_dlb(prc_name, (arith) 0); @@ -788,9 +780,7 @@ prc_exit() } #ifdef DBSYMTAB -db_line(file, line) - char *file; - unsigned int line; +void db_line(char *file, unsigned int line) { static unsigned oldline; static char *oldfile; diff --git a/lang/cem/cemcom.ansi/code.str b/lang/cem/cemcom.ansi/code.str index b818bbea0..b3770395f 100644 --- a/lang/cem/cemcom.ansi/code.str +++ b/lang/cem/cemcom.ansi/code.str @@ -2,9 +2,15 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef CODE_H_ +#define CODE_H_ /* $Id$ */ /* C O D E - G E N E R A T O R D E F I N I T I O N S */ +#include "arith.h" +#include "label.h" + + struct string_cst { /* storing string constants */ struct string_cst *next; char *sc_value; @@ -20,3 +26,44 @@ extern struct string_cst *str_list; #define RVAL 1 #define FALSE 0 #define TRUE 1 + + +#ifndef LINT +void init_code(char *dst_file); +void end_code(void); +#endif + +struct expr; +struct def; +struct idf; + +label code_string(char* val, int len); +void def_strings(register struct string_cst *sc); +void flush_strings(void); +void code_scope(char* text, register struct def *def); +void begin_proc(struct decspecs *ds, struct idf *idf); +void end_proc(arith fbytes); +void do_return(void); +void do_return_expr(struct expr *expr); +void code_declaration(register struct idf *idf, struct expr *expr, + int lvl, int sc); +void loc_init(struct expr *expr, struct idf *id); +void bss(register struct idf *idf); +void formal_cvt(int hasproto, register struct def *df); +void code_expr(struct expr *expr, int val, int code, label tlbl, label flbl); +void code_break(void); +void code_continue(void); +void stack_stmt(label break_label, label cont_label); +void unstack_stmt(void); +void prc_entry(char* name); +void prc_exit(void); + +#ifdef PREPEND_SCOPES +void prepend_scopes(void); +#endif + +#ifdef DBSYMTAB +void db_line(char *file, unsigned int line); +#endif + +#endif diff --git a/lang/cem/cemcom.ansi/conversion.c b/lang/cem/cemcom.ansi/conversion.c index 485d8b8bd..60d4c45b5 100644 --- a/lang/cem/cemcom.ansi/conversion.c +++ b/lang/cem/cemcom.ansi/conversion.c @@ -8,11 +8,15 @@ #include "parameters.h" #ifndef LINT +#include "conversion.h" #include +#include "interface.h" #include "arith.h" #include "type.h" #include "sizes.h" #include "Lpars.h" +#include "error.h" + #define T_SIGNED 1 #define T_UNSIGNED 2 @@ -27,10 +31,9 @@ C?? */ -static int convtype(); +static int convtype(register struct type *); -conversion(from_type, to_type) - register struct type *from_type, *to_type; +void conversion(register struct type *from_type, register struct type *to_type) { register arith from_size = from_type->tp_size; register arith to_size = to_type->tp_size; @@ -126,9 +129,7 @@ conversion(from_type, to_type) /* convtype() returns in which category a given type falls: signed, unsigned or floating */ -static int -convtype(tp) - register struct type *tp; +static int convtype(register struct type *tp) { switch (tp->tp_fund) { case CHAR: diff --git a/lang/cem/cemcom.ansi/conversion.h b/lang/cem/cemcom.ansi/conversion.h new file mode 100644 index 000000000..25756a94d --- /dev/null +++ b/lang/cem/cemcom.ansi/conversion.h @@ -0,0 +1,15 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef CONVERSION_H_ +#define CONVERSION_H_ + +struct type; + +void conversion(register struct type *from_type, register struct type *to_type); + +#endif /* CONVERSION_H_ */ diff --git a/lang/cem/cemcom.ansi/cstoper.c b/lang/cem/cemcom.ansi/cstoper.c index a63103ba3..774e356d6 100644 --- a/lang/cem/cemcom.ansi/cstoper.c +++ b/lang/cem/cemcom.ansi/cstoper.c @@ -6,6 +6,7 @@ /* 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 +#include "cstoper.h" #include "parameters.h" #include #include "arith.h" @@ -14,6 +15,7 @@ #include "expr.h" #include "sizes.h" #include "Lpars.h" +#include "error.h" /* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */ arith full_mask[MAXSIZE + 1]; @@ -23,8 +25,7 @@ arith max_unsigned; /* maximum unsigned on target machine */ #endif /* NOCROSS */ extern int ResultKnown; -cstbin(expp, oper, expr) - register struct expr **expp, *expr; +void cstbin(register struct expr **expp, int oper, register struct expr *expr) { /* The operation oper is performed on the constant expressions *expp(ld) and expr(ct), and the result restored in @@ -134,8 +135,7 @@ cstbin(expp, oper, expr) free_expression(expr); } -cut_size(expr) - register struct expr *expr; +void cut_size(register struct expr *expr) { /* The constant value of the expression expr is made to conform to the size of the type of the expression. @@ -170,7 +170,7 @@ cut_size(expr) expr->VL_VALUE = o1; } -init_cst() +void init_cst(void) { register int i = 0; register arith bt = (arith)0; diff --git a/lang/cem/cemcom.ansi/cstoper.h b/lang/cem/cemcom.ansi/cstoper.h new file mode 100644 index 000000000..4d0d971f1 --- /dev/null +++ b/lang/cem/cemcom.ansi/cstoper.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef CSTOPER_H_ +#define CSTOPER_H_ + +struct expr; + +void cstbin(register struct expr **expp, int oper, register struct expr *expr); +void cut_size(register struct expr *expr); +void init_cst(void); + +#endif /* CSTOPER_H_ */ diff --git a/lang/cem/cemcom.ansi/dataflow.c b/lang/cem/cemcom.ansi/dataflow.c index 6a3fbcf65..cdd7781cf 100644 --- a/lang/cem/cemcom.ansi/dataflow.c +++ b/lang/cem/cemcom.ansi/dataflow.c @@ -10,26 +10,26 @@ */ #include "parameters.h" /* UF */ +#include "dataflow.h" +#include "print.h" #ifdef DATAFLOW char *CurrentFunction = 0; int NumberOfCalls; -DfaStartFunction(nm) - char *nm; +void DfaStartFunction(char* nm) { CurrentFunction = nm; NumberOfCalls = 0; } -DfaEndFunction() +void DfaEndFunction(void) { if (NumberOfCalls == 0) print("DFA: %s: --none--\n", CurrentFunction); } -DfaCallFunction(s) - char *s; +void DfaCallFunction(char* s) { print("DFA: %s: %s\n", CurrentFunction, s); ++NumberOfCalls; diff --git a/lang/cem/cemcom.ansi/dataflow.h b/lang/cem/cemcom.ansi/dataflow.h new file mode 100644 index 000000000..e353b9ac8 --- /dev/null +++ b/lang/cem/cemcom.ansi/dataflow.h @@ -0,0 +1,19 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef DATAFLOW_H_ +#define DATAFLOW_H_ + +#ifdef DATAFLOW + +void DfaStartFunction(char* nm); +void DfaEndFunction(void); +void DfaCallFunction(char* s); + +#endif + +#endif /* DATAFLOW_H_ */ diff --git a/lang/cem/cemcom.ansi/declar.g b/lang/cem/cemcom.ansi/declar.g index d6119f59d..92adefb5f 100644 --- a/lang/cem/cemcom.ansi/declar.g +++ b/lang/cem/cemcom.ansi/declar.g @@ -1,764 +1,768 @@ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -/* $Id$ */ -/* DECLARATION SYNTAX PARSER */ - -{ -#include "parameters.h" -#include -#include -#include "idf.h" -#include "arith.h" -#include "LLlex.h" -#include "label.h" -#include "code.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" -#endif /* LINT */ - -extern char options[]; -} - -/* 3.5 */ -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 legal C. - - On top of that, multiple occurrences of storage_class_specifiers, - unsigned_specifiers and size_specifiers are errors, but a second - type_specifier should end the decl_specifiers and be treated as - the name to be declared. - 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. -*/ -/* Accept a single declaration specifier. Then accept zero or more - declaration specifiers. There can be a conflict on both - TYPE_IDENTIFIER and IDENTIFIER. - The following rule is used: - When we see a TYPE_IDENTIFIER, we accept it if no type-specifier was - given, and it is not directly followed by an identifier. If a - type-specifier was given, it is taken as the identifier being - declared. If it is followed by an identifier, we assume that an - error has been made, (e.g. unsigned typedeffed_int x;) and that - this will be detected later on. - When we see an IDENTIFIER, directly followed by another IDENTIFIER, - we assume that a typing mistake has been made, and we accept it as - an erroneous type-identifier. -*/ - -decl_specifiers /* non-empty */ (register struct decspecs *ds;) - /* Reads a non-empty decl_specifiers and fills the struct - decspecs *ds. - */ -: - single_decl_specifier(ds) - [ %while( (DOT==TYPE_IDENTIFIER - && ds->ds_size == 0 - && ds->ds_unsigned == 0 - && ds->ds_type == (struct type *)0) - || AHEAD == IDENTIFIER) /* always an error */ - single_decl_specifier(ds) - ]* - {do_decspecs(ds);} -; - -single_decl_specifier /* non_empty */ (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; - } -| - VOLATILE - { if (ds->ds_typequal & TQ_VOLATILE) - error("repeated type qualifier"); - ds->ds_typequal |= TQ_VOLATILE; - } -| - CONST - { if (ds->ds_typequal & TQ_CONST) - error("repeated type qualifier"); - ds->ds_typequal |= TQ_CONST; - } -| - [ 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; - } -| - [ VOID | CHAR | INT | FLOAT | DOUBLE ] - { - idf2type(dot.tk_idf, &ds->ds_type); - ds->ds_typedef = 0; - } -| - %default TYPE_IDENTIFIER - { - idf2type(dot.tk_idf, &ds->ds_type); - ds->ds_typedef = 1; - } -| - %erroneous - 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; - } - } -| - %illegal - IDENTIFIER -| - struct_or_union_specifier(&ds->ds_type) -| - enum_specifier(&ds->ds_type) -; - -/* 3.5.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;} -; - -/* 3.5 */ -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); - } -; - -/* 3.5.7: initializer */ -initializer(struct idf *idf; int sc;) - { - struct expr *expr = (struct expr *) 0; - int fund = idf->id_def->df_type->tp_fund; - int autoagg = (level >= L_LOCAL - && sc != STATIC - && ( fund == STRUCT - || fund == UNION - || fund == ARRAY)); - int globalflag = level == L_GLOBAL - || (level >= L_LOCAL && sc == STATIC); - } -: - { if (idf->id_def->df_type->tp_fund == FUNCTION) { - error("illegal initialization of function"); - idf->id_def->df_type->tp_fund = ERRONEOUS; - } - if (level == L_FORMAL2) - error("illegal initialization of formal parameter"); - } - '=' - { - if (AHEAD != '{' && AHEAD != STRING ) autoagg = 0; -#ifdef LINT - lint_statement(); -#endif /* LINT */ - if (globalflag) { - struct expr ex; - code_declaration(idf, &ex, level, sc); - } - else if (autoagg) - loc_init((struct expr *) 0, idf); - } - initial_value((globalflag || autoagg) ? - &(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 */ -#ifdef DBSYMTAB - if (options['g'] && level >= L_LOCAL && expr) { - db_line(expr->ex_file, (unsigned) expr->ex_line); - } -#endif /* DBSYMTAB */ - if (autoagg) - loc_init((struct expr *) 0, idf); - else code_declaration(idf, expr, level, sc); - } -#ifdef DBSYMTAB - if (options['g'] && globalflag) { - stb_string(idf->id_def, sc, idf->id_text); - } -#endif /* DBSYMTAB */ - idf_initialized(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. -*/ -/* 3.5.4 */ -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) - 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; } -: - '[' - { *sizep = (arith)-1; } - [ - constant_expression(&expr) - { - check_array_subscript(expr); - *sizep = expr->VL_VALUE; - free_expression(expr); - } - ]? - ']' -; - -formal_list (struct formal **fmp;) -: - formal(fmp) [ %persistent ',' 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; - if (idf->id_def && idf->id_def->df_sc == TYPEDEF) { - error("typedef name %s may not be redeclared as a parameter", idf->id_text); - } - } -; - -/* Change 2 */ -enum_specifier(register struct type **tpp;) - { - struct idf *idf; - arith l = (arith)0; - } -: - {if (*tpp) error("multiple types in declaration");} - ENUM - [ - {declare_struct(ENUM, (struct idf *) 0, tpp);} - enumerator_pack(*tpp, &l) - | - identifier(&idf) - [ - {declare_struct(ENUM, idf, tpp);} - enumerator_pack(*tpp, &l) - { -#ifdef DBSYMTAB - if (options['g']) { - stb_tag(idf->id_tag, idf->id_text); - } -#endif /*DBSYMTAB */ - } - | - {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; - } -: - {if (*tpp) error("multiple types in declaration");} - [ 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_tag->tg_busy)++; - } - struct_declaration_pack(*tpp) - { - (idf->id_tag->tg_busy)--; -#ifdef DBSYMTAB - if (options['g']) { - stb_tag(idf->id_tag, idf->id_text); - } -#endif /*DBSYMTAB */ - } - | - { - /* a ';' means an empty declaration (probably) - * this means that we have to declare a new - * structure. (yegh) - */ - if (DOT == ';' && - ( !idf->id_tag || - idf->id_tag->tg_level != level || - idf->id_tag->tg_type->tp_size < 0 - )) declare_struct(fund, idf, tpp); - else 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); - completed(stp); - } -; - -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; struct type *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); - if (pl) remove_proto_idfs(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);} -; - -%first first_of_parameter_type_list, parameter_type_list; - -primary_abstract_declarator(struct declarator *dc;) -: -[%if (AHEAD == ')' || first_of_parameter_type_list(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 = PL_ELLIPSIS; - *plp = new; - } - - ]? - { check_for_void(*plp); - if (level == L_PROTO) - level = save_level; - else level++; - } -; - -parameter_decl_list(struct proto **plp;) -: - parameter_decl(plp) - [ %while (AHEAD != ELLIPSIS) - %persistent - ',' 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; - remove_declarator(&Dc); - } -; - -/* 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 separately, 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) - parameter_type_list(&pl) - | - formal_list(&fm) - | - /* empty */ - ] - ')' - { add_decl_unary(dc, FUNCTION, 0, (arith)0, fm, pl); - reject_params(dc); - } - | - arrayer(&count) - {add_decl_unary(dc, ARRAY, 0, count, NO_PARAMS, NO_PROTO);} - ]* -| - 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 == ')' || first_of_parameter_type_list(AHEAD) - && (AHEAD != IDENTIFIER)) - /* 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. -*/ -/* 3.5.4 */ -type_qualifier_list(int *qual;) -: - { *qual = 0; } - [ - VOLATILE - { if (*qual & TQ_VOLATILE) - error("repeated type qualifier"); - *qual |= TQ_VOLATILE; - } - | - CONST - { if (*qual & TQ_CONST) - error("repeated type qualifier"); - *qual |= TQ_CONST; - } - ]* -; - -empty: -; +/* + * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ +/* $Id$ */ +/* DECLARATION SYNTAX PARSER */ + +{ +#include "parameters.h" +#include +#include +#include "idf.h" +#include "arith.h" +#include "LLlex.h" +#include "label.h" +#include "code.h" +#include "type.h" +#include "proto.h" +#include "struct.h" +#include "field.h" +#include "decspecs.h" +#include "declarator.h" +#include "def.h" +#include "declar.h" +#include "label.h" +#include "expr.h" +#include "sizes.h" +#include "level.h" +#include "error.h" +#include "stab.h" + +#ifdef LINT +#include "l_lint.h" +#endif /* LINT */ + +extern char options[]; +} + +/* 3.5 */ +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 legal C. + + On top of that, multiple occurrences of storage_class_specifiers, + unsigned_specifiers and size_specifiers are errors, but a second + type_specifier should end the decl_specifiers and be treated as + the name to be declared. + 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. +*/ +/* Accept a single declaration specifier. Then accept zero or more + declaration specifiers. There can be a conflict on both + TYPE_IDENTIFIER and IDENTIFIER. + The following rule is used: + When we see a TYPE_IDENTIFIER, we accept it if no type-specifier was + given, and it is not directly followed by an identifier. If a + type-specifier was given, it is taken as the identifier being + declared. If it is followed by an identifier, we assume that an + error has been made, (e.g. unsigned typedeffed_int x;) and that + this will be detected later on. + When we see an IDENTIFIER, directly followed by another IDENTIFIER, + we assume that a typing mistake has been made, and we accept it as + an erroneous type-identifier. +*/ + +decl_specifiers /* non-empty */ (register struct decspecs *ds;) + /* Reads a non-empty decl_specifiers and fills the struct + decspecs *ds. + */ +: + single_decl_specifier(ds) + [ %while( (DOT==TYPE_IDENTIFIER + && ds->ds_size == 0 + && ds->ds_unsigned == 0 + && ds->ds_type == (struct type *)0) + || AHEAD == IDENTIFIER) /* always an error */ + single_decl_specifier(ds) + ]* + {do_decspecs(ds);} +; + +single_decl_specifier /* non_empty */ (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; + } +| + VOLATILE + { if (ds->ds_typequal & TQ_VOLATILE) + error("repeated type qualifier"); + ds->ds_typequal |= TQ_VOLATILE; + } +| + CONST + { if (ds->ds_typequal & TQ_CONST) + error("repeated type qualifier"); + ds->ds_typequal |= TQ_CONST; + } +| + [ 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; + } +| + [ VOID | CHAR | INT | FLOAT | DOUBLE ] + { + idf2type(dot.tk_idf, &ds->ds_type); + ds->ds_typedef = 0; + } +| + %default TYPE_IDENTIFIER + { + idf2type(dot.tk_idf, &ds->ds_type); + ds->ds_typedef = 1; + } +| + %erroneous + 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; + } + } +| + %illegal + IDENTIFIER +| + struct_or_union_specifier(&ds->ds_type) +| + enum_specifier(&ds->ds_type) +; + +/* 3.5.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;} +; + +/* 3.5 */ +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); + } +; + +/* 3.5.7: initializer */ +initializer(struct idf *idf; int sc;) + { + struct expr *expr = (struct expr *) 0; + int fund = idf->id_def->df_type->tp_fund; + int autoagg = (level >= L_LOCAL + && sc != STATIC + && ( fund == STRUCT + || fund == UNION + || fund == ARRAY)); + int globalflag = level == L_GLOBAL + || (level >= L_LOCAL && sc == STATIC); + } +: + { if (idf->id_def->df_type->tp_fund == FUNCTION) { + error("illegal initialization of function"); + idf->id_def->df_type->tp_fund = ERRONEOUS; + } + if (level == L_FORMAL2) + error("illegal initialization of formal parameter"); + } + '=' + { + if (AHEAD != '{' && AHEAD != STRING ) autoagg = 0; +#ifdef LINT + lint_statement(); +#endif /* LINT */ + if (globalflag) { + struct expr ex; + code_declaration(idf, &ex, level, sc); + } + else if (autoagg) + loc_init((struct expr *) 0, idf); + } + initial_value((globalflag || autoagg) ? + &(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 */ +#ifdef DBSYMTAB + if (options['g'] && level >= L_LOCAL && expr) { + db_line(expr->ex_file, (unsigned) expr->ex_line); + } +#endif /* DBSYMTAB */ + if (autoagg) + loc_init((struct expr *) 0, idf); + else code_declaration(idf, expr, level, sc); + } +#ifdef DBSYMTAB + if (options['g'] && globalflag) { + stb_string(idf->id_def, sc, idf->id_text); + } +#endif /* DBSYMTAB */ + idf_initialized(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. +*/ +/* 3.5.4 */ +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) + 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; } +: + '[' + { *sizep = (arith)-1; } + [ + constant_expression(&expr) + { + check_array_subscript(expr); + *sizep = expr->VL_VALUE; + free_expression(expr); + } + ]? + ']' +; + +formal_list (struct formal **fmp;) +: + formal(fmp) [ %persistent ',' 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; + if (idf->id_def && idf->id_def->df_sc == TYPEDEF) { + error("typedef name %s may not be redeclared as a parameter", idf->id_text); + } + } +; + +/* Change 2 */ +enum_specifier(register struct type **tpp;) + { + struct idf *idf; + arith l = (arith)0; + } +: + {if (*tpp) error("multiple types in declaration");} + ENUM + [ + {declare_struct(ENUM, (struct idf *) 0, tpp);} + enumerator_pack(*tpp, &l) + | + identifier(&idf) + [ + {declare_struct(ENUM, idf, tpp);} + enumerator_pack(*tpp, &l) + { +#ifdef DBSYMTAB + if (options['g']) { + stb_tag(idf->id_tag, idf->id_text); + } +#endif /*DBSYMTAB */ + } + | + {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; + } +: + {if (*tpp) error("multiple types in declaration");} + [ 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_tag->tg_busy)++; + } + struct_declaration_pack(*tpp) + { + (idf->id_tag->tg_busy)--; +#ifdef DBSYMTAB + if (options['g']) { + stb_tag(idf->id_tag, idf->id_text); + } +#endif /*DBSYMTAB */ + } + | + { + /* a ';' means an empty declaration (probably) + * this means that we have to declare a new + * structure. (yegh) + */ + if (DOT == ';' && + ( !idf->id_tag || + idf->id_tag->tg_level != level || + idf->id_tag->tg_type->tp_size < 0 + )) declare_struct(fund, idf, tpp); + else 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); + completed(stp); + } +; + +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; struct type *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); + if (pl) remove_proto_idfs(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);} +; + +%first first_of_parameter_type_list, parameter_type_list; + +primary_abstract_declarator(struct declarator *dc;) +: +[%if (AHEAD == ')' || first_of_parameter_type_list(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 = PL_ELLIPSIS; + *plp = new; + } + + ]? + { check_for_void(*plp); + if (level == L_PROTO) + level = save_level; + else level++; + } +; + +parameter_decl_list(struct proto **plp;) +: + parameter_decl(plp) + [ %while (AHEAD != ELLIPSIS) + %persistent + ',' 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; + remove_declarator(&Dc); + } +; + +/* 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 separately, 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) + parameter_type_list(&pl) + | + formal_list(&fm) + | + /* empty */ + ] + ')' + { add_decl_unary(dc, FUNCTION, 0, (arith)0, fm, pl); + reject_params(dc); + } + | + arrayer(&count) + {add_decl_unary(dc, ARRAY, 0, count, NO_PARAMS, NO_PROTO);} + ]* +| + 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 == ')' || first_of_parameter_type_list(AHEAD) + && (AHEAD != IDENTIFIER)) + /* 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. +*/ +/* 3.5.4 */ +type_qualifier_list(int *qual;) +: + { *qual = 0; } + [ + VOLATILE + { if (*qual & TQ_VOLATILE) + error("repeated type qualifier"); + *qual |= TQ_VOLATILE; + } + | + CONST + { if (*qual & TQ_CONST) + error("repeated type qualifier"); + *qual |= TQ_CONST; + } + ]* +; + +empty: +; diff --git a/lang/cem/cemcom.ansi/declar.str b/lang/cem/cemcom.ansi/declar.str index 884bd97e7..ebe1869bd 100644 --- a/lang/cem/cemcom.ansi/declar.str +++ b/lang/cem/cemcom.ansi/declar.str @@ -2,6 +2,9 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ + #ifndef DECLAR_H_ + #define DECLAR_H_ + /* $Id$ */ /* DEFINITION OF DECLARATOR DESCRIPTORS */ @@ -39,3 +42,5 @@ struct decl_unary { extern struct type *declare_type(); extern struct declarator null_declarator; + +#endif diff --git a/lang/cem/cemcom.ansi/declarator.c b/lang/cem/cemcom.ansi/declarator.c index 212b8aeb1..2795bda86 100644 --- a/lang/cem/cemcom.ansi/declarator.c +++ b/lang/cem/cemcom.ansi/declarator.c @@ -6,6 +6,7 @@ /* D E C L A R A T O R M A N I P U L A T I O N */ #include "parameters.h" +#include "declarator.h" #include #include #include "arith.h" @@ -14,18 +15,20 @@ #include "Lpars.h" #include "declar.h" #include "def.h" +#include "idf.h" #include "label.h" #include "expr.h" #include "sizes.h" #include "level.h" +#include "error.h" extern char options[]; struct declarator null_declarator; struct type * -declare_type(tp, dc) - struct type *tp; - struct declarator *dc; +declare_type( + 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. @@ -43,12 +46,7 @@ declare_type(tp, dc) 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; +void add_decl_unary(register struct declarator *dc, int fund, 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 @@ -75,8 +73,7 @@ add_decl_unary(dc, fund, qual, count, fm, pl) dc->dc_decl_unary = new; } -remove_declarator(dc) - struct declarator *dc; +void remove_declarator(struct declarator *dc) { /* The decl_unary list starting at dc->dc_decl_unary is removed. @@ -91,8 +88,7 @@ remove_declarator(dc) } } -reject_params(dc) - register struct declarator *dc; +void reject_params(register struct declarator *dc) { /* The declarator is checked to have no parameters, if it is an old-style function. If it is a new-style function, @@ -120,8 +116,7 @@ reject_params(dc) } } -check_array_subscript(expr) - register struct expr *expr; +void check_array_subscript(register struct expr *expr) { arith size = expr->VL_VALUE; diff --git a/lang/cem/cemcom.ansi/declarator.h b/lang/cem/cemcom.ansi/declarator.h new file mode 100644 index 000000000..abda9de1f --- /dev/null +++ b/lang/cem/cemcom.ansi/declarator.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef DECLARATOR_H_ +#define DECLARATOR_H_ + +#include "arith.h" + +/* Forward declarations. */ +struct type; +struct declarator; +struct formal; +struct proto; +struct expr; + +struct type * +declare_type(struct type *tp, struct declarator *dc); +void add_decl_unary(register struct declarator *dc, int fund, int qual, + arith count, struct formal *fm, struct proto *pl); +void remove_declarator(struct declarator *dc); +void reject_params(register struct declarator *dc); +void check_array_subscript(register struct expr *expr); + +#endif /* DECLARATOR_H_ */ diff --git a/lang/cem/cemcom.ansi/decspecs.c b/lang/cem/cemcom.ansi/decspecs.c index bef0c0d2b..42465e213 100644 --- a/lang/cem/cemcom.ansi/decspecs.c +++ b/lang/cem/cemcom.ansi/decspecs.c @@ -6,12 +6,13 @@ /* 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 -#include "Lpars.h" #include "decspecs.h" +#include "Lpars.h" #include "arith.h" #include "type.h" #include "level.h" #include "def.h" +#include "error.h" extern char options[]; extern int level; @@ -20,36 +21,35 @@ extern struct type *qualifier_type(); struct decspecs null_decspecs; -do_decspecs(ds) - register struct decspecs *ds; +void do_decspecs(register struct decspecs *ds) { /* The provisional decspecs ds as obtained from the program - is turned into a legal consistent decspecs. - */ + is turned into a legal consistent decspecs. + */ register struct type *tp = ds->ds_type; - + assert(level != L_FORMAL1); - - if ( level == L_GLOBAL && - (ds->ds_sc == AUTO || ds->ds_sc == REGISTER) - ) { - error("no global %s variable allowed", - symbol2str(ds->ds_sc)); + + if (level == L_GLOBAL && (ds->ds_sc == AUTO || ds->ds_sc == REGISTER)) + { + error("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){ + 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) { + 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)) @@ -58,49 +58,74 @@ do_decspecs(ds) } /* The tests concerning types require a full knowledge of the - type and will have to be postponed to declare_idf. - */ + type and will have to be postponed to declare_idf. + */ /* some adjustments as described in 3.5.2. */ - if (tp == 0) { + if (tp == 0) + { ds->ds_notypegiven = 1; tp = int_type; } - if (ds->ds_size) { + if (ds->ds_size) + { register int ds_isshort = (ds->ds_size == SHORT); - if (ds->ds_typedef) goto SIZE_ERROR; /* yes */ - if (tp == int_type) { - if (ds_isshort) tp = short_type; - else tp = long_type; - } else if (tp == double_type && !ds_isshort ) { + if (ds->ds_typedef) + goto SIZE_ERROR; + /* yes */ + if (tp == int_type) + { + if (ds_isshort) + tp = short_type; + else + tp = long_type; + } + else if (tp == double_type && !ds_isshort) + { tp = lngdbl_type; - } else { - SIZE_ERROR: - error("%s with illegal type",symbol2str(ds->ds_size)); + } + else + { + SIZE_ERROR: error("%s with illegal type", symbol2str(ds->ds_size)); } ds->ds_notypegiven = 0; } - if (ds->ds_unsigned) { + if (ds->ds_unsigned) + { register int ds_isunsigned = (ds->ds_unsigned == UNSIGNED); - if (ds->ds_typedef) goto SIGN_ERROR; /* yes */ + if (ds->ds_typedef) + goto SIGN_ERROR; + /* yes */ /* * All integral types are signed by default (char too), * so the case that ds->ds_unsigned == SIGNED can be ignored. */ - if (tp == schar_type) { - if (ds_isunsigned) tp = uchar_type; - } else if (tp == short_type) { - if (ds_isunsigned) tp = ushort_type; - } else if (tp == int_type) { - if (ds_isunsigned) tp = uint_type; - } else if (tp == long_type) { - if (ds_isunsigned) tp = ulong_type; - } else { - SIGN_ERROR: - error("%s with illegal type" - , symbol2str(ds->ds_unsigned)); + if (tp == schar_type) + { + if (ds_isunsigned) + tp = uchar_type; + } + else if (tp == short_type) + { + if (ds_isunsigned) + tp = ushort_type; + } + else if (tp == int_type) + { + if (ds_isunsigned) + tp = uint_type; + } + else if (tp == long_type) + { + if (ds_isunsigned) + tp = ulong_type; + } + else + { + SIGN_ERROR: error("%s with illegal type", + symbol2str(ds->ds_unsigned)); } ds->ds_notypegiven = 0; } @@ -108,15 +133,12 @@ do_decspecs(ds) } /* 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; + 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(register struct type *tp, int typequal) { register struct type *dtp = tp; register int fund = tp->tp_fund; @@ -124,32 +146,34 @@ qualifier_type(tp, typequal) while (dtp && dtp->tp_typequal != typequal) dtp = dtp->next; - if (!dtp) { + 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; #if 0 -/* The tp_function field does not exist now. See the comment in the - function_of() routine. -*/ + /* The tp_function field does not exist now. See the comment in the + function_of() routine. + */ dtp->tp_function = tp->tp_function; #endif - switch (fund) { + switch (fund) + { case ARRAY: - if (typequal) { - tp->tp_up = qualifier_type(tp->tp_up, typequal); - dtp->tp_typequal = typequal = 0; + if (typequal) + { + tp->tp_up = qualifier_type(tp->tp_up, typequal); + dtp->tp_typequal = typequal = 0; } goto nottagged; case FIELD: dtp->tp_field = tp->tp_field; /* fallthrough */ case POINTER: - case FUNCTION: /* dont't assign tp_proto */ - nottagged: - dtp->tp_up = tp->tp_up; + case FUNCTION: /* dont't assign tp_proto */ + nottagged: dtp->tp_up = tp->tp_up; break; case STRUCT: case UNION: @@ -163,6 +187,6 @@ qualifier_type(tp, typequal) dtp->next = tp->next; /* don't know head or tail */ tp->next = dtp; } - return(dtp); + return (dtp); } diff --git a/lang/cem/cemcom.ansi/decspecs.h b/lang/cem/cemcom.ansi/decspecs.h index 73a4048e2..7256b739d 100644 --- a/lang/cem/cemcom.ansi/decspecs.h +++ b/lang/cem/cemcom.ansi/decspecs.h @@ -2,6 +2,9 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef DECSPECS_H_ +#define DECSPECS_H_ + /* $Id$ */ /* DECLARATION SPECIFIER DEFINITION */ @@ -19,3 +22,10 @@ struct decspecs { extern struct type *qualifier_type(); extern struct decspecs null_decspecs; + +struct type; + +void do_decspecs(register struct decspecs *ds); +struct type *qualifier_type(register struct type *tp, int typequal); + +#endif diff --git a/lang/cem/cemcom.ansi/def.str b/lang/cem/cemcom.ansi/def.str index 0ad7af339..ad528a664 100644 --- a/lang/cem/cemcom.ansi/def.str +++ b/lang/cem/cemcom.ansi/def.str @@ -2,6 +2,9 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef DEF_H_ +#define DEF_H_ + /* $Id$ */ /* IDENTIFIER DEFINITION DESCRIPTOR */ @@ -38,3 +41,5 @@ struct def { /* for ordinary tags */ #define REG_BONUS 10 /* register candidate, declared as such */ /* ALLOCDEF "def" 50 */ + +#endif diff --git a/lang/cem/cemcom.ansi/domacro.c b/lang/cem/cemcom.ansi/domacro.c index d6fc4c501..dc77827ea 100644 --- a/lang/cem/cemcom.ansi/domacro.c +++ b/lang/cem/cemcom.ansi/domacro.c @@ -8,12 +8,17 @@ #include #include #include +#include "domacro.h" #include "parameters.h" #include "idf.h" +#include "interface.h" #include "arith.h" #include "LLlex.h" #include "Lpars.h" #include "input.h" +#include "pragma.h" +#include "skip.h" +#include "error.h" #ifdef DBSYMTAB #include @@ -23,7 +28,9 @@ int IncludeLevel = 0; extern char options[]; -struct idf* GetIdentifier(skiponerr) int skiponerr; /* skip the rest of the line on error */ +static void do_line(unsigned int); + +struct idf* GetIdentifier(int skiponerr) /* skip the rest of the line on error */ { /* returns a pointer to the descriptor of the identifier that is read from the input stream. When the input does not contain @@ -44,7 +51,7 @@ struct idf* GetIdentifier(skiponerr) int skiponerr; /* skip the rest of the line return tk.tk_idf; } -domacro() +void domacro(void) { int tok; struct token tk; @@ -70,7 +77,7 @@ domacro() SkipToNewLine(); } -do_line(l) unsigned int l; +static void do_line(unsigned int l) { struct token tk; int t = GetToken(&tk); diff --git a/lang/cem/cemcom.ansi/domacro.h b/lang/cem/cemcom.ansi/domacro.h new file mode 100644 index 000000000..75d6085a0 --- /dev/null +++ b/lang/cem/cemcom.ansi/domacro.h @@ -0,0 +1,16 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef DOMACRO_H_ +#define DOMACRO_H_ + +struct idf; + +struct idf* GetIdentifier(int skiponerr) ; +void domacro(void); + +#endif /* DOMACRO_H_ */ diff --git a/lang/cem/cemcom.ansi/error.c b/lang/cem/cemcom.ansi/error.c index 6f2283b74..76421ed80 100644 --- a/lang/cem/cemcom.ansi/error.c +++ b/lang/cem/cemcom.ansi/error.c @@ -6,6 +6,7 @@ /* 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 "parameters.h" +#include "error.h" #if __STDC__ #include #else @@ -17,13 +18,15 @@ #else #include "l_em.h" #endif /* LINT */ - +#include #include "tokenname.h" #include +#include "interface.h" #include "arith.h" #include "label.h" #include "expr.h" #include "def.h" +#include "print.h" #include "LLlex.h" /* This file contains the error-message and diagnostic @@ -56,12 +59,11 @@ extern char loptions[]; FileName, expression errors get their information from the expression, whereas other errors use the information in the token. */ - -static void _error(); +static void _error(int, char *, unsigned int, char*, va_list); #if __STDC__ /*VARARGS*/ -error(char *fmt, ...) +void error(char *fmt, ...) { va_list ap; @@ -73,7 +75,7 @@ error(char *fmt, ...) } /*VARARGS*/ -expr_error(struct expr *expr, char *fmt, ...) +void expr_error(struct expr *expr, char *fmt, ...) { va_list ap; @@ -89,7 +91,7 @@ expr_error(struct expr *expr, char *fmt, ...) } /*VARARGS*/ -lexstrict(char *fmt, ...) +void lexstrict(char *fmt, ...) { va_list ap; @@ -101,7 +103,7 @@ lexstrict(char *fmt, ...) } /*VARARGS*/ -strict(char *fmt, ...) +void strict(char *fmt, ...) { va_list ap; @@ -113,7 +115,7 @@ strict(char *fmt, ...) } /*VARARGS*/ -expr_strict(struct expr *expr, char *fmt, ...) +void expr_strict(struct expr *expr, char *fmt, ...) { va_list ap; @@ -129,7 +131,7 @@ expr_strict(struct expr *expr, char *fmt, ...) #ifdef DEBUG /*VARARGS*/ -debug(char *fmt, ...) +void debug(char *fmt, ...) { va_list ap; @@ -142,7 +144,7 @@ debug(char *fmt, ...) #endif /* DEBUG */ /*VARARGS*/ -warning(char *fmt, ...) +void warning(char *fmt, ...) { va_list ap; @@ -154,7 +156,7 @@ warning(char *fmt, ...) } /*VARARGS*/ -expr_warning(struct expr *expr, char *fmt, ...) +void expr_warning(struct expr *expr, char *fmt, ...) { va_list ap; @@ -171,7 +173,7 @@ expr_warning(struct expr *expr, char *fmt, ...) #ifdef LINT /*VARARGS*/ -def_warning(struct def *def, char *fmt, ...) +void def_warning(struct def *def, char *fmt, ...) { va_list ap; @@ -184,7 +186,7 @@ def_warning(struct def *def, char *fmt, ...) /*VARARGS*/ -hwarning(char *fmt, ...) +void hwarning(char *fmt, ...) { va_list ap; @@ -197,7 +199,7 @@ hwarning(char *fmt, ...) } /*VARARGS*/ -awarning(char *fmt, ...) +void awarning(char *fmt, ...) { va_list ap; @@ -212,7 +214,7 @@ awarning(char *fmt, ...) #endif /* LINT */ /*VARARGS*/ -lexerror(char *fmt, ...) +void lexerror(char *fmt, ...) { va_list ap; @@ -224,7 +226,7 @@ lexerror(char *fmt, ...) } /*VARARGS*/ -lexwarning(char *fmt, ...) +void lexwarning(char *fmt, ...) { va_list ap; @@ -236,7 +238,7 @@ lexwarning(char *fmt, ...) } /*VARARGS*/ -crash(char *fmt, ...) +void crash(char *fmt, ...) { va_list ap; @@ -256,7 +258,7 @@ crash(char *fmt, ...) } /*VARARGS*/ -fatal(char *fmt, ...) +void fatal(char *fmt, ...) { va_list ap; @@ -272,7 +274,7 @@ fatal(char *fmt, ...) } #else /*VARARGS*/ -error(va_alist) /* fmt, args */ +void error(va_alist) /* fmt, args */ va_dcl { va_list ap; @@ -286,7 +288,7 @@ error(va_alist) /* fmt, args */ } /*VARARGS*/ -expr_error(va_alist) /* expr, fmt, args */ +void expr_error(va_alist) /* expr, fmt, args */ va_dcl { va_list ap; @@ -306,7 +308,7 @@ expr_error(va_alist) /* expr, fmt, args */ } /*VARARGS*/ -lexstrict(va_alist) +void lexstrict(va_alist) va_dcl { va_list ap; @@ -320,7 +322,7 @@ lexstrict(va_alist) } /*VARARGS*/ -strict(va_alist) +void strict(va_alist) va_dcl { va_list ap; @@ -334,7 +336,7 @@ strict(va_alist) } /*VARARGS*/ -expr_strict(va_alist) /* expr, fmt, args */ +void expr_strict(va_alist) /* expr, fmt, args */ va_dcl { va_list ap; @@ -354,7 +356,7 @@ expr_strict(va_alist) /* expr, fmt, args */ #ifdef DEBUG /*VARARGS*/ -debug(va_alist) +void debug(va_alist) va_dcl { va_list ap; @@ -369,7 +371,7 @@ debug(va_alist) #endif /* DEBUG */ /*VARARGS*/ -warning(va_alist) +void warning(va_alist) va_dcl { va_list ap; @@ -383,7 +385,7 @@ warning(va_alist) } /*VARARGS*/ -expr_warning(va_alist) /* expr, fmt, args */ +void expr_warning(va_alist) /* expr, fmt, args */ va_dcl { va_list ap; @@ -404,7 +406,7 @@ expr_warning(va_alist) /* expr, fmt, args */ #ifdef LINT /*VARARGS*/ -def_warning(va_alist) /* def, fmt, args */ +void def_warning(va_alist) /* def, fmt, args */ va_dcl { va_list ap; @@ -421,7 +423,7 @@ def_warning(va_alist) /* def, fmt, args */ /*VARARGS*/ -hwarning(va_alist) /* fmt, args */ +void hwarning(va_alist) /* fmt, args */ va_dcl { va_list ap; @@ -436,7 +438,7 @@ hwarning(va_alist) /* fmt, args */ } /*VARARGS*/ -awarning(va_alist) /* fmt, args */ +void awarning(va_alist) /* fmt, args */ va_dcl { va_list ap; @@ -453,7 +455,7 @@ awarning(va_alist) /* fmt, args */ #endif /* LINT */ /*VARARGS*/ -lexerror(va_alist) /* fmt, args */ +void lexerror(va_alist) /* fmt, args */ va_dcl { va_list ap; @@ -467,7 +469,7 @@ lexerror(va_alist) /* fmt, args */ } /*VARARGS*/ -lexwarning(va_alist) /* fmt, args */ +void lexwarning(va_alist) /* fmt, args */ va_dcl { va_list ap; @@ -481,7 +483,7 @@ lexwarning(va_alist) /* fmt, args */ } /*VARARGS*/ -crash(va_alist) /* fmt, args */ +void crash(va_alist) /* fmt, args */ va_dcl { va_list ap; @@ -503,7 +505,7 @@ crash(va_alist) /* fmt, args */ } /*VARARGS*/ -fatal(va_alist) /* fmt, args */ +void fatal(va_alist) /* fmt, args */ va_dcl { va_list ap; @@ -521,13 +523,7 @@ fatal(va_alist) /* fmt, args */ } #endif -static void -_error(class, fn, ln, fmt, ap) - int class; - char *fn; - unsigned int ln; - char *fmt; - va_list ap; +static void _error(int class, char *fn, unsigned int ln, char* fmt, va_list ap) { char *remark; @@ -614,9 +610,9 @@ _error(class, fn, ln, fmt, ap) #endif /* LINT */ if (fn) - fprint(ERROUT, "\"%s\", line %u: ", fn, ln); + fprint(stderr, "\"%s\", line %u: ", fn, ln); if (remark) - fprint(ERROUT, "%s ", remark); - doprnt(ERROUT, fmt, ap); /* contents of error */ - fprint(ERROUT, "\n"); + fprint(stderr, "%s ", remark); + doprnt(stderr, fmt, ap); /* contents of error */ + fprint(stderr, "\n"); } diff --git a/lang/cem/cemcom.ansi/error.h b/lang/cem/cemcom.ansi/error.h new file mode 100644 index 000000000..595cd2aba --- /dev/null +++ b/lang/cem/cemcom.ansi/error.h @@ -0,0 +1,94 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef ERROR_H_ +#define ERROR_H_ + +struct expr; + +#if __STDC__ +/*VARARGS*/ +void error(char *fmt, ...); +/*VARARGS*/ +void expr_error(struct expr *expr, char *fmt, ...); +/*VARARGS*/ +void lexstrict(char *fmt, ...); +/*VARARGS*/ +void strict(char *fmt, ...); +/*VARARGS*/ +void expr_strict(struct expr *expr, char *fmt, ...); + +#ifdef DEBUG +/*VARARGS*/ +void debug(char *fmt, ...); +#endif /* DEBUG */ + +/*VARARGS*/ +void warning(char *fmt, ...); +/*VARARGS*/ +void expr_warning(struct expr *expr, char *fmt, ...); +#ifdef LINT +/*VARARGS*/ +void def_warning(struct def *def, char *fmt, ...); +/*VARARGS*/ +void hwarning(char *fmt, ...); +/*VARARGS*/ +void awarning(char *fmt, ...); +#endif /* LINT */ + +/*VARARGS*/ +void lexerror(char *fmt, ...); +/*VARARGS*/ +void lexwarning(char *fmt, ...); +/*VARARGS*/ +void crash(char *fmt, ...); +/*VARARGS*/ +void fatal(char *fmt, ...); + +#else +/*VARARGS*/ +void error(va_alist); /* fmt, args */ +/*VARARGS*/ +void expr_error(va_alist); /* expr, fmt, args */ +/*VARARGS*/ +void lexstrict(va_alist); +/*VARARGS*/ +void strict(va_alist); +/*VARARGS*/ +void expr_strict(va_alist); /* expr, fmt, args */ +#ifdef DEBUG +/*VARARGS*/ +void debug(va_alist); +#endif /* DEBUG */ + +/*VARARGS*/ +void warning(va_alist); +/*VARARGS*/ +void expr_warning(va_alist); /* expr, fmt, args */ +#ifdef LINT + +/*VARARGS*/ +void def_warning(va_alist); /* def, fmt, args */ +/*VARARGS*/ +void hwarning(va_alist); /* fmt, args */ +/*VARARGS*/ +void awarning(va_alist); /* fmt, args */ +#endif /* LINT */ + +/*VARARGS*/ +void lexerror(va_alist); /* fmt, args */ +/*VARARGS*/ +void lexwarning(va_alist); /* fmt, args */ +/*VARARGS*/ +void crash(va_alist); /* fmt, args */ +/*VARARGS*/ +void fatal(va_alist); /* fmt, args */ +#endif + + + +#endif /* ERROR_H_ */ diff --git a/lang/cem/cemcom.ansi/estack.str b/lang/cem/cemcom.ansi/estack.str index b65629ed6..0718cca64 100644 --- a/lang/cem/cemcom.ansi/estack.str +++ b/lang/cem/cemcom.ansi/estack.str @@ -2,6 +2,9 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ + #ifndef ESTACK_H_ + #define ESTACK_H_ + /* $Id$ */ /* EXPRESSION STACK */ /* Used for global initializations */ @@ -19,3 +22,5 @@ struct e_stack { #define last_offset s_cnt2 #define elem_count s_cnt1 #define nelem s_cnt2 + +#endif \ No newline at end of file diff --git a/lang/cem/cemcom.ansi/eval.c b/lang/cem/cemcom.ansi/eval.c index 0ec25dac6..352d590b3 100644 --- a/lang/cem/cemcom.ansi/eval.c +++ b/lang/cem/cemcom.ansi/eval.c @@ -14,6 +14,8 @@ #include #include #include +#include "interface.h" +#include "eval.h" #include "idf.h" #include "arith.h" #include "type.h" @@ -22,13 +24,21 @@ #include "def.h" #include "expr.h" #include "sizes.h" +#include "field.h" #include "Lpars.h" #include "level.h" +#include "conversion.h" #include "stack.h" +#include "struct.h" #include "align.h" #include "mes.h" #include "atw.h" +#include "ch3.h" +#include "util.h" +#include "blocks.h" +#include "dataflow.h" #include "specials.h" +#include "error.h" #define CRASH() crash("EVAL: CRASH at line %u", __LINE__) @@ -37,8 +47,12 @@ arith NewLocal(); /* util.c */ #define LocalPtrVar() NewLocal(pointer_size, pointer_align, reg_pointer, REGISTER) extern int err_occurred; /* error.c */ -void store_val(); -void load_val(); + +/* Forward internal declarations */ +static void operands(register struct expr *, int); +static void ptr_add(arith size); +static void truthvalue(int relop); +static void compare(int relop, label lbl); /* EVAL() is the main expression-tree evaluator, which turns any legal expression tree into EM code. parameters.h: @@ -66,11 +80,7 @@ void load_val(); labels, in case they are specified (i.e. are non-zero) */ -void -EVAL(expr, val, code, true_label, false_label) - register struct expr *expr; - int val, code; - label true_label, false_label; +void EVAL(register struct expr *expr, int val, int code, label true_label, label false_label) { int vol = (code != TRUE && recurqual(expr->ex_type, TQ_VOLATILE)); register int gencode = code == TRUE; @@ -659,9 +669,7 @@ EVAL(expr, val, code, true_label, false_label) } /* compare() serves as an auxiliary function of EVAL */ -compare(relop, lbl) - int relop; - label lbl; +static void compare(int relop, label lbl) { switch (relop) { case '<': @@ -688,8 +696,7 @@ compare(relop, lbl) } /* truthvalue() serves as an auxiliary function of EVAL */ -truthvalue(relop) - int relop; +static void truthvalue(int relop) { switch (relop) { case '<': @@ -717,12 +724,10 @@ truthvalue(relop) /* assop() generates the opcode of an assignment operators op= */ -assop(type, oper) - register struct type *type; - int oper; +void assop(register struct type *type, int oper) { register arith size; - register uns = type->tp_unsigned; + register int uns = type->tp_unsigned; if ((int)(size = type->tp_size) < (int)word_size) size = word_size; @@ -822,8 +827,7 @@ assop(type, oper) } } -ptr_add(size) - arith size; +static void ptr_add(arith size) { if (size != pointer_size) { C_loc(size); @@ -840,10 +844,7 @@ ptr_add(size) - into a local static variable - absolute addressing */ -void -store_val(vl, tp) - register struct value *vl; - register struct type *tp; +void store_val(register struct value *vl, register struct type *tp) { register int inword = 0; register int indword = 0; @@ -911,11 +912,10 @@ store_val(vl, tp) - global variable - static variable - local variable + + rlval generate rlval or lval */ -void -load_val(expr, rlval) - register struct expr *expr; /* expression containing the value */ - int rlval; /* generate either LVAL or RVAL */ +void load_val(register struct expr *expr, int rlval) { register struct type *tp = expr->ex_type; int rvalue = (rlval == RVAL && expr->ex_lvalue != 0); @@ -1012,8 +1012,7 @@ load_val(expr, rlval) } } -load_cst(val, siz) - arith val, siz; +void load_cst(arith val, arith siz) { if ((int)siz <= (int)word_size) C_loc(val); @@ -1030,8 +1029,7 @@ load_cst(val, siz) } } -operands(expr, gencode) - register struct expr *expr; +static void operands(register struct expr *expr, int gencode) { EVAL(expr->OP_LEFT, RVAL, gencode, NO_LABEL, NO_LABEL); EVAL(expr->OP_RIGHT, RVAL, gencode, NO_LABEL, NO_LABEL); diff --git a/lang/cem/cemcom.ansi/eval.h b/lang/cem/cemcom.ansi/eval.h new file mode 100644 index 000000000..337b5ac57 --- /dev/null +++ b/lang/cem/cemcom.ansi/eval.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-06 + * + */ +#ifndef EVAL_H_ +#define EVAL_H_ + +#ifndef LINT + + +#include + +struct expr; +struct value; +struct type; + +void EVAL(register struct expr *expr, int val, int code, label true_label, label false_label); + +/* assop() generates the opcode of an assignment operators op= */ +void assop(register struct type *type, int oper); +/* 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 +*/ +void store_val(register struct value *vl, register struct type *tp); +void load_val(register struct expr *expr, int rlval); +void load_cst(arith val, arith siz); + +#endif /* LINT */ + +#endif /* EVAL_H_ */ diff --git a/lang/cem/cemcom.ansi/expr.c b/lang/cem/cemcom.ansi/expr.c index 7b686c3fe..b24c408d0 100644 --- a/lang/cem/cemcom.ansi/expr.c +++ b/lang/cem/cemcom.ansi/expr.c @@ -10,6 +10,7 @@ #include "parameters.h" #include #include +#include "expr.h" #include "idf.h" #include "arith.h" #include "def.h" @@ -22,20 +23,21 @@ #include "declar.h" #include "sizes.h" #include "level.h" +#include "cstoper.h" +#include "error.h" extern char *symbol2str(); extern char options[]; extern int InSizeof; -int -rank_of(oper) - int oper; +int rank_of(int oper) { /* The rank of the operator oper is returned. - */ - switch (oper) { + */ + switch (oper) + { default: - return 0; /* INT2INT etc. */ + return 0; /* INT2INT etc. */ case '[': case '(': case '.': @@ -48,7 +50,7 @@ rank_of(oper) case CAST: case SIZEOF: case ADDRESSOF: - return 2; /* monadic */ + return 2; /* monadic */ case '*': case '/': case '%': @@ -98,18 +100,18 @@ rank_of(oper) /*NOTREACHED*/ } -dot2expr(expp) - struct expr **expp; +void dot2expr(struct expr **expp) { /* The token in dot is converted into an expression, a - pointer to which is stored in *expp. - */ + 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) { + switch (DOT) + { case IDENTIFIER: idf2expr(ex); break; @@ -125,25 +127,27 @@ dot2expr(expp) } } -idf2expr(expr) - register struct expr *expr; +void idf2expr(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*/ + 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 == '(') { + + if (def == 0) + { + if (AHEAD == '(') + { /* function call, declare name implicitly (3.3.2.2) */ if (!options['o']) - warning("implicit declaration of function %s" - , idf->id_text); + warning("implicit declaration of function %s", idf->id_text); add_def(idf, EXTERN, funint_type, level); - } else { + } + else + { if (!is_anon_idf(idf)) error("%s undefined", idf->id_text); /* declare idf anyway */ @@ -153,8 +157,10 @@ idf2expr(expr) } /* now def != 0 */ #ifndef LINT - if (!InSizeof) { - if (! def->df_used) { + if (!InSizeof) + { + if (!def->df_used) + { #ifndef PREPEND_SCOPES code_scope(idf->id_text, def); #endif /* PREPEND_SCOPES */ @@ -163,46 +169,45 @@ idf2expr(expr) } #endif /* LINT */ expr->ex_type = def->df_type; - if (expr->ex_type == error_type) { + if (expr->ex_type == error_type) + { expr->ex_flags |= EX_ERROR; } expr->ex_lvalue = - ( def->df_type->tp_fund == FUNCTION || - def->df_type->tp_fund == ARRAY || - def->df_sc == ENUM - ) ? 0 : 1; + (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) { + 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) { + 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; + expr->VL_VALUE = (arith) 0; } #endif /* LINT */ - else { + else + { expr->VL_CLASS = Name; expr->VL_IDF = idf; - expr->VL_VALUE = (arith)0; + expr->VL_VALUE = (arith) 0; } } -string2expr(expp, str, len) - register struct expr **expp; - int len; - char *str; +void string2expr(register struct expr **expp, char *str, int len) + { /* The string in the argument is converted into an expression, - a pointer to which is stored in *expp. - */ + a pointer to which is stored in *expp. + */ register struct expr *ex = new_expr(); *expp = ex; @@ -217,25 +222,24 @@ string2expr(expp, str, len) ex->SG_LEN = len; } -int2expr(expr) - struct expr *expr; +void int2expr(struct expr *expr) { /* Dot contains an integer constant which is turned - into an expression. - */ + into an expression. + */ fill_int_expr(expr, dot.tk_ival, dot.tk_fund); } -float2expr(expr) - register struct expr *expr; +void float2expr(register struct expr *expr) { /* Dot contains a floating point constant which is turned - into an expression. - */ + into an expression. + */ register int fund; fund = dot.tk_fund; - switch (fund) { + switch (fund) + { case FLOAT: expr->ex_type = float_type; break; @@ -253,17 +257,15 @@ float2expr(expr) free(dot.tk_fval); assert(flt_status != FLT_NOFLT); if (flt_status == FLT_OVFL) - expr_warning(expr,"internal floating point overflow"); + expr_warning(expr, "internal floating point overflow"); } -struct expr* -intexpr(ivalue, fund) - arith ivalue; - int fund; +struct expr*intexpr( +arith ivalue, int fund) { /* The value ivalue is turned into an integer expression of - the size indicated by fund. - */ + the size indicated by fund. + */ register struct expr *expr = new_expr(); expr->ex_file = dot.tk_file; @@ -272,15 +274,14 @@ intexpr(ivalue, fund) return expr; } -fill_int_expr(ex, ivalue, fund) - register struct expr *ex; - arith ivalue; - int fund; +void fill_int_expr(register struct expr *ex, +arith ivalue, int fund) { /* Details derived from ivalue and fund are put into the - constant integer expression ex. - */ - switch (fund) { + constant integer expression ex. + */ + switch (fund) + { case INT: ex->ex_type = int_type; break; @@ -288,7 +289,7 @@ fill_int_expr(ex, ivalue, fund) ex->ex_type = uint_type; break; case LONG: - ex->ex_type = long_type; + ex->ex_type = long_type; break; case ULONG: ex->ex_type = ulong_type; @@ -303,38 +304,38 @@ fill_int_expr(ex, ivalue, fund) cut_size(ex); } -struct expr * -new_oper(tp, e1, oper, e2) - struct type *tp; - register struct expr *e1, *e2; +struct expr *new_oper(struct type *tp, register struct expr *e1, int oper, + register struct expr *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. - */ + 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) { + 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) { + 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 { + else + { expr->ex_file = dot.tk_file; expr->ex_line = dot.tk_line; } @@ -342,20 +343,22 @@ new_oper(tp, e1, oper, e2) expr->ex_type = tp; expr->ex_class = Oper; /* combine depths and flags of both expressions */ - if (e2) { + 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_depth = (e1_depth > e2->ex_depth ? e1_depth : e2->ex_depth) + + 1; expr->ex_flags = (e1_flags | e2->ex_flags) - & ~(EX_PARENS | EX_READONLY | EX_VOLATILE ); + & ~(EX_PARENS | EX_READONLY | EX_VOLATILE); } /* * A function call should be evaluated first when possible. Just say * that the expression tree is very deep. */ - if (oper == '(') { + if (oper == '(') + { expr->ex_depth = 50; } op = &expr->ex_object.ex_oper; @@ -369,42 +372,42 @@ new_oper(tp, e1, oper, e2) return expr; } -void -chk_cst_expr(expp) - struct expr **expp; +void chk_cst_expr(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. - - Special problems (of which there is only one, sizeof in - Preprocessor #if) have to be dealt with locally - */ + + 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. + + Special problems (of which there is only one, sizeof in + Preprocessor #if) have to be dealt with locally + */ register struct expr *expr = *expp; - + #ifdef DEBUG print_expr("constant_expression", expr); #endif /* DEBUG */ - switch(expr->ex_type->tp_fund) { + switch (expr->ex_type->tp_fund) + { case CHAR: case SHORT: case INT: case ENUM: case LONG: - if (is_ld_cst(expr)) { + if (is_ld_cst(expr)) + { return; } expr_error(expr, "expression is not constant"); @@ -416,67 +419,58 @@ chk_cst_expr(expp) erroneous2int(expp); } -init_expression(eppp, expr) - register struct expr ***eppp; - struct expr *expr; +void init_expression(register struct expr ***eppp, struct expr *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. - */ + 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; +int is_ld_cst(register struct expr *expr) { /* An expression is a `load-time constant' if it is of the form - +/- or . - */ + +/- or . + */ #ifdef LINT if (expr->ex_class == String) - return 1; + return 1; #endif /* LINT */ return expr->ex_lvalue == 0 && expr->ex_class == Value; } -int -is_cp_cst(expr) - struct expr *expr; +int is_cp_cst(struct expr *expr) { /* An expression is a `compile-time constant' if it is a - load-time constant, and the idf is not there. - */ + load-time constant, and the idf is not there. + */ return is_ld_cst(expr) && expr->VL_CLASS == Const; } -int -is_fp_cst(expr) - struct expr *expr; +int is_fp_cst(struct expr *expr) { /* An expression is a `floating-point constant' if it consists - of the float only. - */ + of the float only. + */ return expr->ex_class == Float; } -int -is_zero_cst(expr) - register struct expr *expr; +int is_zero_cst(register struct expr *expr) { flt_arith var; - switch(expr->ex_class) { + switch (expr->ex_class) + { case Value: return expr->VL_VALUE == 0; case Float: @@ -486,13 +480,14 @@ is_zero_cst(expr) /*NOTREACHED*/ } -free_expression(expr) - register struct expr *expr; +void free_expression(register struct expr *expr) { /* The expression expr is freed recursively. - */ - if (expr) { - if (expr->ex_class == Oper) { + */ + if (expr) + { + if (expr->ex_class == Oper) + { free_expression(expr->OP_LEFT); free_expression(expr->OP_RIGHT); } diff --git a/lang/cem/cemcom.ansi/expr.str b/lang/cem/cemcom.ansi/expr.str index b341524ed..97ac5b1f9 100644 --- a/lang/cem/cemcom.ansi/expr.str +++ b/lang/cem/cemcom.ansi/expr.str @@ -4,6 +4,13 @@ */ /* $Id$ */ /* EXPRESSION DESCRIPTOR */ +#ifndef EXPR_H_ +#define EXPR_H_ + +#include "parameters.h" +#include "arith.h" +#include "label.h" +#include "flt_arith.h" /* 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. @@ -97,3 +104,24 @@ extern struct expr *intexpr(), *new_oper(); /* ALLOCDEF "expr" 20 */ + + +int rank_of(int oper); +void dot2expr(struct expr **expp); +void idf2expr(register struct expr *expr); +void string2expr(register struct expr **expp, char *str, int len); +void int2expr(struct expr *expr); +void float2expr(register struct expr *expr); +struct expr* intexpr(arith ivalue, int fund); +void fill_int_expr(register struct expr *ex,arith ivalue, int fund); +struct expr *new_oper(struct type *tp, register struct expr *e1, int oper, + register struct expr *e2); +void chk_cst_expr(struct expr **expp); +void init_expression(register struct expr ***eppp, struct expr *expr); +int is_ld_cst(register struct expr *expr); +int is_cp_cst(struct expr *expr); +int is_fp_cst(struct expr *expr); +int is_zero_cst(register struct expr *expr); +void free_expression(register struct expr *expr); + +#endif \ No newline at end of file diff --git a/lang/cem/cemcom.ansi/expression.g b/lang/cem/cemcom.ansi/expression.g index 3a1284e69..0998883c1 100644 --- a/lang/cem/cemcom.ansi/expression.g +++ b/lang/cem/cemcom.ansi/expression.g @@ -1,349 +1,354 @@ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -/* $Id$ */ -/* EXPRESSION SYNTAX PARSER */ - -{ -#include -#include "parameters.h" -#include -#include "arith.h" -#include "LLlex.h" -#include "type.h" -#include "label.h" -#include "expr.h" -#include "code.h" -#include "sizes.h" - -extern struct expr *intexpr(); -int InSizeof = 0; /* inside a sizeof- expression */ -int ResultKnown = 0; /* result of the expression is already known */ - -/* Since the grammar in the standard is not LL(n), it is modified so that - * it accepts basically the same grammar. This means that there is no 1-1 - * mapping from the grammar in the standard to the grammar given here. - * Such is life. - */ -} - -/* 3.3.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 = Realloc(str, (unsigned) (--len + dot.tk_len)); - for (i = 0; i < dot.tk_len; i++) - str[len++] = dot.tk_bts[i]; - } - ]* - { string2expr(expp, str, len); } -; - -/* 3.3.2 */ -postfix_expression(register struct expr **expp;) - { int oper; - struct expr *e1 = 0; - struct idf *idf; - } -: - primary(expp) - [ - '[' expression(&e1) ']' - { ch3bin(expp, '[', e1); e1 = 0; } - | - '(' parameter_list(&e1)? ')' - { ch3bin(expp, '(', e1); call_proto(expp); e1 = 0; } - | - [ '.' | ARROW ] { oper = DOT; } - identifier(&idf) { ch3sel(expp, oper, idf); } - | - [ - PLUSPLUS { oper = POSTINCR; } - | - MINMIN { oper = POSTDECR; } - ] - { ch3incr(expp, oper); } - ]* -; - -parameter_list(struct expr **expp;) - {struct expr *e1 = 0;} -: - assignment_expression(expp) - {any2opnd(expp, PARCOMMA);} - [ %persistent - ',' - assignment_expression(&e1) - {any2opnd(&e1, PARCOMMA);} - {ch3bin(expp, PARCOMMA, e1);} - ]* -; - -%first first_of_type_specifier, type_specifier; - -/* 3.3.3 & 3.3.4 */ -unary(register struct expr **expp;) - {struct type *tp; int oper;} -: -%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER) - cast(&tp) unary(expp) - { ch3cast(expp, CAST, tp); - (*expp)->ex_flags |= EX_CAST; - if (int_size != pointer_size) - (*expp)->ex_flags &= ~EX_PTRDIFF; - } -| - postfix_expression(expp) -| - unop(&oper) unary(expp) - {ch3mon(oper, expp);} -| - size_of(expp) -; - -/* When an identifier is used in a sizeof()-expression, we must stil not - * mark it as used. - * extern int i; .... sizeof(i) .... need not have a definition for i - */ -size_of(register struct expr **expp;) - {struct type *tp;} -: - SIZEOF { InSizeof++; } /* handle (sizeof(sizeof(int))) too */ - [%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER) - cast(&tp) - { - *expp = intexpr(size_of_type(tp, "type"), UNSIGNED); - (*expp)->ex_flags |= EX_SIZEOF; - } - | - unary(expp) - {ch3mon(SIZEOF, expp);} - ] - { InSizeof--; } -; - -/* 3.3.5-3.3.17 */ -/* The set of operators in C is stratified in 15 levels, with level - N being treated in RM 7.N (although this is not the standard - anymore). The standard describes this in phrase-structure-grammar, - which we are unable to parse. The description that follows comes - from the old C-compiler. - - In principle each operator is assigned a rank, ranging - from 1 to 15. Such an expression can be parsed by a construct - like: - binary_expression(int maxrank;) - {int oper;} - : - binary_expression(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, OldResultKnown; struct expr *e1;} -: - unary(expp) - [%while (rank_of(DOT) <= maxrank ) - /* '?', '=', and ',' are no binops - */ - binop(&oper) - { OldResultKnown = ResultKnown; - if (oper == OR || oper == AND) { - if (is_cp_cst(*expp) || is_fp_cst(*expp)) { - if (is_zero_cst(*expp)) { - if (oper == AND) ResultKnown++; - } else if (oper == OR) ResultKnown++; - } - } - } - binary_expression(rank_of(oper)-1, &e1) - { - ch3bin(expp, oper, e1); - ResultKnown = OldResultKnown; - } - ]* -; - -/* 3.3.15 */ -conditional_expression(struct expr **expp;) - {struct expr *e1 = 0, *e2 = 0; int OldResultKnown, ConstExpr=0;} -: - /* allow all binary operators */ - binary_expression(rank_of('?') - 1, expp) - [ '?' - { OldResultKnown = ResultKnown; - if (is_cp_cst(*expp) || is_fp_cst(*expp)) { - ConstExpr++; - if (is_zero_cst(*expp)) ResultKnown++; - } - } - expression(&e1) - ':' - { if (ConstExpr) { - if (OldResultKnown == ResultKnown) ResultKnown++; - else ResultKnown = OldResultKnown; - } - } - conditional_expression(&e2) - { - ResultKnown = OldResultKnown; - ch3bin(&e1, ':', e2); - opnd2test(expp, '?'); - ch3bin(expp, '?', e1); - } - ]? -; - -/* 3.3.16 */ -assignment_expression(struct expr **expp;) - { int oper; - struct expr *e1 = 0; - } -: - conditional_expression(expp) - [ - asgnop(&oper) - assignment_expression(&e1) - {ch3asgn(expp, oper, e1);} - | - empty /* LLgen artefact ??? */ - ] -; - -/* 3.3.17 */ -expression(struct expr **expp;) - {struct expr *e1;} -: - assignment_expression(expp) - [ ',' - assignment_expression(&e1) - { - ch3bin(expp, ',', e1); - } - ]* -; - -unop(int *oper;) : - ['*' | '&' | '-' | '+' | '!' | '~' | PLUSPLUS | MINMIN] - { if (DOT == '&') DOT = ADDRESSOF; - *oper = DOT; - } -; - -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;): - [ '=' | PLUSAB | MINAB | TIMESAB | DIVAB | MODAB - | LEFTAB | RIGHTAB | ANDAB | XORAB | ORAB ] - { *oper = DOT; } - -; - -constant(struct expr **expp;) : -[ - INTEGER -| - FLOATING -] {dot2expr(expp);} -; - -/* 3.4 */ -constant_expression (struct expr **expp;) : - conditional_expression(expp) - { chk_cst_expr(expp); } -; - -identifier(struct idf **idfp;) : -[ IDENTIFIER -| TYPE_IDENTIFIER -] - { *idfp = dot.tk_idf; } -; +/* + * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ +/* $Id$ */ +/* EXPRESSION SYNTAX PARSER */ + +{ +#include +#include "parameters.h" +#include +#include "arith.h" +#include "LLlex.h" +#include "type.h" +#include "label.h" +#include "expr.h" +#include "code.h" +#include "error.h" +#include "ch3.h" +#include "ch3bin.h" +#include "ch3mon.h" +#include "proto.h" +#include "sizes.h" + +extern struct expr *intexpr(); +int InSizeof = 0; /* inside a sizeof- expression */ +int ResultKnown = 0; /* result of the expression is already known */ + +/* Since the grammar in the standard is not LL(n), it is modified so that + * it accepts basically the same grammar. This means that there is no 1-1 + * mapping from the grammar in the standard to the grammar given here. + * Such is life. + */ +} + +/* 3.3.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 = Realloc(str, (unsigned) (--len + dot.tk_len)); + for (i = 0; i < dot.tk_len; i++) + str[len++] = dot.tk_bts[i]; + } + ]* + { string2expr(expp, str, len); } +; + +/* 3.3.2 */ +postfix_expression(register struct expr **expp;) + { int oper; + struct expr *e1 = 0; + struct idf *idf; + } +: + primary(expp) + [ + '[' expression(&e1) ']' + { ch3bin(expp, '[', e1); e1 = 0; } + | + '(' parameter_list(&e1)? ')' + { ch3bin(expp, '(', e1); call_proto(expp); e1 = 0; } + | + [ '.' | ARROW ] { oper = DOT; } + identifier(&idf) { ch3sel(expp, oper, idf); } + | + [ + PLUSPLUS { oper = POSTINCR; } + | + MINMIN { oper = POSTDECR; } + ] + { ch3incr(expp, oper); } + ]* +; + +parameter_list(struct expr **expp;) + {struct expr *e1 = 0;} +: + assignment_expression(expp) + {any2opnd(expp, PARCOMMA);} + [ %persistent + ',' + assignment_expression(&e1) + {any2opnd(&e1, PARCOMMA);} + {ch3bin(expp, PARCOMMA, e1);} + ]* +; + +%first first_of_type_specifier, type_specifier; + +/* 3.3.3 & 3.3.4 */ +unary(register struct expr **expp;) + {struct type *tp; int oper;} +: +%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER) + cast(&tp) unary(expp) + { ch3cast(expp, CAST, tp); + (*expp)->ex_flags |= EX_CAST; + if (int_size != pointer_size) + (*expp)->ex_flags &= ~EX_PTRDIFF; + } +| + postfix_expression(expp) +| + unop(&oper) unary(expp) + {ch3mon(oper, expp);} +| + size_of(expp) +; + +/* When an identifier is used in a sizeof()-expression, we must stil not + * mark it as used. + * extern int i; .... sizeof(i) .... need not have a definition for i + */ +size_of(register struct expr **expp;) + {struct type *tp;} +: + SIZEOF { InSizeof++; } /* handle (sizeof(sizeof(int))) too */ + [%if (first_of_type_specifier(AHEAD) && AHEAD != IDENTIFIER) + cast(&tp) + { + *expp = intexpr(size_of_type(tp, "type"), UNSIGNED); + (*expp)->ex_flags |= EX_SIZEOF; + } + | + unary(expp) + {ch3mon(SIZEOF, expp);} + ] + { InSizeof--; } +; + +/* 3.3.5-3.3.17 */ +/* The set of operators in C is stratified in 15 levels, with level + N being treated in RM 7.N (although this is not the standard + anymore). The standard describes this in phrase-structure-grammar, + which we are unable to parse. The description that follows comes + from the old C-compiler. + + In principle each operator is assigned a rank, ranging + from 1 to 15. Such an expression can be parsed by a construct + like: + binary_expression(int maxrank;) + {int oper;} + : + binary_expression(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, OldResultKnown; struct expr *e1;} +: + unary(expp) + [%while (rank_of(DOT) <= maxrank ) + /* '?', '=', and ',' are no binops + */ + binop(&oper) + { OldResultKnown = ResultKnown; + if (oper == OR || oper == AND) { + if (is_cp_cst(*expp) || is_fp_cst(*expp)) { + if (is_zero_cst(*expp)) { + if (oper == AND) ResultKnown++; + } else if (oper == OR) ResultKnown++; + } + } + } + binary_expression(rank_of(oper)-1, &e1) + { + ch3bin(expp, oper, e1); + ResultKnown = OldResultKnown; + } + ]* +; + +/* 3.3.15 */ +conditional_expression(struct expr **expp;) + {struct expr *e1 = 0, *e2 = 0; int OldResultKnown, ConstExpr=0;} +: + /* allow all binary operators */ + binary_expression(rank_of('?') - 1, expp) + [ '?' + { OldResultKnown = ResultKnown; + if (is_cp_cst(*expp) || is_fp_cst(*expp)) { + ConstExpr++; + if (is_zero_cst(*expp)) ResultKnown++; + } + } + expression(&e1) + ':' + { if (ConstExpr) { + if (OldResultKnown == ResultKnown) ResultKnown++; + else ResultKnown = OldResultKnown; + } + } + conditional_expression(&e2) + { + ResultKnown = OldResultKnown; + ch3bin(&e1, ':', e2); + opnd2test(expp, '?'); + ch3bin(expp, '?', e1); + } + ]? +; + +/* 3.3.16 */ +assignment_expression(struct expr **expp;) + { int oper; + struct expr *e1 = 0; + } +: + conditional_expression(expp) + [ + asgnop(&oper) + assignment_expression(&e1) + {ch3asgn(expp, oper, e1);} + | + empty /* LLgen artefact ??? */ + ] +; + +/* 3.3.17 */ +expression(struct expr **expp;) + {struct expr *e1;} +: + assignment_expression(expp) + [ ',' + assignment_expression(&e1) + { + ch3bin(expp, ',', e1); + } + ]* +; + +unop(int *oper;) : + ['*' | '&' | '-' | '+' | '!' | '~' | PLUSPLUS | MINMIN] + { if (DOT == '&') DOT = ADDRESSOF; + *oper = DOT; + } +; + +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;): + [ '=' | PLUSAB | MINAB | TIMESAB | DIVAB | MODAB + | LEFTAB | RIGHTAB | ANDAB | XORAB | ORAB ] + { *oper = DOT; } + +; + +constant(struct expr **expp;) : +[ + INTEGER +| + FLOATING +] {dot2expr(expp);} +; + +/* 3.4 */ +constant_expression (struct expr **expp;) : + conditional_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 index f5635d1fe..d1b014c01 100644 --- a/lang/cem/cemcom.ansi/field.c +++ b/lang/cem/cemcom.ansi/field.c @@ -23,8 +23,11 @@ #include "align.h" #include "Lpars.h" #include "field.h" +#include "util.h" +#include "conversion.h" +#include "eval.h" + -arith NewLocal(); /* util.c */ extern arith full_mask[]; /* cstoper.c */ /* Eval_field() evaluates expressions involving bit fields. @@ -39,9 +42,9 @@ extern arith full_mask[]; /* cstoper.c */ [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; +void eval_field( + struct expr *expr, + int code) { int op = expr->OP_OPER; register struct expr *leftop = expr->OP_LEFT; @@ -126,12 +129,12 @@ eval_field(expr, code) } } -store_field(fd, uns, code, leftop, tmpvar) - register struct field *fd; - int uns; - int code; - register struct expr *leftop; - arith tmpvar; +void store_field( + register struct field *fd, + int uns, + int code, + register struct expr *leftop, + arith tmpvar) { C_loc(fd->fd_mask); C_and(word_size); diff --git a/lang/cem/cemcom.ansi/field.str b/lang/cem/cemcom.ansi/field.str index 7b4f219a1..2c8635c43 100644 --- a/lang/cem/cemcom.ansi/field.str +++ b/lang/cem/cemcom.ansi/field.str @@ -2,6 +2,11 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef FIELD_H_ +#define FIELD_H_ + +#include "arith.h" + /* $Id$ */ /* FIELD DESCRIPTOR */ @@ -13,3 +18,20 @@ struct field { /* for field specifiers */ }; /* ALLOCDEF "field" 10 */ + +#ifndef LINT + + +#ifndef NOBITFIELD + +struct expr; + +void store_field(register struct field *fd, int uns, int code, + register struct expr *leftop, arith tmpvar); +void eval_field(struct expr *expr, int code); + +#endif /* NOBITFIELD */ + +#endif /* LINT */ + +#endif /* FIELD_H_ */ \ No newline at end of file diff --git a/lang/cem/cemcom.ansi/fltcstoper.c b/lang/cem/cemcom.ansi/fltcstoper.c index 7b48fc725..c33d7a278 100644 --- a/lang/cem/cemcom.ansi/fltcstoper.c +++ b/lang/cem/cemcom.ansi/fltcstoper.c @@ -10,18 +10,19 @@ #include "parameters.h" #include #include +#include "fltcstoper.h" #include "arith.h" #include "type.h" #include "label.h" #include "expr.h" #include "sizes.h" #include "Lpars.h" +#include "error.h" extern int ResultKnown; extern char *symbol2str(); -fltcstbin(expp, oper, expr) - register struct expr **expp, *expr; +void fltcstbin(register struct expr **expp, int oper, register struct expr *expr) { /* The operation oper is performed on the constant expressions *expp(ld) and expr(ct), and the result restored in diff --git a/lang/cem/cemcom.ansi/fltcstoper.h b/lang/cem/cemcom.ansi/fltcstoper.h new file mode 100644 index 000000000..4b65618f6 --- /dev/null +++ b/lang/cem/cemcom.ansi/fltcstoper.h @@ -0,0 +1,15 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-07 + * + */ +#ifndef FLTCSTOPER_H_ +#define FLTCSTOPER_H_ + +struct expr; + +void fltcstbin(register struct expr **expp, int oper, register struct expr *expr); + +#endif /* FLTCSTOPER_H_ */ diff --git a/lang/cem/cemcom.ansi/idf.c b/lang/cem/cemcom.ansi/idf.c index 54727221e..4d3f0fc89 100644 --- a/lang/cem/cemcom.ansi/idf.c +++ b/lang/cem/cemcom.ansi/idf.c @@ -25,6 +25,12 @@ #include "declar.h" #include "decspecs.h" #include "sizes.h" +#include "print.h" +#include "util.h" +#include "stab.h" +#include "code.h" +#include "error.h" +#include "ch3.h" #include "Lpars.h" extern char options[]; @@ -37,91 +43,92 @@ extern char *symbol2str(); #include -void global_redecl(); -struct idf * -gen_idf() + +struct idf *gen_idf(void) { /* A new idf is created out of nowhere, to serve as an - anonymous name. - */ + anonymous name. + */ static int name_cnt; char *s = Malloc(strlen(dot.tk_file) + 50); - sprint(s, "#%d in %s, line %u", - ++name_cnt, dot.tk_file, dot.tk_line); - s = Realloc(s, strlen(s)+1); + sprint(s, "#%d in %s, line %u", ++name_cnt, dot.tk_file, dot.tk_line); + s = Realloc(s, strlen(s) + 1); return str2idf(s, 0); } -int -is_anon_idf(idf) - struct idf *idf; +int is_anon_idf(struct idf *idf) { return idf->id_text[0] == '#'; } -declare_idf(ds, dc, lvl) - struct decspecs *ds; - struct declarator *dc; +void declare_idf(struct decspecs *ds, struct declarator *dc, int lvl) { /* 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. - */ + 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 */ + /* 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) { + 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 */ + type = int_type; /* may change at L_FORMAL2 */ } - else { + 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) { + 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: - */ - if (type->tp_fund != VOID) { - if (level != L_GLOBAL) - error("unknown %s-type", - symbol2str(type->tp_fund)); - } else error("void is not a complete type"); + but it has to be: + */ + if (type->tp_fund != VOID) + { + if (level != L_GLOBAL) + error("unknown %s-type", symbol2str(type->tp_fund)); + } + else + error("void is not a complete type"); } - else strict("%s has size 0", idf->id_text); + else + strict("%s has size 0", idf->id_text); } } /* some additional work for formal definitions */ - if (lvl == L_FORMAL2) { - switch (type->tp_fund) { + 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); + warning("%s is a function; cannot be formal", idf->id_text); + type = construct_type(POINTER, type, 0, (arith) 0, + NO_PROTO); break; - case ARRAY: /* 3.7.1 */ - type = construct_type(POINTER, type->tp_up, 0, (arith)0, - NO_PROTO); + case ARRAY: /* 3.7.1 */ + type = construct_type(POINTER, type->tp_up, 0, (arith) 0, + NO_PROTO); formal_array = 1; break; case FLOAT: @@ -135,72 +142,77 @@ declare_idf(ds, dc, lvl) } } /* The tests on types, postponed from do_decspecs(), can now - be performed. - */ + be performed. + */ /* update the storage class */ - if (type && type->tp_fund == FUNCTION) { - if (lvl != L_GLOBAL) { /* 3.5.1 */ + if (type && type->tp_fund == FUNCTION) + { + if (lvl != L_GLOBAL) + { /* 3.5.1 */ if (sc == 0) sc = GLOBAL; - else if (sc != EXTERN && sc != TYPEDEF) { - error("illegal storage class %s for function with block-scope" - , symbol2str(sc)); + else if (sc != EXTERN && sc != TYPEDEF) + { + error("illegal storage class %s for function with block-scope", + symbol2str(sc)); ds->ds_sc = sc = EXTERN; } } else if (sc == 0) sc = GLOBAL; } - else /* non-FUNCTION */ - if (sc == 0) - sc = lvl == L_GLOBAL ? GLOBAL - : lvl == L_FORMAL1 || lvl == L_FORMAL2 ? FORMAL - : AUTO; + else /* non-FUNCTION */ + if (sc == 0) + sc = lvl == L_GLOBAL ? GLOBAL : + lvl == L_FORMAL1 || lvl == L_FORMAL2 ? FORMAL : AUTO; #ifdef LINT - check_hiding(idf, lvl, sc); /* of some idf by this idf */ + check_hiding(idf, lvl, sc); /* of some idf by this idf */ #endif /* LINT */ - if (def && lvl == L_LOCAL && def->df_level == L_FORMAL2) { + if (def && lvl == L_LOCAL && def->df_level == L_FORMAL2) + { error("%s redeclared", idf->id_text); } - if (def && - ( def->df_level == lvl || - ( lvl != L_GLOBAL && def->df_level > lvl ) || - (lvl == L_GLOBAL - && def->df_level == L_PROTO - && def->next && def->next->df_level == L_GLOBAL) - )) { + if (def + && (def->df_level == lvl || (lvl != L_GLOBAL && def->df_level > lvl) + || (lvl == L_GLOBAL && def->df_level == L_PROTO && def->next + && def->next->df_level == L_GLOBAL))) + { /* There is already a declaration for idf on this - level, or even more inside. - The rules differ for different levels. - */ - switch (lvl) { + 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 */ + case L_FORMAL1: /* formal declaration */ error("formal %s redeclared", idf->id_text); break; - case L_FORMAL2: /* formal definition */ - default: /* local */ - if (sc != EXTERN) error("%s redeclared", idf->id_text); + case L_FORMAL2: /* formal definition */ + default: /* local */ + if (sc != EXTERN) + 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)) { + 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_level = L_FORMAL2; /* CJ */ def->df_file = idf->id_file; def->df_line = idf->id_line; } - else { /* fill in the def block */ + else + { /* fill in the def block */ register struct def *newdef = new_def(); newdef->next = def; @@ -218,28 +230,27 @@ declare_idf(ds, dc, lvl) 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) { + 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) { + switch (sc) + { case REGISTER: case AUTO: - if (type->tp_size == (arith)-1 - && type->tp_fund != ARRAY) { - error("size of local %s unknown", - idf->id_text); - /** type = idf->id_def->df_type = int_type; **/ + if (type->tp_size == (arith) -1 && type->tp_fund != ARRAY) + { + error("size of local %s unknown", idf->id_text); + /** type = idf->id_def->df_type = int_type; **/ } - if (type->tp_size != (arith) -1) { - newdef->df_address = - NewLocal(type->tp_size, - type->tp_align, - regtype(type), - sc); + if (type->tp_size != (arith) -1) + { + newdef->df_address = NewLocal(type->tp_size, type->tp_align, + regtype(type), sc); } break; case STATIC: @@ -250,21 +261,19 @@ declare_idf(ds, dc, lvl) } } -int -actual_declaration(sc, tp) - int sc; - struct type *tp; +int actual_declaration(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; - if (sc == EXTERN && fund == VOID) { + if (sc == EXTERN && fund == VOID) + { /* strange, but should be accepted */ return 0; } @@ -272,51 +281,59 @@ actual_declaration(sc, tp) return 1; } -void -global_redecl(idf, new_sc, tp) - register struct idf *idf; - struct type *tp; +void global_redecl(register struct idf *idf, int new_sc, 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. - */ + 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; - while (def->df_level != L_GLOBAL) def = def->next; - if (!equal_type(tp, def->df_type, 0, 1)) { + while (def->df_level != L_GLOBAL) + def = def->next; + if (!equal_type(tp, def->df_type, 0, 1)) + { error("redeclaration of %s with different type", idf->id_text); return; - } else update_proto(tp, def->df_type); - if (tp->tp_fund == ARRAY) { + } + else + update_proto(tp, def->df_type); + if (tp->tp_fund == ARRAY) + { /* Multiple array declaration; this may be interesting */ - if (tp->tp_size < 0) { /* new decl has [] */ + if (tp->tp_size < 0) + { /* new decl has [] */ /* nothing new */ - } else - if (def->df_type->tp_size < 0) { /* old decl has [] */ + } + else if (def->df_type->tp_size < 0) + { /* old decl has [] */ def->df_type = tp; } - } if (tp->tp_fund == FUNCTION && new_sc == GLOBAL) { + } + if (tp->tp_fund == FUNCTION && new_sc == GLOBAL) + { /* see 3.1.2.2 */ new_sc = EXTERN; } /* 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" - */ - - switch (def->df_sc) { /* the old 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" + */ + + switch (def->df_sc) + { /* the old storage class */ case EXTERN: - switch (new_sc) { /* the new storage class */ + switch (new_sc) + { /* the new storage class */ case STATIC: warning("%s redeclared static", idf->id_text); /* fallthrough */ @@ -331,8 +348,9 @@ global_redecl(idf, new_sc, tp) } break; case GLOBAL: - switch (new_sc) { /* the new storage class */ - case STATIC: /* linkage disagreement */ + switch (new_sc) + { /* the new storage class */ + case STATIC: /* linkage disagreement */ warning("%s redeclared static", idf->id_text); def->df_sc = new_sc; /* fallthrough */ @@ -345,8 +363,9 @@ global_redecl(idf, new_sc, tp) } break; case STATIC: - switch (new_sc) { /* the new storage class */ - case GLOBAL: /* linkage disagreement */ + switch (new_sc) + { /* the new storage class */ + case GLOBAL: /* linkage disagreement */ case EXTERN: warning("%s is already declared static", idf->id_text); /* fallthrough */ @@ -367,142 +386,147 @@ global_redecl(idf, new_sc, tp) } } -int -good_formal(def, idf) - register struct def *def; - register struct idf *idf; +int good_formal(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 */ + 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 */ + assert(def->df_sc == FORMAL); /* CJ */ return 1; } -declare_params(dc) - struct declarator *dc; +void declare_params(struct declarator *dc) { /* Declares the formal parameters if they exist. - */ + */ register struct formal *fm = dc->dc_formal; - while (fm) { + while (fm) + { declare_parameter(fm->fm_idf); fm = fm->next; } } -void -idf_initialized(idf) - register struct idf *idf; +void idf_initialized(register struct idf *idf) { /* The topmost definition of idf is set to initialized. - */ - register struct def *def = idf->id_def; /* the topmost */ - - while (def->df_level <= L_PROTO) def = def->next; + */ + register struct def *def = idf->id_def; /* the topmost */ + + while (def->df_level <= L_PROTO) + def = def->next; if (def->df_initialized) error("multiple initialization of %s", idf->id_text); - if (def->df_sc == TYPEDEF) { + if (def->df_sc == TYPEDEF) + { error("typedef cannot be initialized"); return; } def->df_initialized = 1; } -declare_parameter(idf) - struct idf *idf; +void declare_parameter(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; +void declare_enum(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; } -void -check_formals(idf, dc) - struct idf *idf; - struct declarator *dc; +void check_formals(struct idf *idf, struct declarator *dc) { register struct formal *fm = dc->dc_formal; register struct proto *pl = idf->id_def->df_type->tp_proto; register struct decl_unary *du = dc->dc_decl_unary; - if (!du) { /* error or typdef'ed function */ + if (!du) + { /* error or typdef'ed function */ error("illegal definition of %s", idf->id_text); return; } while (du - && (du->du_fund != FUNCTION - || du->next != (struct decl_unary *) 0)) { + && (du->du_fund != FUNCTION || du->next != (struct decl_unary *) 0)) + { du = du->next; } - if (!du) return; /* terrible error, signalled earlier */ + if (!du) + return; /* terrible error, signalled earlier */ - if (du->du_proto) return; + if (du->du_proto) + return; - if (pl) { + if (pl) + { /* Don't give a warning about an old-style definition, * since the arguments will be checked anyway. */ - if (pl->pl_flag & PL_ELLIPSIS) { - if (!(du->du_proto) && !(pl->pl_flag & PL_ERRGIVEN)) - error("ellipsis terminator in previous declaration"); - pl = pl->next; + if (pl->pl_flag & PL_ELLIPSIS) + { + if (!(du->du_proto) && !(pl->pl_flag & PL_ERRGIVEN)) + error("ellipsis terminator in previous declaration"); + pl = pl->next; } - else if (pl->pl_flag & PL_VOID) { - pl = pl->next; /* should be 0 */ + else if (pl->pl_flag & PL_VOID) + { + pl = pl->next; /* should be 0 */ } - while(fm && pl) { - if (!equal_type(promoted_type(fm->fm_idf->id_def->df_type) - , pl->pl_type, -1, 1)) { - if (!(pl->pl_flag & PL_ERRGIVEN)) - error("incorrect type for parameter %s" - , fm->fm_idf->id_text); - pl->pl_flag |= PL_ERRGIVEN; - } - fm = fm->next; - pl = pl->next; + while (fm && pl) + { + if (!equal_type(promoted_type(fm->fm_idf->id_def->df_type), + pl->pl_type, -1, 1)) + { + if (!(pl->pl_flag & PL_ERRGIVEN)) + error("incorrect type for parameter %s", + fm->fm_idf->id_text); + pl->pl_flag |= PL_ERRGIVEN; + } + fm = fm->next; + pl = pl->next; } - if (pl || fm) { + if (pl || fm) + { error("incorrect number of parameters"); } - } else { /* make a pseudo-prototype */ + } + else + { /* make a pseudo-prototype */ register struct proto *lpl = new_proto(); if (!options['o']) - warning("'%s' old-fashioned function definition" - , dc->dc_idf->id_text); - - while (fm) { - if (pl == 0) pl = lpl; - else { + warning("'%s' old-fashioned function definition", + dc->dc_idf->id_text); + + while (fm) + { + if (pl == 0) + pl = lpl; + else + { lpl->next = new_proto(); lpl = lpl->next; } lpl->pl_flag = PL_FORMAL; lpl->pl_idf = fm->fm_idf; - lpl->pl_type = - promoted_type(fm->fm_idf->id_def->df_type); + lpl->pl_type = promoted_type(fm->fm_idf->id_def->df_type); fm = fm->next; } - if (pl == 0) { /* make func(void) */ + if (pl == 0) + { /* make func(void) */ pl = lpl; pl->pl_type = void_type; pl->pl_flag = PL_FORMAL | PL_VOID; @@ -513,26 +537,26 @@ check_formals(idf, dc) dc->dc_formal = 0; } -declare_formals(idf, fp) - struct idf *idf; - arith *fp; +void declare_formals(struct idf *idf, 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; - */ + 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; + arith f_offset = (arith) 0; register int nparams = 0; int hasproto; struct def *df = idf->id_def; /* When one of the formals has the same name as the function, - it hides the function def. Get it. - */ - while (se) { - if (se->se_idf == idf) { + it hides the function def. Get it. + */ + while (se) + { + if (se->se_idf == idf) + { df = df->next; break; } @@ -540,49 +564,53 @@ declare_formals(idf, fp) } se = stack_level_of(L_FORMAL1)->sl_entry; - + hasproto = df->df_type->tp_proto != 0; #ifdef DEBUG if (options['t']) - dumpidftab("start declare_formals", 0); + dumpidftab("start declare_formals", 0); #endif /* DEBUG */ - if (is_struct_or_union(df->df_type->tp_up->tp_fund)) { + if (is_struct_or_union(df->df_type->tp_up->tp_fund)) + { /* create space for address of return value */ f_offset = pointer_size; } - while (se) { + while (se) + { df = se->se_idf->id_def; - + /* this stacklevel may also contain tags. ignore them */ - if (!df || df->df_level < L_FORMAL1 ) { + if (!df || df->df_level < L_FORMAL1) + { se = se->next; continue; } df->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. - */ - if (! hasproto - && df->df_type->tp_fund == FLOAT - && df->df_type->tp_size != double_size) { + word boundaries, i.e. take care that the following + parameter starts on a new word boundary. + */ + if (!hasproto && df->df_type->tp_fund == FLOAT + && df->df_type->tp_size != double_size) + { f_offset = align(f_offset + double_size, (int) word_size); } - else f_offset = align(f_offset + df->df_type->tp_size, (int) word_size); + else + f_offset = align(f_offset + df->df_type->tp_size, (int) word_size); RegisterAccount(df->df_address, df->df_type->tp_size, - regtype(df->df_type), - df->df_sc); + regtype(df->df_type), df->df_sc); /* cvt int to char or short and double to float, if necessary */ formal_cvt(hasproto, df); - df->df_level = L_FORMAL2; /* CJ */ + df->df_level = L_FORMAL2; /* CJ */ if (nparams++ >= STDC_NPARAMS) strict("number of formal parameters exceeds ANSI limit"); #ifdef DBSYMTAB - if (options['g']) { + if (options['g']) + { stb_string(df, FORMAL, se->se_idf->id_text); } #endif /* DBSYMTAB */ @@ -591,11 +619,10 @@ declare_formals(idf, fp) *fp = f_offset; } -int -regtype(tp) - struct type *tp; +int regtype(struct type *tp) { - switch(tp->tp_fund) { + switch (tp->tp_fund) + { case INT: case LONG: return reg_any; @@ -609,18 +636,15 @@ regtype(tp) return -1; } -add_def(idf, sc, tp, lvl) - struct idf *idf; - struct type *tp; - int lvl; - int sc; +void add_def(struct idf *idf, int sc, struct type *tp, int lvl) { /* 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; + 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; @@ -630,25 +654,24 @@ add_def(idf, sc, tp, lvl) declare_idf(&Ds, &Dc, lvl); } -update_ahead(idf) - register struct idf *idf; +void update_ahead(register struct idf *idf) { /* The tk_symb of the token ahead is updated in the light of new - information about the identifier idf. - */ + information about the identifier idf. + */ register int tk_symb = AHEAD; - if ( (tk_symb == IDENTIFIER || tk_symb == TYPE_IDENTIFIER) && - ahead.tk_idf == idf - ) + 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; + TYPE_IDENTIFIER : + IDENTIFIER; } -free_formals(fm) - register struct formal *fm; +void free_formals(register struct formal *fm) { - while (fm) { + while (fm) + { struct formal *tmp = fm->next; free_formal(fm); diff --git a/lang/cem/cemcom.ansi/idf.str b/lang/cem/cemcom.ansi/idf.str index 06caa7f3e..d26ebfe56 100644 --- a/lang/cem/cemcom.ansi/idf.str +++ b/lang/cem/cemcom.ansi/idf.str @@ -2,10 +2,15 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef IDF_H_ +#define IDF_H_ + + /* $Id$ */ /* IDENTIFIER DESCRIPTOR */ #include "parameters.h" +#include "arith.h" struct id_u { int idd_reserved; /* non-zero for reserved words */ @@ -33,4 +38,28 @@ struct id_u { #include extern int level; -extern struct idf *gen_idf(); + +struct decspecs; +struct declarator; +struct type; +struct formal; + + +struct idf *gen_idf(void); +int is_anon_idf(struct idf *idf); +void declare_idf(struct decspecs *ds, struct declarator *dc, int lvl); +int actual_declaration(int sc, struct type *tp); +void global_redecl(register struct idf *idf, int new_sc, struct type *tp); +int good_formal(register struct def *def, register struct idf *idf); +void declare_params(struct declarator *dc); +void idf_initialized(register struct idf *idf); +void declare_parameter(struct idf *idf); +void declare_enum(struct type *tp, struct idf *idf, arith l); +void check_formals(struct idf *idf, struct declarator *dc); +void declare_formals(struct idf *idf, arith *fp); +int regtype(struct type *tp); +void add_def(struct idf *idf, int sc, struct type *tp, int lvl); +void update_ahead(register struct idf *idf); +void free_formals(register struct formal *fm); + +#endif \ No newline at end of file diff --git a/lang/cem/cemcom.ansi/input.c b/lang/cem/cemcom.ansi/input.c index dea9a4892..e5d019bb4 100644 --- a/lang/cem/cemcom.ansi/input.c +++ b/lang/cem/cemcom.ansi/input.c @@ -10,6 +10,7 @@ #include #include "file_info.h" #include "input.h" +#include "error.h" #define INP_PUSHBACK 3 #define INP_TYPE struct file_info @@ -20,14 +21,14 @@ struct file_info finfo; int NoUnstack; -AtEoIT() +int AtEoIT(void) { return 0; } extern char *source; -AtEoIF() +int AtEoIF(void) { if (NoUnstack) lexerror("unexpected EOF"); return 0; diff --git a/lang/cem/cemcom.ansi/input.h b/lang/cem/cemcom.ansi/input.h index 972eaf2f6..4ffbe0f5c 100644 --- a/lang/cem/cemcom.ansi/input.h +++ b/lang/cem/cemcom.ansi/input.h @@ -12,4 +12,4 @@ #define UnGetChar() ((LexSave != EOI) ? ChPushBack(LexSave) : 0) extern int LexSave; /* last character read by GetChar */ -extern int GetChar(); /* character input, with trigraph parsing */ + diff --git a/lang/cem/cemcom.ansi/ival.g b/lang/cem/cemcom.ansi/ival.g index e867aad86..80c6d1d01 100644 --- a/lang/cem/cemcom.ansi/ival.g +++ b/lang/cem/cemcom.ansi/ival.g @@ -1,774 +1,759 @@ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -/* $Id$ */ -/* CODE FOR THE INITIALISATION OF GLOBAL VARIABLES */ - -{ -#include -#include -#include "parameters.h" -#ifndef LINT -#include -#else -#include "l_em.h" -#include "l_lint.h" -#endif /* LINT */ -#include -#include -#include -#include -#include "idf.h" -#include "arith.h" -#include "label.h" -#include "expr.h" -#include "type.h" -#include "proto.h" -#include "struct.h" -#include "field.h" -#include "Lpars.h" -#include "sizes.h" -#include "align.h" -#include "level.h" -#include "def.h" -#include "LLlex.h" -#include "estack.h" -#include "stack.h" - -#define con_nullbyte() C_con_ucon("0", (arith)1) -#define aggregate_type(tp) ((tp)->tp_fund == ARRAY || (tp)->tp_fund == STRUCT) - -char *strncpy(); -extern char options[]; -static int gen_error; -static int pack_level; -struct type **gen_tphead(), **gen_tpmiddle(); -struct sdef *gen_align_to_next(); -struct e_stack *p_stack; - -void pad(); -void gen_simple_exp(); -void gen_tpcheck(); - -} - -/* initial_value recursively guides the initialisation expression. - */ -/* 3.5 */ - -initial_value(register struct type **tpp; register struct expr **expp;) : - { if (tpp) gen_tpcheck(tpp); } -[ - { if (pack_level == 0) gen_error = 0; } - assignment_expression(expp) - { -#ifdef LINT - lint_expr(*expp, USED); -#endif /* LINT */ - if ((*expp)->ex_type->tp_fund == ARRAY) - array2pointer(*expp); - if (tpp) { - if (level >= L_LOCAL - || is_ld_cst(*expp) - || is_fp_cst(*expp) - || (*expp)->ex_class == String) { - gen_simple_exp(tpp, expp); - free_expression(*expp); - *expp = 0; - } else { - expr_error(*expp,"illegal initialization"); - free_expression(*expp); - *expp = 0; - } - } - } -| - initial_value_pack(tpp, expp) -] -; - -initial_value_pack(struct type **tpp; struct expr **expp;) -: - '{' - { 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; - } - } - if (pack_level < gen_error) gen_error = 0; - } - '}' -; - -initial_value_list(register struct type **tpp; struct expr **expp;) - { struct expr *e1; - register struct type **tpp2 = 0; - int err_flag = gen_error; - } -: - { 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 && ! err_flag) gen_tpend(); } - ','? /* optional trailing comma */ -; - -{ -void -gen_tpcheck(tpp) - 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 = pack_level; - break; - case STRUCT: - if (! valid_type(tp, "struct")) - gen_error = pack_level; - break; - case UNION: - if (! valid_type(tp, "union")) - gen_error = pack_level; - break; - case ERRONEOUS: - if (! gen_error) gen_error = pack_level; - break; - } -} - -void -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: - case FUNCTION: - case VOID: - gen_error = pack_level; - 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) && tp->tp_up->tp_fund != UNION)) - 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); - 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 = pack_level; - return 0; - } - if (gen_error) return tpp; - if (tp->tp_fund == UNION) { - /* Here, we saw a {, which could be the start of a union - initializer. It could, however, also be the start of the - initializer for the first union field ... - */ - sd = tp->tp_sdef; - if (AHEAD != '{' && - (aggregate_type(sd->sd_type) || - sd->sd_type->tp_fund == UNION)) { - /* In this case, assume that it is the start of the - initializer of the union field, so: - */ - return gen_tphead(&(tp->tp_sdef->sd_type), nest); - } - } - p = new_e_stack(); - p->next = p_stack; - p_stack = p; - p->s_nested = nest; - p->s_tpp = tpp; - switch(tp->tp_fund) { - case UNION: - p->s_def = sd = tp->tp_sdef; - p->bytes_upto_here = 0; - return &(sd->sd_type); - 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 = pack_level; - 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); - case ERRONEOUS: - if (! gen_error) gen_error = pack_level; - /* fall through */ - 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) { - case ERRONEOUS: - if (! gen_error) gen_error = pack_level; - return p->s_tpp; - case UNION: - sd = p->s_def; - p->bytes_upto_here += - size_of_type(sd->sd_type, "selector"); - return p->s_tpp; - 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 UNION: - sd = p->s_def; - p->bytes_upto_here += - size_of_type(sd->sd_type, "selector"); - while (p->bytes_upto_here++ < tp->tp_size) - con_nullbyte(); - break; - 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; - } -} - -/* 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. -*/ -void -pad(tpx) - struct type *tpx; -{ - register struct type *tp = tpx; - register arith sz = tp->tp_size; - - gen_tpcheck(&tpx); - if (gen_error) return; -#ifndef NOBITFIELD - if (tp->tp_fund == FIELD) { - put_bf(tp, (arith)0); - return; - } -#endif /* NOBITFIELD */ - - if (tp->tp_align >= word_align) 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 ch3cast 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: - ch3cast(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 - && idf->id_def->df_sc != GLOBAL - && idf->id_def->df_sc != EXTERN) { - 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; - case FLOAT: - case DOUBLE: - case LNGDBL: - ch3cast(expp, '=', tp); - expr = *expp; -#ifdef DEBUG - print_expr("init-expr after cast", expr); -#endif /* DEBUG */ - if (expr->ex_class == Float) { - char buf[FLT_STRLEN]; - - flt_flt2str(&(expr->FL_ARITH), buf, FLT_STRLEN); - C_con_fcon(buf, 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; - -#ifndef NOBITFIELD - case FIELD: - ch3cast(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: - if (! gen_error) gen_error = pack_level; - /* fall through */ - case VOID: - 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 int length = ex->SG_LEN, i; - register char *to, *from, *s; - - assert(ex->ex_class == String); - if (tp->tp_size == (arith)-1) { - /* set the dimension */ - tp = *tpp = construct_type(ARRAY, tp->tp_up, 0, (arith)length, NO_PROTO); - } - else { - arith dim = tp->tp_size / tp->tp_up->tp_size; - -#ifdef LINT - if (length == dim + 1) { - expr_warning(ex, "array is not null-terminated"); - } else -#endif - if (length > dim + 1) { - expr_strict(ex, "too many initializers"); - } - length = dim; - } - /* throw out the characters of the already prepared string */ - s = Malloc((unsigned) (length)); - clear(s, (unsigned)length); - i = length <= ex->SG_LEN ? length : ex->SG_LEN; - to = s; from = ex->SG_VALUE; - while(--i >= 0) { - *to++ = *from++; - } - free(ex->SG_VALUE); - str_cst(s, length, 0); /* a string, but not in rom */ - 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, inrom) - register char *str; - register int len; - int inrom; -{ - int chunksize = ((127 + (int) word_size) / (int) word_size) * (int) word_size; - - while (len > chunksize) { - if (inrom) - C_rom_scon(str, (arith) chunksize); - else C_con_scon(str, (arith) chunksize); - len -= chunksize; - str += chunksize; - } - if (inrom) - C_rom_scon(str, (arith) len); - else 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"); - 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 initialization constant"); - gen_error = pack_level; -} - -too_many_initialisers() -{ - error("too many initializers"); - gen_error = pack_level; -} -} +/* + * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ +/* $Id$ */ +/* CODE FOR THE INITIALISATION OF GLOBAL VARIABLES */ + +{ +#include +#include +#include "parameters.h" +#ifndef LINT +#include +#else +#include "l_em.h" +#include "l_lint.h" +#endif /* LINT */ +#include +#include +#include +#include +#include +#include "idf.h" +#include "arith.h" +#include "label.h" +#include "expr.h" +#include "type.h" +#include "proto.h" +#include "struct.h" +#include "field.h" +#include "Lpars.h" +#include "sizes.h" +#include "align.h" +#include "level.h" +#include "error.h" +#include "def.h" +#include "LLlex.h" +#include "estack.h" +#include "stack.h" +#include "ch3.h" + +#define con_nullbyte() C_con_ucon("0", (arith)1) +#define aggregate_type(tp) ((tp)->tp_fund == ARRAY || (tp)->tp_fund == STRUCT) + +extern char options[]; +static int gen_error; +static int pack_level; +struct e_stack *p_stack; + +void gen_tpcheck(struct type **); +void gen_simple_exp(struct type **, struct expr **); +struct type **arr_elem(struct type **, struct e_stack *); +struct sdef *next_field(register struct sdef *,register struct e_stack *); +struct type **gen_tphead(struct type **, int); +struct type **gen_tpmiddle(void); +struct sdef *gen_align_to_next(register struct e_stack *); +void gen_tpend(void); +void check_and_pad(struct expr **, struct type **); +void pad(struct type *); +void check_ival(struct expr **, register struct type *); +void ch_array(struct type **, /* type tp = array of characters */ + struct expr *); +void str_cst(register char *, register int, int); +#ifndef NOBITFIELD +void put_bf(struct type *, arith ); +#endif /* NOBITFIELD */ +int zero_bytes(register struct sdef *); +int valid_type(struct type *, char *); +void con_int(register struct expr *); +void illegal_init_cst(struct expr *); +void too_many_initialisers(void); + +} + +/* initial_value recursively guides the initialisation expression. + */ +/* 3.5 */ + +initial_value(register struct type **tpp; register struct expr **expp;) : + { if (tpp) gen_tpcheck(tpp); } +[ + { if (pack_level == 0) gen_error = 0; } + assignment_expression(expp) + { +#ifdef LINT + lint_expr(*expp, USED); +#endif /* LINT */ + if ((*expp)->ex_type->tp_fund == ARRAY) + array2pointer(*expp); + if (tpp) { + if (level >= L_LOCAL + || is_ld_cst(*expp) + || is_fp_cst(*expp) + || (*expp)->ex_class == String) { + gen_simple_exp(tpp, expp); + free_expression(*expp); + *expp = 0; + } else { + expr_error(*expp,"illegal initialization"); + free_expression(*expp); + *expp = 0; + } + } + } +| + initial_value_pack(tpp, expp) +] +; + +initial_value_pack(struct type **tpp; struct expr **expp;) +: + '{' + { 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; + } + } + if (pack_level < gen_error) gen_error = 0; + } + '}' +; + +initial_value_list(register struct type **tpp; struct expr **expp;) + { struct expr *e1; + register struct type **tpp2 = 0; + int err_flag = gen_error; + } +: + { 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 && ! err_flag) gen_tpend(); } + ','? /* optional trailing comma */ +; + +{ +void gen_tpcheck(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 = pack_level; + break; + case STRUCT: + if (! valid_type(tp, "struct")) + gen_error = pack_level; + break; + case UNION: + if (! valid_type(tp, "union")) + gen_error = pack_level; + break; + case ERRONEOUS: + if (! gen_error) gen_error = pack_level; + break; + } +} + +void gen_simple_exp(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: + case FUNCTION: + case VOID: + gen_error = pack_level; + break; + default: + check_ival(expp, tp); + break; + } +} + +struct type **arr_elem(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) && tp->tp_up->tp_fund != UNION)) + return &(tp->tp_up); + return gen_tphead(&(tp->tp_up), 1); +} + +struct sdef *next_field(register struct sdef *sd, + register struct e_stack *p) +{ + if (sd->sd_sdef) + p->bytes_upto_here += zero_bytes(sd); + 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(struct type **tpp, int nest) +{ + register struct type *tp = *tpp; + register struct e_stack *p; + register struct sdef *sd; + + if (tpp && *tpp == error_type) { + gen_error = pack_level; + return 0; + } + if (gen_error) return tpp; + if (tp->tp_fund == UNION) { + /* Here, we saw a {, which could be the start of a union + initializer. It could, however, also be the start of the + initializer for the first union field ... + */ + sd = tp->tp_sdef; + if (AHEAD != '{' && + (aggregate_type(sd->sd_type) || + sd->sd_type->tp_fund == UNION)) { + /* In this case, assume that it is the start of the + initializer of the union field, so: + */ + return gen_tphead(&(tp->tp_sdef->sd_type), nest); + } + } + p = new_e_stack(); + p->next = p_stack; + p_stack = p; + p->s_nested = nest; + p->s_tpp = tpp; + switch(tp->tp_fund) { + case UNION: + p->s_def = sd = tp->tp_sdef; + p->bytes_upto_here = 0; + return &(sd->sd_type); + 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 = pack_level; + 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); + case ERRONEOUS: + if (! gen_error) gen_error = pack_level; + /* fall through */ + default: + p->nelem = 1; + p->elem_count = 1; + return tpp; + } +} + +struct type **gen_tpmiddle(void) +{ + 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) { + case ERRONEOUS: + if (! gen_error) gen_error = pack_level; + return p->s_tpp; + case UNION: + sd = p->s_def; + p->bytes_upto_here += + size_of_type(sd->sd_type, "selector"); + return p->s_tpp; + 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(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; +} + +void gen_tpend(void) +{ + 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 UNION: + sd = p->s_def; + p->bytes_upto_here += + size_of_type(sd->sd_type, "selector"); + while (p->bytes_upto_here++ < tp->tp_size) + con_nullbyte(); + break; + 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; + } +} + +/* 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. +*/ +void check_and_pad(struct expr **expp, struct type **tpp) +{ + 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. +*/ +void pad(struct type *tpx) +{ + register struct type *tp = tpx; + register arith sz = tp->tp_size; + + gen_tpcheck(&tpx); + if (gen_error) return; +#ifndef NOBITFIELD + if (tp->tp_fund == FIELD) { + put_bf(tp, (arith)0); + return; + } +#endif /* NOBITFIELD */ + + if (tp->tp_align >= word_align) 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. +*/ +void check_ival(struct expr **expp, register struct type *tp) +{ + /* The philosophy here is that ch3cast 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: + ch3cast(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 + && idf->id_def->df_sc != GLOBAL + && idf->id_def->df_sc != EXTERN) { + 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; + case FLOAT: + case DOUBLE: + case LNGDBL: + ch3cast(expp, '=', tp); + expr = *expp; +#ifdef DEBUG + print_expr("init-expr after cast", expr); +#endif /* DEBUG */ + if (expr->ex_class == Float) { + char buf[FLT_STRLEN]; + + flt_flt2str(&(expr->FL_ARITH), buf, FLT_STRLEN); + C_con_fcon(buf, 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; + +#ifndef NOBITFIELD + case FIELD: + ch3cast(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: + if (! gen_error) gen_error = pack_level; + /* fall through */ + case VOID: + break; + default: + crash("check_ival"); + /*NOTREACHED*/ + } +} + +/* ch_array() initialises an array of characters when given + a string constant. + Alignment is taken care of. +*/ +void ch_array(struct type **tpp, /* type tp = array of characters */ + struct expr *ex) +{ + register struct type *tp = *tpp; + register int length = ex->SG_LEN, i; + register char *to, *from, *s; + + assert(ex->ex_class == String); + if (tp->tp_size == (arith)-1) { + /* set the dimension */ + tp = *tpp = construct_type(ARRAY, tp->tp_up, 0, (arith)length, NO_PROTO); + } + else { + arith dim = tp->tp_size / tp->tp_up->tp_size; + +#ifdef LINT + if (length == dim + 1) { + expr_warning(ex, "array is not null-terminated"); + } else +#endif + if (length > dim + 1) { + expr_strict(ex, "too many initializers"); + } + length = dim; + } + /* throw out the characters of the already prepared string */ + s = Malloc((unsigned) (length)); + clear(s, (unsigned)length); + i = length <= ex->SG_LEN ? length : ex->SG_LEN; + to = s; from = ex->SG_VALUE; + while(--i >= 0) { + *to++ = *from++; + } + free(ex->SG_VALUE); + str_cst(s, length, 0); /* a string, but not in rom */ + free(s); +} + +/* As long as some parts of the pipeline cannot handle very long string + constants, string constants are written out in chunks +*/ +void str_cst(register char *str, register int len, int inrom) +{ + int chunksize = ((127 + (int) word_size) / (int) word_size) * (int) word_size; + + while (len > chunksize) { + if (inrom) + C_rom_scon(str, (arith) chunksize); + else C_con_scon(str, (arith) chunksize); + len -= chunksize; + str += chunksize; + } + if (inrom) + C_rom_scon(str, (arith) len); + else 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. +*/ +void put_bf(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(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"); + int count = n; + + while (n-- > 0) + con_nullbyte(); + return count; +} + +int valid_type(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; +} + +void con_int(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); +} + +void illegal_init_cst(struct expr *ex) +{ + expr_error(ex, "illegal initialization constant"); + gen_error = pack_level; +} + +void too_many_initialisers(void) +{ + error("too many initializers"); + gen_error = pack_level; +} +} diff --git a/lang/cem/cemcom.ansi/label.c b/lang/cem/cemcom.ansi/label.c index fb200956e..e4c10f85d 100644 --- a/lang/cem/cemcom.ansi/label.c +++ b/lang/cem/cemcom.ansi/label.c @@ -14,11 +14,12 @@ #include "def.h" #include "type.h" #include "stack.h" +#include "error.h" + extern char options[]; -enter_label(idf, defining) - register struct idf *idf; +void enter_label(register struct idf *idf, int defining) { /* The identifier idf is entered as a label. If it is new, it is entered into the idf list with the largest possible @@ -45,8 +46,7 @@ enter_label(idf, defining) def->df_initialized = 1; } -unstack_label(idf) - register struct idf *idf; +void unstack_label(register struct idf *idf) { /* The scope in which the label idf occurred is left. */ diff --git a/lang/cem/cemcom.ansi/label.h b/lang/cem/cemcom.ansi/label.h index 629577db2..47d6b5bea 100644 --- a/lang/cem/cemcom.ansi/label.h +++ b/lang/cem/cemcom.ansi/label.h @@ -4,6 +4,8 @@ */ /* $Id$ */ /* L A B E L D E F I N I T I O N */ +#ifndef LABEL_H_ +#define LABEL_H_ #include /* obtain definition of "label" */ @@ -26,3 +28,10 @@ extern label datlab_count; not be there, and if it is there, it may be from a declaration or another application. */ + +struct idf; + +void enter_label(register struct idf *idf, int defining); +void unstack_label(register struct idf *idf); + +#endif /* LABEL_H_ */ diff --git a/lang/cem/cemcom.ansi/main.c b/lang/cem/cemcom.ansi/main.c index d8e951af3..9d9f8903f 100644 --- a/lang/cem/cemcom.ansi/main.c +++ b/lang/cem/cemcom.ansi/main.c @@ -23,7 +23,13 @@ #include "specials.h" #include "sizes.h" #include "align.h" +#include "stack.h" #include "macro.h" +#include "options.h" +#include "error.h" +#include "code.h" +#include "cstoper.h" +#include "tokenname.h" extern struct tokenname tkidf[]; extern char *symbol2str(); @@ -34,7 +40,15 @@ struct sp_id special_ids[] = { {0, 0} }; -void dependency(); +void compile(int argc, char *argv[]); +static void init(void); +static void init_specials(register struct sp_id *si); +#ifdef DEBUG +void Info(void); +#endif + +extern void C_program(void); /* program.c */ + #ifndef NOCROSS arith @@ -63,8 +77,7 @@ int char *prog_name; -main(argc, argv) - char *argv[]; +int main(int argc, char *argv[]) { /* parse and interpret the command line options */ prog_name = argv[0]; @@ -104,8 +117,7 @@ char *source = 0; char *nmlist = 0; #endif /* GEN_NM_LIST */ -compile(argc, argv) - char *argv[]; +void compile(int argc, char *argv[]) { char *result; #ifndef LINT @@ -190,7 +202,7 @@ compile(argc, argv) } } -init() +static void init(void) { init_cst(); /* initialize variables of "cstoper.c" */ reserve(tkidf); /* mark the C reserved words as such */ @@ -255,8 +267,7 @@ init() stack_level(); } -init_specials(si) - register struct sp_id *si; +static void init_specials(register struct sp_id *si) { while (si->si_identifier) { struct idf *idf = str2idf(si->si_identifier, 0); @@ -269,7 +280,7 @@ init_specials(si) } #ifdef DEBUG -Info() +void Info(void) { extern int cnt_string_cst, cnt_formal, cnt_decl_unary, cnt_def, cnt_expr, cnt_field, @@ -301,14 +312,12 @@ Info() } #endif /* DEBUG */ -void -No_Mem() /* called by alloc package */ +void No_Mem(void) /* called by alloc package */ { fatal("out of memory"); } -void -C_failed() /* called by EM_code module */ +void C_failed(void) /* called by EM_code module */ { fatal("write failed"); } diff --git a/lang/cem/cemcom.ansi/next.str b/lang/cem/cemcom.ansi/next.str new file mode 100644 index 000000000..5dd79564f --- /dev/null +++ b/lang/cem/cemcom.ansi/next.str @@ -0,0 +1 @@ +#include "parameters.h" diff --git a/lang/cem/cemcom.ansi/options.c b/lang/cem/cemcom.ansi/options.c index c0b411934..62864f5b7 100644 --- a/lang/cem/cemcom.ansi/options.c +++ b/lang/cem/cemcom.ansi/options.c @@ -9,12 +9,14 @@ #include #include #include +#include "options.h" #include "class.h" #include "macro.h" #include "idf.h" #include "arith.h" #include "sizes.h" #include "align.h" +#include "error.h" char options[128]; /* one for every char */ #ifdef LINT @@ -24,10 +26,11 @@ char loptions[128]; /* one for every char */ extern int idfsize; extern int density; -static int txt2int(); -do_option(text) - char *text; + +static int txt2int(register char **); + +void do_option(char *text) { register char opt; @@ -209,9 +212,7 @@ next_option: /* to allow combined one-char options */ } } -static int -txt2int(tp) - register char **tp; +static int txt2int(register char **tp) { /* the integer pointed to by *tp is read, while increasing *tp; the resulting value is yielded. diff --git a/lang/cem/cemcom.ansi/options.h b/lang/cem/cemcom.ansi/options.h new file mode 100644 index 000000000..ade29ed88 --- /dev/null +++ b/lang/cem/cemcom.ansi/options.h @@ -0,0 +1,13 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-07 + * + */ +#ifndef OPTIONS_H_ +#define OPTIONS_H_ + +void do_option(char *text); + +#endif /* OPTIONS_H_ */ diff --git a/lang/cem/cemcom.ansi/pragma.c b/lang/cem/cemcom.ansi/pragma.c index b4198d92b..335cb9263 100644 --- a/lang/cem/cemcom.ansi/pragma.c +++ b/lang/cem/cemcom.ansi/pragma.c @@ -6,37 +6,43 @@ /* PREPROCESSOR: PRAGMA INTERPRETER */ #include "parameters.h" +#include "pragma.h" +#include "skip.h" #define P_UNKNOWN 0 #define NR_PRAGMAS 0 -struct pkey { +struct pkey +{ char *pk_name; int pk_key; -} pragmas[NR_PRAGMAS + 1] = { - {0, P_UNKNOWN} -}; +} pragmas[NR_PRAGMAS + 1] = +{ +{ 0, P_UNKNOWN } }; extern struct idf *GetIdentifier(); -do_pragma() +void do_pragma(void) { #if NR_PRAGMAS register struct pkey *pkp = &pragmas[0]; #endif register struct idf *id = GetIdentifier(1); - if (id != (struct idf *)0) { + if (id != (struct idf *) 0) + { #if NR_PRAGMAS - while(pkp->pk_name) { + while(pkp->pk_name) + { if (strcmp(pkp->pk_name, id->id_text) == 0) - break; + break; pkp++; } - switch (pkp->pk_key) { - case P_UNKNOWN: - default: + switch (pkp->pk_key) + { + case P_UNKNOWN: + default: break; } #endif diff --git a/lang/cem/cemcom.ansi/pragma.h b/lang/cem/cemcom.ansi/pragma.h new file mode 100644 index 000000000..df62ad6c0 --- /dev/null +++ b/lang/cem/cemcom.ansi/pragma.h @@ -0,0 +1,13 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-07 + * + */ +#ifndef PRAGMA_H_ +#define PRAGMA_H_ + +void do_pragma(void); + +#endif /* PRAGMA_H_ */ diff --git a/lang/cem/cemcom.ansi/program.g b/lang/cem/cemcom.ansi/program.g index 631603cff..616065da5 100644 --- a/lang/cem/cemcom.ansi/program.g +++ b/lang/cem/cemcom.ansi/program.g @@ -1,224 +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". - */ -/* $Id$ */ -/* 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 "parameters.h" -#include -#include "arith.h" -#include "LLlex.h" -#include "label.h" -#include "type.h" -#include "declar.h" -#include "decspecs.h" -#include "code.h" -#include "expr.h" -#include "def.h" -#include "stack.h" -#ifdef LINT -#include "l_lint.h" -#endif /* LINT */ - -extern error(); -} - -control_if_expression - { - struct expr *exprX; - } -: - constant_expression(&exprX) - { - } -; - -/* 3.7 */ -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. - - With the introduction of prototypes, extra problems for the scope - administration were introduced as well. We can have, for example, - int x(double x); - and - int x(double x) { ... use(x) ... } - In the first case, the parameter name can be forgotten, whereas in - the second case, the parameter should have a block scope. The - problem lies in the fact that the parameter's type is known before - the type of the function, which causes the def structure to be on - the end of the list. Our solution is as follows: - 1- In case of a declaration, throw the parameter identifier away - before the declaration of the outer x. - 2- In case of a definition, the function begin_proc() changes the - def list for the identifier. This means that declare_idf() - contains an extra test in case we already saw a declaration of - such a function, because this function is called before - begin_proc(). -*/ - -external_definition - { struct decspecs Ds; - struct declarator Dc; - } -: - { Ds = null_decspecs; - Dc = null_declarator; - } - [ %if (DOT != IDENTIFIER || AHEAD == IDENTIFIER) - decl_specifiers(&Ds) - | - {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) - | - { if (! Ds.ds_sc_given && ! Ds.ds_typequal && - Ds.ds_notypegiven) { - strict("declaration specifiers missing"); - } - } - non_function(&Ds, &Dc) - ] - | - { if (! Ds.ds_sc_given && ! Ds.ds_typequal && - Ds.ds_notypegiven) { - strict("declaration missing"); - } - } - ';' - ] - {remove_declarator(&Dc); flush_strings(); } -; - -non_function(register struct decspecs *ds; register struct declarator *dc;) -: - { reject_params(dc); - } - [ - initializer(dc->dc_idf, ds->ds_sc) - | - { code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); } - ] - { -#ifdef LINT - lint_non_function_decl(ds, dc); -#endif /* LINT */ - } - [ - ',' - init_declarator(ds) - ]* - ';' -; - -/* 3.7.1 */ -function(struct decspecs *ds; struct declarator *dc;) - { - arith fbytes; - register struct idf *idf = dc->dc_idf; - } -: - { -#ifdef LINT - lint_start_function(); -#endif /* LINT */ - idf_initialized(idf); - stack_level(); /* L_FORMAL1 declarations */ - declare_params(dc); - begin_proc(ds, idf); /* sets global function info */ - stack_level(); /* L_FORMAL2 declarations */ - declare_protos(dc); - } - declaration* - { - check_formals(idf, dc); /* check style-mixtures */ - declare_formals(idf, &fbytes); -#ifdef LINT - lint_formals(); -#endif /* LINT */ - } - compound_statement - { - end_proc(fbytes); -#ifdef LINT - lint_implicit_return(); -#endif /* LINT */ - unstack_level(); /* L_FORMAL2 declarations */ -#ifdef LINT - lint_end_formals(); -#endif /* LINT */ - unstack_level(); /* L_FORMAL1 declarations */ -#ifdef LINT - lint_end_function(); -#endif /* LINT */ - } -; +/* + * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ +/* $Id$ */ +/* 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 "parameters.h" +#include +#include "arith.h" +#include "LLlex.h" +#include "label.h" +#include "type.h" +#include "declar.h" +#include "decspecs.h" +#include "code.h" +#include "expr.h" +#include "def.h" +#include "idf.h" +#include "declarator.h" +#include "stack.h" +#include "proto.h" +#include "error.h" +#ifdef LINT +#include "l_lint.h" +#endif /* LINT */ + +} + +control_if_expression + { + struct expr *exprX; + } +: + constant_expression(&exprX) + { + } +; + +/* 3.7 */ +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. + + With the introduction of prototypes, extra problems for the scope + administration were introduced as well. We can have, for example, + int x(double x); + and + int x(double x) { ... use(x) ... } + In the first case, the parameter name can be forgotten, whereas in + the second case, the parameter should have a block scope. The + problem lies in the fact that the parameter's type is known before + the type of the function, which causes the def structure to be on + the end of the list. Our solution is as follows: + 1- In case of a declaration, throw the parameter identifier away + before the declaration of the outer x. + 2- In case of a definition, the function begin_proc() changes the + def list for the identifier. This means that declare_idf() + contains an extra test in case we already saw a declaration of + such a function, because this function is called before + begin_proc(). +*/ + +external_definition + { struct decspecs Ds; + struct declarator Dc; + } +: + { Ds = null_decspecs; + Dc = null_declarator; + } + [ %if (DOT != IDENTIFIER || AHEAD == IDENTIFIER) + decl_specifiers(&Ds) + | + {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) + | + { if (! Ds.ds_sc_given && ! Ds.ds_typequal && + Ds.ds_notypegiven) { + strict("declaration specifiers missing"); + } + } + non_function(&Ds, &Dc) + ] + | + { if (! Ds.ds_sc_given && ! Ds.ds_typequal && + Ds.ds_notypegiven) { + strict("declaration missing"); + } + } + ';' + ] + {remove_declarator(&Dc); flush_strings(); } +; + +non_function(register struct decspecs *ds; register struct declarator *dc;) +: + { reject_params(dc); + } + [ + initializer(dc->dc_idf, ds->ds_sc) + | + { code_declaration(dc->dc_idf, (struct expr *) 0, level, ds->ds_sc); } + ] + { +#ifdef LINT + lint_non_function_decl(ds, dc); +#endif /* LINT */ + } + [ + ',' + init_declarator(ds) + ]* + ';' +; + +/* 3.7.1 */ +function(struct decspecs *ds; struct declarator *dc;) + { + arith fbytes; + register struct idf *idf = dc->dc_idf; + } +: + { +#ifdef LINT + lint_start_function(); +#endif /* LINT */ + idf_initialized(idf); + stack_level(); /* L_FORMAL1 declarations */ + declare_params(dc); + begin_proc(ds, idf); /* sets global function info */ + stack_level(); /* L_FORMAL2 declarations */ + declare_protos(dc); + } + declaration* + { + check_formals(idf, dc); /* check style-mixtures */ + declare_formals(idf, &fbytes); +#ifdef LINT + lint_formals(); +#endif /* LINT */ + } + compound_statement + { + end_proc(fbytes); +#ifdef LINT + lint_implicit_return(); +#endif /* LINT */ + unstack_level(); /* L_FORMAL2 declarations */ +#ifdef LINT + lint_end_formals(); +#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 index ff99ba98c..a9812b196 100644 --- a/lang/cem/cemcom.ansi/proto.c +++ b/lang/cem/cemcom.ansi/proto.c @@ -23,20 +23,24 @@ #include "declar.h" #include "decspecs.h" #include "proto.h" +#include "error.h" +#include "ch3.h" extern char options[]; -void -check_for_void(pl) - register struct proto *pl; +void check_for_void(register struct proto *pl) { register int errcnt = 0; - if (!pl) return; - if ((pl->pl_flag & PL_VOID) && !(pl->next)) return; + if (!pl) + return; + if ((pl->pl_flag & PL_VOID) && !(pl->next)) + return; - while (pl) { - if (pl->pl_flag & PL_VOID) { + while (pl) + { + if (pl->pl_flag & PL_VOID) + { if (!errcnt && !(pl->pl_flag & PL_ERRGIVEN)) error("illegal use of void in argument list"); pl->pl_flag |= PL_ERRGIVEN; @@ -46,37 +50,35 @@ check_for_void(pl) } } -add_proto(pl, ds, dc, lvl) - struct proto *pl; - struct decspecs *ds; - struct declarator *dc; - int lvl; +void add_proto(struct proto *pl, struct decspecs *ds, struct declarator *dc, + int lvl) { /* 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. - */ + 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 = dc->dc_idf; - register struct def *def = idf ? idf->id_def : (struct def *)0; + register struct def *def = idf ? idf->id_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); + assert(ds->ds_type != (struct type * )0); pl->pl_flag = PL_FORMAL; type = declare_type(ds->ds_type, dc); - if (type->tp_size < (arith)0 && actual_declaration(sc, type)) { + if (type->tp_size < (arith) 0 && actual_declaration(sc, type)) + { extern char *symbol2str(); if (type->tp_fund != VOID) error("unknown %s-type", symbol2str(type->tp_fund)); - else { - if (idf != (struct idf *)0 - || ds->ds_sc_given - || ds->ds_typequal) { + else + { + if (idf != (struct idf *) 0 || ds->ds_sc_given || ds->ds_typequal) + { error("illegal use of void in argument list"); pl->pl_flag |= PL_ERRGIVEN; } @@ -84,43 +86,54 @@ add_proto(pl, ds, dc, lvl) pl->pl_flag |= PL_VOID; } } - if (ds->ds_sc_given && ds->ds_sc != REGISTER) { - if (!(pl->pl_flag & PL_ERRGIVEN)) { - if (ds->ds_sc != AUTO) { - error("illegal storage class in parameter declaration"); - } else { - warning("illegal storage class in parameter declaration"); - } + if (ds->ds_sc_given && ds->ds_sc != REGISTER) + { + if (!(pl->pl_flag & PL_ERRGIVEN)) + { + if (ds->ds_sc != AUTO) + { + error("illegal storage class in parameter declaration"); + } + else + { + warning("illegal storage class in parameter declaration"); + } } } /* Perform some special conversions for parameters. - */ - if (type->tp_fund == FUNCTION) { + */ + if (type->tp_fund == FUNCTION) + { type = construct_type(POINTER, type, 0, (arith) 0, NO_PROTO); - } else if (type->tp_fund == ARRAY) { + } + else if (type->tp_fund == ARRAY) + { type = construct_type(POINTER, type->tp_up, 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 == lvl /* || def->df_level < L_PROTO */ )) { + 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 == lvl /* || def->df_level < L_PROTO */)) + { /* redeclaration at the same level */ error("parameter %s redeclared", idf->id_text); - } else if (idf != (struct idf *)0) { + } + else if (idf != (struct idf *) 0) + { /* New definition, redefinition hides earlier one - */ + */ register struct def *newdef = new_def(); - + newdef->next = def; newdef->df_level = lvl; newdef->df_sc = sc; @@ -133,28 +146,28 @@ add_proto(pl, ds, dc, lvl) /* 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. - */ + 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); } @@ -163,35 +176,33 @@ add_proto(pl, ds, dc, lvl) pl->pl_type = type; } -struct tag * -gettag(tp, idpp) -struct type *tp; -struct idf **idpp; +static struct tag * gettag(struct type *tp, struct idf **idpp) { - struct tag *tg = (struct tag *)0; + struct tag *tg = (struct tag *) 0; register int fund = tp->tp_fund; - while (fund == FIELD || fund == POINTER - || fund == ARRAY || fund == FUNCTION) { - tp = tp->tp_up; - fund = tp->tp_fund; - } + while (fund == FIELD || fund == POINTER || fund == ARRAY || fund == FUNCTION) + { + tp = tp->tp_up; + fund = tp->tp_fund; + } *idpp = tp->tp_idf; - switch(tp->tp_fund) { + switch (tp->tp_fund) + { case ENUM: case UNION: - case STRUCT: tg = tp->tp_idf->id_tag; break; + case STRUCT: + tg = tp->tp_idf->id_tag; + break; } return tg; } - -declare_protos(dc) - register struct declarator *dc; +void declare_protos(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. - */ + 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; @@ -200,31 +211,39 @@ declare_protos(dc) #ifdef DEBUG if (options['t']) - dumpidftab("start declare_protos", 0); + dumpidftab("start declare_protos", 0); #endif /* DEBUG */ du = dc->dc_decl_unary; - while (du) { - if (du->du_fund == FUNCTION) { - if (du->next != (struct decl_unary *) 0) { + while (du) + { + if (du->du_fund == FUNCTION) + { + if (du->next != (struct decl_unary *) 0) + { remove_proto_idfs(du->du_proto); du->du_proto = 0; - } else break; + } + else + break; } du = du->next; } pl = du ? du->du_proto : NO_PROTO; - if (pl) { + if (pl) + { #if 0 /* the id_proto member is deleted (???) */ idf->id_proto = 0; #endif /* 0 */ - do { + do + { struct tag *tg; struct idf *idp = 0; type = pl->pl_type; /* `...' only for type checking */ - if (pl->pl_flag & PL_ELLIPSIS) { + if (pl->pl_flag & PL_ELLIPSIS) + { pl = pl->next; continue; } @@ -233,14 +252,15 @@ declare_protos(dc) if (type->tp_fund == VOID) break; - if (!pl->pl_idf || !(def = pl->pl_idf->id_def)) { + if (!pl->pl_idf || !(def = pl->pl_idf->id_def)) + { error("no parameter identifier supplied"); pl = pl->next; continue; } /* Postponed storage class checking. - */ + */ if (def->df_sc == 0) error("illegal storage class in parameter declaration"); @@ -249,7 +269,8 @@ declare_protos(dc) pl = pl->next; tg = gettag(type, &idp); - if (tg && tg->tg_level <= L_PROTO) { + if (tg && tg->tg_level <= L_PROTO) + { tg->tg_level = L_FORMAL2; stack_idf(idp, stl); } @@ -257,43 +278,47 @@ declare_protos(dc) } #ifdef DEBUG if (options['t']) - dumpidftab("end declare_protos", 0); + dumpidftab("end declare_protos", 0); #endif /* DEBUG */ } - -void -update_proto(tp, otp) - register struct type *tp, *otp; +void update_proto(register struct type *tp, register struct type *otp) { /* This routine performs the proto type updates. - Consider the following code: + Consider the following code: - int f(double g()); - int f(double g(int f(), int)); - int f(double g(int f(long double), int)); + 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. - */ + 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 (tp == otp) return; - if (!tp || !otp) return; + if (tp == otp) + return; + if (!tp || !otp) + return; - while (tp->tp_fund != FUNCTION) { - if (tp->tp_fund != POINTER && tp->tp_fund != ARRAY) return; + while (tp->tp_fund != FUNCTION) + { + if (tp->tp_fund != POINTER && tp->tp_fund != ARRAY) + return; tp = tp->tp_up; otp = otp->tp_up; - if (!tp) return; + if (!tp) + return; } pl = tp->tp_proto; opl = otp->tp_proto; - if (pl && opl) { + if (pl && opl) + { /* both have prototypes */ - while (pl && opl) { + while (pl && opl) + { update_proto(pl->pl_type, opl->pl_type); pl = pl->next; opl = opl->next; @@ -302,9 +327,13 @@ update_proto(tp, otp) * a typedef. */ otp->tp_proto = tp->tp_proto; - } else if (opl) { + } + else if (opl) + { /* old decl has type */ - } else if (pl) { + } + else if (pl) + { otp->tp_proto = pl; } @@ -314,39 +343,44 @@ update_proto(tp, otp) /* struct/union and enum tags can be declared inside prototypes * remove them from the symbol-table */ -void -remove_proto_tag(tp) -struct type *tp; +static void remove_proto_tag(struct type *tp) { register struct idf *ident; register struct tag *tgp, **tgpp; register int fund = tp->tp_fund; - while (fund == FIELD || fund == POINTER - || fund == ARRAY || fund == FUNCTION) { + while (fund == FIELD || fund == POINTER || fund == ARRAY || fund == FUNCTION) + { tp = tp->tp_up; fund = tp->tp_fund; } ident = tp->tp_idf; - switch (tp->tp_fund) { + switch (tp->tp_fund) + { case ENUM: case STRUCT: - case UNION: tgpp = &(ident->id_tag); break; - default: return; + case UNION: + tgpp = &(ident->id_tag); + break; + default: + return; } - while((*tgpp) && (*tgpp)->tg_type != tp) { + while ((*tgpp) && (*tgpp)->tg_type != tp) + { tgpp = &((*tgpp)->next); } - if (!*tgpp) return; + if (!*tgpp) + return; tgp = *tgpp; - if (tgp->tg_level > L_PROTO) return; + if (tgp->tg_level > L_PROTO) + return; #ifdef DEBUG if (options['t']) - print("Removing idf %s from list\n", + print("Removing idf %s from list\n", ident->id_text); #endif @@ -354,52 +388,55 @@ struct type *tp; free_tag(tgp); } -remove_proto_idfs(pl) - register struct proto *pl; +/* Remove all the identifier definitions from the + prototype list. */ +void remove_proto_idfs(register struct proto *pl) { - /* Remove all the identifier definitions from the - prototype list. - */ + register struct def *def; - while (pl) { - if (pl->pl_idf) { + while (pl) + { + if (pl->pl_idf) + { #ifdef DEBUG if (options['t']) - print("Removing idf %s from list\n", + print("Removing idf %s from list\n", pl->pl_idf->id_text); #endif def = pl->pl_idf->id_def; - if (def && def->df_level <= L_PROTO) { + if (def && def->df_level <= L_PROTO) + { pl->pl_idf->id_def = def->next; free_def(def); } pl->pl_idf = (struct idf *) 0; } - if (pl->pl_type) { + if (pl->pl_type) + { remove_proto_tag(pl->pl_type); } pl = pl->next; } } -void -call_proto(expp) - register struct expr **expp; +void call_proto(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. - */ + 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; - static struct proto ellipsis = { 0, 0, 0, PL_ELLIPSIS }; + static struct proto ellipsis = + { 0, 0, 0, PL_ELLIPSIS }; - if (left != NILEXPR) { /* in case of an error */ + if (left != NILEXPR) + { /* in case of an error */ register struct type *tp = left->ex_type; while (tp && tp->tp_fund != FUNCTION && tp != error_type) @@ -408,17 +445,20 @@ call_proto(expp) pl = tp->tp_proto; } - if (right != NILEXPR) { /* function call with parameters */ + if (right != NILEXPR) + { /* function call with parameters */ register struct expr **ep = &((*expp)->OP_RIGHT); register int ecnt = 0, pcnt = 0; struct expr **estack[NPARAMS]; struct proto *pstack[NPARAMS]; /* stack up the parameter expressions */ - while (right->ex_class == Oper && right->OP_OPER == PARCOMMA) { + while (right->ex_class == Oper && right->OP_OPER == PARCOMMA) + { if (ecnt == STDC_NPARAMS) expr_strict(right, "number of parameters exceeds ANSI limit"); - if (ecnt >= NPARAMS-1) { + if (ecnt >= NPARAMS - 1) + { expr_error(right, "too many parameters"); return; } @@ -429,45 +469,56 @@ call_proto(expp) estack[ecnt] = ep; /* Declarations like int f(void) do not expect any - parameters. - */ - if (pl && pl->pl_flag & PL_VOID) { + parameters. + */ + if (pl && pl->pl_flag & PL_VOID) + { expr_strict(*expp, "no parameters expected"); pl = NO_PROTO; } /* stack up the prototypes */ - if (pl) { + if (pl) + { pcnt--; - do { + do + { /* stack prototypes */ pstack[++pcnt] = pl; pl = pl->next; } while (pl); } - else { + else + { pstack[0] = &ellipsis; } - for (ecnt; ecnt >= 0; ecnt--) { + 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) { - expr_error(*expp, "more parameters than specified in prototype"); + are checked and converted. The parameters that + fall under the ellipsis clause are neither + checked nor converted ! + */ + if (pcnt < 0) + { + expr_error(*expp, + "more parameters than specified in prototype"); break; } - else if (!(pstack[pcnt]->pl_flag & PL_ELLIPSIS)) { - ch3cast(estack[ecnt],CASTAB,pstack[pcnt]->pl_type); + else if (!(pstack[pcnt]->pl_flag & PL_ELLIPSIS)) + { + ch3cast(estack[ecnt], CASTAB, pstack[pcnt]->pl_type); pcnt--; - } else + } + else any2parameter(estack[ecnt]); } if (pcnt > 0 || (pcnt == 0 && !(pstack[0]->pl_flag & PL_ELLIPSIS))) expr_error(*expp, "fewer parameters than specified in prototype"); - } else { + } + else + { if (pl && !(pl->pl_flag & PL_VOID)) expr_error(*expp, "fewer parameters than specified in prototype"); } diff --git a/lang/cem/cemcom.ansi/proto.str b/lang/cem/cemcom.ansi/proto.str index 03219deee..690588265 100644 --- a/lang/cem/cemcom.ansi/proto.str +++ b/lang/cem/cemcom.ansi/proto.str @@ -2,6 +2,9 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef PROTO_H +#define PROTO_H + /* $Id$ */ /* PARAMETER TYPE LIST DEFINITION */ @@ -20,3 +23,20 @@ struct proto { #define PL_ERRGIVEN 0x08 /* ALLOCDEF "proto" 20 */ + +/* Forward structure declarations */ +struct expr; +struct type; +struct declarator; +struct decspecs; + + +void remove_proto_idfs(register struct proto *pl); +void call_proto(register struct expr **expp); +void update_proto(register struct type *tp, register struct type *otp); +void declare_protos(register struct declarator *dc); +void add_proto(struct proto *pl, struct decspecs *ds, struct declarator *dc, + int lvl); +void check_for_void(register struct proto *pl); + +#endif diff --git a/lang/cem/cemcom.ansi/skip.c b/lang/cem/cemcom.ansi/skip.c index b617f08e9..8dd6ee837 100644 --- a/lang/cem/cemcom.ansi/skip.c +++ b/lang/cem/cemcom.ansi/skip.c @@ -10,9 +10,10 @@ #include "LLlex.h" #include "class.h" #include "input.h" +#include "skip.h" -SkipToNewLine() +int SkipToNewLine(void) { register int ch; register int garbage = 0; diff --git a/lang/cem/cemcom.ansi/skip.h b/lang/cem/cemcom.ansi/skip.h new file mode 100644 index 000000000..52ef8cbda --- /dev/null +++ b/lang/cem/cemcom.ansi/skip.h @@ -0,0 +1,13 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-07 + * + */ +#ifndef SKIP_H_ +#define SKIP_H_ + +int SkipToNewLine(void); + +#endif /* SKIP_H_ */ diff --git a/lang/cem/cemcom.ansi/stab.c b/lang/cem/cemcom.ansi/stab.c index f80b360b4..a7a7928c9 100644 --- a/lang/cem/cemcom.ansi/stab.c +++ b/lang/cem/cemcom.ansi/stab.c @@ -20,6 +20,7 @@ #include #include +#include "stab.h" #include "idf.h" #include "LLlex.h" #include "stack.h" @@ -29,34 +30,34 @@ #include "field.h" #include "Lpars.h" #include "level.h" +#include "print.h" -extern long full_mask[]; -extern char *sprint(); +extern long full_mask[]; #define INCR_SIZE 64 -static struct db_str { - unsigned sz; - char *base; - char *currpos; +static struct db_str +{ + unsigned sz; + char *base; + char *currpos; } db_str; -static -create_db_str() +static void create_db_str(void) { - if (! db_str.base) { + if (!db_str.base) + { db_str.base = Malloc(INCR_SIZE); db_str.sz = INCR_SIZE; } db_str.currpos = db_str.base; } -static -addc_db_str(c) - int c; +static void addc_db_str(int c) { int df = db_str.currpos - db_str.base; - if (df >= db_str.sz-1) { + if (df >= db_str.sz - 1) + { db_str.sz += INCR_SIZE; db_str.base = Realloc(db_str.base, db_str.sz); db_str.currpos = db_str.base + df; @@ -65,34 +66,35 @@ addc_db_str(c) *db_str.currpos = '\0'; } -static -adds_db_str(s) - char *s; +static void adds_db_str(char *s) { - while (*s) addc_db_str(*s++); + while (*s) + addc_db_str(*s++); } -static void -stb_type(tp) - register struct type *tp; +static void stb_type(register struct type *tp) { - char buf[128]; - static int stb_count; - long l; + char buf[128]; + static int stb_count; + long l; - if (tp->tp_dbindex > 0) { + if (tp->tp_dbindex > 0) + { adds_db_str(sprint(buf, "%d", tp->tp_dbindex)); return; } - if (tp->tp_dbindex < 0 && tp->tp_size < 0) { + if (tp->tp_dbindex < 0 && tp->tp_size < 0) + { adds_db_str(sprint(buf, "%d", -tp->tp_dbindex)); return; } - if (tp->tp_dbindex <= 0) { + if (tp->tp_dbindex <= 0) + { tp->tp_dbindex = ++stb_count; } adds_db_str(sprint(buf, "%d=", tp->tp_dbindex)); - switch(tp->tp_fund) { + switch (tp->tp_fund) + { /* simple types ... */ case VOID: adds_db_str(sprint(buf, "%d", void_type->tp_dbindex)); @@ -101,49 +103,44 @@ stb_type(tp) case LONG: case CHAR: case SHORT: - l = full_mask[(int)tp->tp_size]; - if (tp->tp_unsigned) { - adds_db_str(sprint(buf, - "r%d;0;%ld", - tp->tp_dbindex, - l)); + l = full_mask[(int) tp->tp_size]; + if (tp->tp_unsigned) + { + adds_db_str(sprint(buf, "r%d;0;%ld", tp->tp_dbindex, l)); } - else { - l &= ~ (1L << ((int)tp->tp_size * 8 - 1)); - adds_db_str(sprint(buf, - "r%d;%ld;%ld", - tp->tp_dbindex, - -l-1, - l)); + else + { + l &= ~(1L << ((int) tp->tp_size * 8 - 1)); + adds_db_str(sprint(buf, "r%d;%ld;%ld", tp->tp_dbindex, -l - 1, l)); } break; case FLOAT: case DOUBLE: case LNGDBL: - adds_db_str(sprint(buf, - "r%d;%ld;0", - tp->tp_dbindex, - (long)tp->tp_size)); + adds_db_str( + sprint(buf, "r%d;%ld;0", tp->tp_dbindex, (long) tp->tp_size)); break; - /* constructed types ... */ + /* constructed types ... */ case POINTER: addc_db_str('*'); stb_type(tp->tp_up); break; case ARRAY: - if (tp->tp_size > 0) { + if (tp->tp_size > 0) + { adds_db_str("ar"); stb_type(int_type); - adds_db_str(sprint(buf, ";0;%ld;", tp->tp_size / tp->tp_up->tp_size - 1)); + adds_db_str( + sprint(buf, ";0;%ld;", + tp->tp_size / tp->tp_up->tp_size - 1)); stb_type(tp->tp_up); } break; case ENUM: - if (tp->tp_size < 0) { - adds_db_str(sprint(buf, - "xe%s:", - tp->tp_idf->id_text)); + if (tp->tp_size < 0) + { + adds_db_str(sprint(buf, "xe%s:", tp->tp_idf->id_text)); tp->tp_dbindex = -tp->tp_dbindex; break; } @@ -151,15 +148,16 @@ stb_type(tp) { register struct stack_entry *se = local_level->sl_entry; - while (se) { - register struct def *edef = se->se_idf->id_def; - while (edef) { - if (edef->df_type == tp && - edef->df_sc == ENUM) { - adds_db_str(sprint(buf, - "%s:%ld,", - se->se_idf->id_text, - edef->df_address)); + while (se) + { + register struct def *edef = se->se_idf->id_def; + while (edef) + { + if (edef->df_type == tp && edef->df_sc == ENUM) + { + adds_db_str( + sprint(buf, "%s:%ld,", se->se_idf->id_text, + edef->df_address)); } edef = edef->next; } @@ -170,37 +168,39 @@ stb_type(tp) break; case STRUCT: case UNION: - if (tp->tp_size < 0) { - adds_db_str(sprint(buf, - "x%c%s:", - tp->tp_fund == STRUCT ? 's' : 'u', - tp->tp_idf->id_text)); + if (tp->tp_size < 0) + { + adds_db_str( + sprint(buf, "x%c%s:", tp->tp_fund == STRUCT ? 's' : 'u', + tp->tp_idf->id_text)); tp->tp_dbindex = -tp->tp_dbindex; break; } - adds_db_str(sprint(buf, - "%c%ld", - tp->tp_fund == STRUCT ? 's' : 'u', - tp->tp_size)); + adds_db_str( + sprint(buf, "%c%ld", tp->tp_fund == STRUCT ? 's' : 'u', + tp->tp_size)); { - register struct sdef *sdef = tp->tp_sdef; + register struct sdef *sdef = tp->tp_sdef; - while (sdef) { + while (sdef) + { adds_db_str(sdef->sd_idf->id_text); addc_db_str(':'); - if (sdef->sd_type->tp_fund == FIELD) { + if (sdef->sd_type->tp_fund == FIELD) + { stb_type(sdef->sd_type->tp_up); - adds_db_str(sprint(buf, - ",%ld,%ld;", - sdef->sd_offset*8+sdef->sd_type->tp_field->fd_shift, - sdef->sd_type->tp_field->fd_width)); + adds_db_str( + sprint(buf, ",%ld,%ld;", + sdef->sd_offset * 8 + + sdef->sd_type->tp_field->fd_shift, + sdef->sd_type->tp_field->fd_width)); } - else { + else + { stb_type(sdef->sd_type); - adds_db_str(sprint(buf, - ",%ld,%ld;", - sdef->sd_offset*8, - sdef->sd_type->tp_size*8)); + adds_db_str( + sprint(buf, ",%ld,%ld;", sdef->sd_offset * 8, + sdef->sd_type->tp_size * 8)); } sdef = sdef->sd_sdef; } @@ -213,9 +213,7 @@ stb_type(tp) } } -stb_tag(tg, str) - register struct tag *tg; - char *str; +void stb_tag(register struct tag *tg, char *str) { create_db_str(); adds_db_str(str); @@ -223,16 +221,12 @@ stb_tag(tg, str) stb_type(tg->tg_type); addc_db_str(';'); C_ms_stb_cst(db_str.base, - N_LSYM, - tg->tg_type == void_type || tg->tg_type->tp_size >= 32767 - ? 0 - : (int)tg->tg_type->tp_size, - (arith) 0); + N_LSYM, + tg->tg_type == void_type || tg->tg_type->tp_size >= 32767 ? + 0 : (int) tg->tg_type->tp_size, (arith) 0); } -stb_typedef(tp, str) - register struct type *tp; - char *str; +void stb_typedef(register struct type *tp, char *str) { create_db_str(); adds_db_str(str); @@ -240,23 +234,19 @@ stb_typedef(tp, str) stb_type(tp); addc_db_str(';'); C_ms_stb_cst(db_str.base, - N_LSYM, - tp == void_type || tp->tp_size >= 32767 - ? 0 - : (int)tp->tp_size, - (arith) 0); + N_LSYM, tp == void_type || tp->tp_size >= 32767 ? 0 : (int) tp->tp_size, + (arith) 0); } -stb_string(df, kind, str) - register struct def *df; - char *str; +void stb_string(register struct def *df, int kind, char* str) { - register struct type *tp = df->df_type; + register struct type *tp = df->df_type; create_db_str(); adds_db_str(str); addc_db_str(':'); - switch(kind) { + switch (kind) + { case FUNCTION: addc_db_str(df->df_sc == STATIC ? 'f' : 'F'); stb_type(tp->tp_up); @@ -264,40 +254,50 @@ stb_string(df, kind, str) C_ms_stb_pnam(db_str.base, N_FUN, 1 /* proclevel */, str); break; default: - if (df->df_sc == FORMAL || - (df->df_sc == REGISTER && df->df_address >= 0)) { - /* value parameter */ + if (df->df_sc == FORMAL + || (df->df_sc == REGISTER && df->df_address >= 0)) + { + /* value parameter */ addc_db_str('p'); stb_type(tp); addc_db_str(';'); C_ms_stb_cst(db_str.base, N_PSYM, 0, df->df_address); } - else if (df->df_sc != AUTO && df->df_sc != REGISTER) { - /* global */ + else if (df->df_sc != AUTO && df->df_sc != REGISTER) + { + /* global */ int stabtp = df->df_initialized ? N_STSYM : N_LCSYM; - if (df->df_sc == STATIC) { - if (df->df_level >= L_LOCAL) { + if (df->df_sc == STATIC) + { + if (df->df_level >= L_LOCAL) + { addc_db_str('V'); } - else { + else + { addc_db_str('S'); } } - else { + else + { addc_db_str('G'); } stb_type(tp); addc_db_str(';'); - if (df->df_sc == STATIC && df->df_level >= L_LOCAL) { - C_ms_stb_dlb(db_str.base, stabtp, 0, (label) df->df_address, (arith) 0); + if (df->df_sc == STATIC && df->df_level >= L_LOCAL) + { + C_ms_stb_dlb(db_str.base, stabtp, 0, (label) df->df_address, + (arith) 0); } - else { + else + { C_ms_stb_dnam(db_str.base, stabtp, 0, str, (arith) 0); } } - else { /* local variable */ - stb_type(tp); /* assign type num to avoid - difficult to parse string */ + else + { /* local variable */ + stb_type(tp); /* assign type num to avoid + difficult to parse string */ addc_db_str(';'); C_ms_stb_cst(db_str.base, N_LSYM, 0, df->df_address); } diff --git a/lang/cem/cemcom.ansi/stab.h b/lang/cem/cemcom.ansi/stab.h new file mode 100644 index 000000000..5f584adf8 --- /dev/null +++ b/lang/cem/cemcom.ansi/stab.h @@ -0,0 +1,20 @@ +/* Copyright (c) 2019 ACK Project. + * See the copyright notice in the ACK home directory, + * in the file "Copyright". + * + * Created on: 2019-02-07 + * + */ +#ifndef STAB_H_ +#define STAB_H_ + + +struct def; +struct type; +struct tag; + +void stb_tag(register struct tag *tg, char *str); +void stb_typedef(register struct type *tp, char *str); +void stb_string(register struct def *df, int kind, char* str); + +#endif /* STAB_H_ */ diff --git a/lang/cem/cemcom.ansi/stack.c b/lang/cem/cemcom.ansi/stack.c index c8616b86e..1d2cd699f 100644 --- a/lang/cem/cemcom.ansi/stack.c +++ b/lang/cem/cemcom.ansi/stack.c @@ -22,6 +22,9 @@ #include "struct.h" #include "level.h" #include "mes.h" +#include "code.h" +#include "util.h" +#include "error.h" /* #include */ @@ -41,7 +44,7 @@ struct stack_level *local_level = &UniversalLevel; int level; /* Always equal to local_level->sl_level. */ -stack_level() { +void stack_level(void) { /* A new level is added on top of the identifier stack. */ register struct stack_level *stl = new_stack_level(); @@ -57,10 +60,9 @@ stack_level() { #endif /* LINT */ } -void -stack_idf(idf, stl) - struct idf *idf; - register struct stack_level *stl; +void stack_idf( + struct idf *idf, + register struct stack_level *stl) { /* The identifier idf is inserted in the stack on level stl, but only if it is not already present at this level. @@ -81,8 +83,7 @@ stack_idf(idf, stl) stl->sl_entry = se; } -struct stack_level * -stack_level_of(lvl) +struct stack_level *stack_level_of(int lvl) { /* The stack_level corresponding to level lvl is returned. The stack should probably be an array, to be extended with @@ -100,7 +101,7 @@ stack_level_of(lvl) return stl; } -unstack_level() +void unstack_level(void) { /* The top level of the identifier stack is removed. */ @@ -174,7 +175,7 @@ unstack_level() #endif /* DEBUG */ } -unstack_world() +void unstack_world(void) { /* The global level of identifiers is scanned, and final decisions are taken about such issues as @@ -263,14 +264,13 @@ unstack_world() extern char *nmlist; /* BAH! -- main.c */ static File *nfp = 0; -open_name_list() +void open_name_list(void) { if (nmlist && sys_open(nmlist, OP_WRITE, &nfp) == 0) fatal("cannot create namelist %s", nmlist); } -namelist(nm) - char *nm; +void namelist(char *nm) { if (nmlist) { sys_write(nfp, nm, strlen(nm)); diff --git a/lang/cem/cemcom.ansi/stack.str b/lang/cem/cemcom.ansi/stack.str index ddb38c56c..a7f59d1db 100644 --- a/lang/cem/cemcom.ansi/stack.str +++ b/lang/cem/cemcom.ansi/stack.str @@ -2,9 +2,14 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef STACK_H_ +#define STACK_H_ + /* $Id$ */ /* IDENTIFIER STACK DEFINITIONS */ +struct idf; + /* 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. @@ -30,5 +35,26 @@ struct stack_entry { /* ALLOCDEF "stack_entry" 50 */ extern struct stack_level *local_level; -extern struct stack_level *stack_level_of(); extern int level; + +/* A new level is added on top of the identifier stack. */ +void stack_level(void); +/* The identifier idf is inserted in the stack on level stl, + but only if it is not already present at this level. +*/ +void stack_idf(struct idf *idf, register struct stack_level *stl); +/*The stack_level corresponding to level lvl is returned. + The stack should probably be an array, to be extended with + realloc where needed. +*/ +struct stack_level *stack_level_of(int lvl); +/* The top level of the identifier stack is removed. */ +void unstack_level(void); +void unstack_world(void); + +#ifdef GEN_NM_LIST +void open_name_list(void); +void namelist(char *nm); +#endif /* GEN_NM_LIST */ + +#endif diff --git a/lang/cem/cemcom.ansi/statement.g b/lang/cem/cemcom.ansi/statement.g index 9eb60d2ed..3d1dcd4f2 100644 --- a/lang/cem/cemcom.ansi/statement.g +++ b/lang/cem/cemcom.ansi/statement.g @@ -1,505 +1,506 @@ -/* - * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. - * See the copyright notice in the ACK home directory, in the file "Copyright". - */ -/* $Id$ */ -/* STATEMENT SYNTAX PARSER */ - -{ -#include "parameters.h" -#ifndef LINT -#include -#else -#include "l_em.h" -#include "l_lint.h" -#endif /* LINT */ - -#include -#include "idf.h" -#include "arith.h" -#include "LLlex.h" -#include "type.h" -#include "label.h" -#include "expr.h" -#include "code.h" -#include "stack.h" -#include "def.h" -#ifdef DBSYMTAB -#include -#endif /* DBSYMTAB */ - -extern int level; -extern char options[]; -} - -/* 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. - */ - -/* 3.6 */ -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); - } -; - -/* 3.6.1 (partially) */ -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_label->df_address); - } -; - -/* 3.6.4.1 */ -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 */ - } - ] -; - -/* 3.6.5.3 */ -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); - } - } - else { - code_expr(expr, RVAL, TRUE, l_body, l_break); - C_df_ilb(l_body); - } -#ifdef LINT - start_while_stmt(expr); -#endif /* LINT */ - } - ')' - statement - { - C_bra(l_continue); - C_df_ilb(l_break); - unstack_stmt(); - free_expression(expr); -#ifdef LINT - end_loop_body(); - end_loop_stmt(); -#endif /* LINT */ - } -; - -/* 3.6.5.2 */ -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_do_stmt(); -#endif /* LINT */ - } - statement - WHILE - '(' - { -#ifdef LINT - end_loop_body(); -#endif /* LINT */ - 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); - } -; - -/* 3.6.5.3 */ -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(); - } -: - 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); - } - } - else { - code_expr(e_test, RVAL, TRUE, l_body, l_break); - C_df_ilb(l_body); - } - } - ]? - ';' - expression(&e_incr)? - ')' - { -#ifdef LINT - start_for_stmt(e_test); -#endif /* LINT */ - } - statement - { -#ifdef LINT - end_loop_body(); -#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); -#ifdef LINT - end_loop_stmt(); -#endif /* LINT */ - } -; - -/* 3.6.4.2 */ -switch_statement - { - struct expr *expr; - } -: - SWITCH - '(' - expression(&expr) - { - code_startswitch(&expr); -#ifdef LINT - start_switch_part(is_cp_cst(expr)); -#endif /* LINT */ - } - ')' - statement - { -#ifdef LINT - end_switch_stmt(); -#endif /* LINT */ - code_endswitch(); - free_expression(expr); - } -; - -/* 3.6.1 (partially) */ -case_statement - { - struct expr *expr; - } -: - CASE - constant_expression(&expr) - { -#ifdef LINT - lint_case_stmt(0); -#endif /* LINT */ - code_case(expr); - free_expression(expr); - } - ':' - statement -; - -/* 3.6.1 (partially) */ -default_statement -: - DEFAULT - { -#ifdef LINT - lint_case_stmt(1); -#endif /* LINT */ - code_default(); - } - ':' - statement -; - -/* 3.6.6.4 */ -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(VALRETURNED); -#endif /* LINT */ - } - | - empty - { - do_return(); -#ifdef LINT - lint_return_stmt(NOVALRETURNED); -#endif /* LINT */ - } - ] - ';' -; - -/* 3.6.6.1 (partially) */ -jump - { struct idf *idf; - } -: - GOTO - identifier(&idf) - ';' - { - apply_label(idf); - C_bra((label)idf->id_label->df_address); -#ifdef LINT - lint_jump_stmt(idf); -#endif /* LINT */ - } -; - -/* 3.6.2 */ -compound_statement - { -#ifdef DBSYMTAB - static int brc_level = 1; - int decl_seen = brc_level == 1; -#endif /* DBSYMTAB */ - } -: - '{' - { - stack_level(); - } - [%while ((DOT != IDENTIFIER && AHEAD != ':') || - (DOT == IDENTIFIER && AHEAD == IDENTIFIER)) - /* >>> conflict on TYPE_IDENTIFIER, IDENTIFIER */ - declaration - { -#ifdef DBSYMTAB - decl_seen++; -#endif /* DBSYMTAB */ - } - ]* - { -#ifdef DBSYMTAB - ++brc_level; - if (options['g'] && decl_seen) { - C_ms_std((char *) 0, N_LBRAC, brc_level); - } -#endif /* DBSYMTAB */ - } - [%persistent - statement - ]* - '}' - { - unstack_level(); -#ifdef DBSYMTAB - if (options['g'] && decl_seen) { - C_ms_std((char *) 0, N_RBRAC, brc_level); - } - brc_level--; -#endif /* DBSYMTAB */ - } -; +/* + * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. + * See the copyright notice in the ACK home directory, in the file "Copyright". + */ +/* $Id$ */ +/* STATEMENT SYNTAX PARSER */ + +{ +#include "parameters.h" +#ifndef LINT +#include +#else +#include "l_em.h" +#include "l_lint.h" +#endif /* LINT */ + +#include +#include "idf.h" +#include "arith.h" +#include "LLlex.h" +#include "type.h" +#include "label.h" +#include "expr.h" +#include "code.h" +#include "stack.h" +#include "def.h" +#include "switch.h" +#ifdef DBSYMTAB +#include +#endif /* DBSYMTAB */ + +extern int level; +extern char options[]; +} + +/* 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. + */ + +/* 3.6 */ +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); + } +; + +/* 3.6.1 (partially) */ +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_label->df_address); + } +; + +/* 3.6.4.1 */ +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 */ + } + ] +; + +/* 3.6.5.3 */ +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); + } + } + else { + code_expr(expr, RVAL, TRUE, l_body, l_break); + C_df_ilb(l_body); + } +#ifdef LINT + start_while_stmt(expr); +#endif /* LINT */ + } + ')' + statement + { + C_bra(l_continue); + C_df_ilb(l_break); + unstack_stmt(); + free_expression(expr); +#ifdef LINT + end_loop_body(); + end_loop_stmt(); +#endif /* LINT */ + } +; + +/* 3.6.5.2 */ +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_do_stmt(); +#endif /* LINT */ + } + statement + WHILE + '(' + { +#ifdef LINT + end_loop_body(); +#endif /* LINT */ + 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); + } +; + +/* 3.6.5.3 */ +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(); + } +: + 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); + } + } + else { + code_expr(e_test, RVAL, TRUE, l_body, l_break); + C_df_ilb(l_body); + } + } + ]? + ';' + expression(&e_incr)? + ')' + { +#ifdef LINT + start_for_stmt(e_test); +#endif /* LINT */ + } + statement + { +#ifdef LINT + end_loop_body(); +#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); +#ifdef LINT + end_loop_stmt(); +#endif /* LINT */ + } +; + +/* 3.6.4.2 */ +switch_statement + { + struct expr *expr; + } +: + SWITCH + '(' + expression(&expr) + { + code_startswitch(&expr); +#ifdef LINT + start_switch_part(is_cp_cst(expr)); +#endif /* LINT */ + } + ')' + statement + { +#ifdef LINT + end_switch_stmt(); +#endif /* LINT */ + code_endswitch(); + free_expression(expr); + } +; + +/* 3.6.1 (partially) */ +case_statement + { + struct expr *expr; + } +: + CASE + constant_expression(&expr) + { +#ifdef LINT + lint_case_stmt(0); +#endif /* LINT */ + code_case(expr); + free_expression(expr); + } + ':' + statement +; + +/* 3.6.1 (partially) */ +default_statement +: + DEFAULT + { +#ifdef LINT + lint_case_stmt(1); +#endif /* LINT */ + code_default(); + } + ':' + statement +; + +/* 3.6.6.4 */ +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(VALRETURNED); +#endif /* LINT */ + } + | + empty + { + do_return(); +#ifdef LINT + lint_return_stmt(NOVALRETURNED); +#endif /* LINT */ + } + ] + ';' +; + +/* 3.6.6.1 (partially) */ +jump + { struct idf *idf; + } +: + GOTO + identifier(&idf) + ';' + { + apply_label(idf); + C_bra((label)idf->id_label->df_address); +#ifdef LINT + lint_jump_stmt(idf); +#endif /* LINT */ + } +; + +/* 3.6.2 */ +compound_statement + { +#ifdef DBSYMTAB + static int brc_level = 1; + int decl_seen = brc_level == 1; +#endif /* DBSYMTAB */ + } +: + '{' + { + stack_level(); + } + [%while ((DOT != IDENTIFIER && AHEAD != ':') || + (DOT == IDENTIFIER && AHEAD == IDENTIFIER)) + /* >>> conflict on TYPE_IDENTIFIER, IDENTIFIER */ + declaration + { +#ifdef DBSYMTAB + decl_seen++; +#endif /* DBSYMTAB */ + } + ]* + { +#ifdef DBSYMTAB + ++brc_level; + if (options['g'] && decl_seen) { + C_ms_std((char *) 0, N_LBRAC, brc_level); + } +#endif /* DBSYMTAB */ + } + [%persistent + statement + ]* + '}' + { + unstack_level(); +#ifdef DBSYMTAB + if (options['g'] && decl_seen) { + C_ms_std((char *) 0, N_RBRAC, brc_level); + } + brc_level--; +#endif /* DBSYMTAB */ + } +; diff --git a/lang/cem/cemcom.ansi/stb.c b/lang/cem/cemcom.ansi/stb.c index 0a98e6725..4fcd26258 100644 --- a/lang/cem/cemcom.ansi/stb.c +++ b/lang/cem/cemcom.ansi/stb.c @@ -3,10 +3,10 @@ * See the copyright notice in the ACK home directory, in the file "Copyright". */ /* $Id$ */ -/* library routine for copying structs */ -__stb(n, f, t) - register char *f, *t; register n; + +/* library routine for copying structs */ +void __stb(register int n, register char *f, register char *t) { if (n > 0) do diff --git a/lang/cem/cemcom.ansi/stmt.str b/lang/cem/cemcom.ansi/stmt.str index feaa82fcd..aea09b36b 100644 --- a/lang/cem/cemcom.ansi/stmt.str +++ b/lang/cem/cemcom.ansi/stmt.str @@ -2,6 +2,9 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef STMT_H_ +#define STMT_H_ + /* $Id$ */ /* 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 */ @@ -12,3 +15,5 @@ struct stmt_block { }; /* ALLOCDEF "stmt_block" 5 */ + +#endif \ No newline at end of file diff --git a/lang/cem/cemcom.ansi/struct.c b/lang/cem/cemcom.ansi/struct.c index a36b11e20..fbba71a0e 100644 --- a/lang/cem/cemcom.ansi/struct.c +++ b/lang/cem/cemcom.ansi/struct.c @@ -19,16 +19,23 @@ #include "Lpars.h" #include "align.h" #include "level.h" +#include "ch3.h" #include "sizes.h" +#include "error.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; +static int field_busy = 0; extern char options[]; char *symbol2str(); -int lcm(); + +static void check_selector(register struct idf *, struct type *); +/* Greatest Common Divisor */ +static int gcd(register int , register int ); +/* Least Common Multiple */ +static int lcm(register int, register int); /* The semantics of the identification of structure/union tags is obscure. Some highly regarded compilers are found out to accept, @@ -51,13 +58,13 @@ int lcm(); 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; +void add_sel( /* 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, @@ -147,12 +154,11 @@ add_sel(stp, tp, idf, sdefpp, szp, fd) /* this is horrible */ } } -check_selector(idf, stp) - register struct idf *idf; - struct type *stp; /* the type of the struct */ +static void check_selector(register struct idf *idf, struct type *stp) { /* checks if idf occurs already as a selector in - struct or union *stp. + struct or union *stp. "stp" indicates the type + of the struct. */ register struct sdef *sdef = stp->tp_sdef; @@ -163,9 +169,7 @@ check_selector(idf, stp) } } -declare_struct(fund, idf, tpp) - register struct idf *idf; - struct type **tpp; +void declare_struct(int fund, 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 @@ -232,9 +236,9 @@ declare_struct(fund, idf, tpp) } } -apply_struct(fund, idf, tpp) - register struct idf *idf; - struct type **tpp; +void apply_struct(int fund, + 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 @@ -258,10 +262,9 @@ apply_struct(fund, idf, tpp) declare_struct(fund, idf, tpp); } -struct sdef * -idf2sdef(idf, tp) - register struct idf *idf; - struct type *tp; +struct sdef *idf2sdef( + register struct idf *idf, + struct type *tp) { /* The identifier idf is identified as a selector in the struct tp. @@ -296,9 +299,7 @@ idf2sdef(idf, tp) } #if 0 -int -uniq_selector(idf_sdef) - register struct sdef *idf_sdef; +int uniq_selector(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 @@ -324,12 +325,12 @@ uniq_selector(idf_sdef) #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 */ +add_field( + 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 @@ -438,18 +439,12 @@ add_field(szp, fd, fdtpp, idf, stp) #endif /* NOBITFIELD */ /* some utilities */ -int -is_struct_or_union(fund) - register int fund; +int is_struct_or_union(register int fund) { return fund == STRUCT || fund == UNION; } -/* Greatest Common Divisor - */ -int -gcd(m, n) - register int m, n; +static int gcd(register int m, register int n) { register int r; @@ -461,11 +456,8 @@ gcd(m, n) return m; } -/* Least Common Multiple - */ -int -lcm(m, n) - register int m, n; + +static int lcm(register int m, register int n) { return m * (n / gcd(m, n)); } diff --git a/lang/cem/cemcom.ansi/struct.str b/lang/cem/cemcom.ansi/struct.str index 8dafd856e..c0a95244d 100644 --- a/lang/cem/cemcom.ansi/struct.str +++ b/lang/cem/cemcom.ansi/struct.str @@ -2,7 +2,17 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef STRUCT_H_ +#define STRUCT_H_ + /* $Id$ */ + +#include "arith.h" + +struct type; +struct idf; +struct field; + /* SELECTOR DESCRIPTOR */ struct sdef { /* for selectors */ @@ -27,4 +37,26 @@ struct tag { /* for struct-, union- and enum tags */ /* ALLOCDEF "tag" 10 */ -struct sdef *idf2sdef(); +struct sdef *idf2sdef(register struct idf *idf, struct type *tp); +void add_sel( + 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); +void declare_struct(int fund, register struct idf *idf, struct type **tpp); +void apply_struct(int fund, register struct idf *idf, struct type **tpp); +int is_struct_or_union(register int fund); + +#ifndef NOBITFIELD +arith +add_field( + 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 */ +#endif + +#endif diff --git a/lang/cem/cemcom.ansi/switch.c b/lang/cem/cemcom.ansi/switch.c index 77a9dcef3..24cb82c6f 100644 --- a/lang/cem/cemcom.ansi/switch.c +++ b/lang/cem/cemcom.ansi/switch.c @@ -23,13 +23,16 @@ #include "expr.h" #include "type.h" #include "sizes.h" +#include "switch.h" +#include "eval.h" +#include "ch3.h" +#include "error.h" extern char options[]; int density = DENSITY; -compact(nr, low, up) - arith low, up; +static int compact(int nr, arith low, arith up) { /* Careful! up - low might not fit in an arith. And then, the test "up-low < 0" might also not work to detect this @@ -49,8 +52,7 @@ static struct switch_hdr *switch_stack = 0; For simplicity, we suppose int_size == word_size. */ -code_startswitch(expp) - struct expr **expp; +void code_startswitch(struct expr **expp) { /* Check the expression, stack a new case header and fill in the necessary fields. @@ -85,7 +87,7 @@ code_startswitch(expp) C_bra(l_table); /* goto start of switch_table */ } -code_endswitch() +void code_endswitch(void) { register struct switch_hdr *sh = switch_stack; register label tablabel; @@ -158,9 +160,7 @@ code_endswitch() unstack_stmt(); } -void -code_case(expr) - struct expr *expr; +void code_case(struct expr *expr) { register arith val; register struct case_entry *ce; @@ -227,8 +227,7 @@ code_case(expr) } } -void -code_default() +void code_default(void) { register struct switch_hdr *sh = switch_stack; diff --git a/lang/cem/cemcom.ansi/switch.str b/lang/cem/cemcom.ansi/switch.str index fd2dd455b..94a45ca42 100644 --- a/lang/cem/cemcom.ansi/switch.str +++ b/lang/cem/cemcom.ansi/switch.str @@ -2,7 +2,16 @@ * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ +#ifndef SWITCH_H_ +#define SWITCH_H_ + /* $Id$ */ + +#include "arith.h" + +struct type; +struct expr; + /* S W I T C H - T A B L E - S T R U C T U R E */ struct switch_hdr { @@ -27,3 +36,12 @@ struct case_entry { }; /* ALLOCDEF "case_entry" 20 */ + +void code_startswitch(struct expr **expp); +void code_endswitch(void); +void code_case(struct expr *expr); +void code_default(void); + + + +#endif \ No newline at end of file diff --git a/lang/cem/cemcom.ansi/tokcase.sed b/lang/cem/cemcom.ansi/tokcase.sed new file mode 100644 index 000000000..25cd5d9d3 --- /dev/null +++ b/lang/cem/cemcom.ansi/tokcase.sed @@ -0,0 +1,3 @@ +/{[A-Z]/!d +s/.*{\(.*\),.*\(".*"\).*$/ case \1 :\ + return \2;/ diff --git a/lang/cem/cemcom.ansi/tokcasee.in b/lang/cem/cemcom.ansi/tokcasee.in new file mode 100644 index 000000000..5df07e7c9 --- /dev/null +++ b/lang/cem/cemcom.ansi/tokcasee.in @@ -0,0 +1,16 @@ + default: + if (tok <= 0) return "end of file"; + if (tok < 040 || tok >= 0177) { + return "bad token"; + } + /* fall through */ + case '\n': + case '\f': + case '\v': + case '\r': + case '\t': + index = (index+2) & (SIZBUF-1); + buf[index] = tok; + return &buf[index]; + } +} \ No newline at end of file diff --git a/lang/cem/cemcom.ansi/tokcaseh.in b/lang/cem/cemcom.ansi/tokcaseh.in new file mode 100644 index 000000000..63b1932cb --- /dev/null +++ b/lang/cem/cemcom.ansi/tokcaseh.in @@ -0,0 +1,12 @@ +/* Generated by make.tokcase */ +/* $Id$ */ +#include "Lpars.h" + +char *symbol2str(int tok) +{ +#define SIZBUF 8 + /* allow for a few invocations in f.i. an argument list */ + static char buf[SIZBUF]; + static int index; + + switch (tok) { diff --git a/lang/cem/cemcom.ansi/tokenname.c b/lang/cem/cemcom.ansi/tokenname.c index 8c52b4dcb..b430abbd8 100644 --- a/lang/cem/cemcom.ansi/tokenname.c +++ b/lang/cem/cemcom.ansi/tokenname.c @@ -11,6 +11,7 @@ #include "LLlex.h" #include "tokenname.h" #include "Lpars.h" +#include "error.h" /* To centralize the declaration of %tokens, their presence in this file is taken as their declaration. The Makefile will produce @@ -132,8 +133,7 @@ struct tokenname tkfunny[] = { /* internal keywords */ }; #endif /* ____ */ -reserve(resv) - register struct tokenname resv[]; +void reserve(register struct tokenname resv[]) { /* The names of the tokens described in resv are entered as reserved words. diff --git a/lang/cem/cemcom.ansi/tokenname.h b/lang/cem/cemcom.ansi/tokenname.h index fdff2fbc2..f3f5edb2e 100644 --- a/lang/cem/cemcom.ansi/tokenname.h +++ b/lang/cem/cemcom.ansi/tokenname.h @@ -4,6 +4,8 @@ */ /* $Id$ */ /* TOKENNAME DEFINITION */ +#ifndef TOKENNAME_H_ +#define TOKENNAME_H_ struct tokenname { /* Used for defining the name of a token as identified by its symbol @@ -11,3 +13,7 @@ struct tokenname { /* Used for defining the name of a int tn_symbol; char *tn_name; }; + +void reserve(register struct tokenname resv[]); + +#endif /* TOKENNAME_H_ */ diff --git a/lang/cem/cemcom.ansi/type.c b/lang/cem/cemcom.ansi/type.c index 2b477a725..ff3a6eab3 100644 --- a/lang/cem/cemcom.ansi/type.c +++ b/lang/cem/cemcom.ansi/type.c @@ -16,68 +16,59 @@ #include "sizes.h" #include "align.h" #include "decspecs.h" +#include "error.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 - *schar_type, *uchar_type, - *short_type, *ushort_type, - *word_type, *uword_type, - *int_type, *uint_type, - *long_type, *ulong_type, - *float_type, *double_type, *lngdbl_type, - *void_type, - *string_type, *funint_type, *error_type; - -struct type *pa_type; /* Pointer-Arithmetic type */ - -struct type * -create_type(fund) - int fund; + line parameters. + */ +struct type *schar_type, *uchar_type, *short_type, *ushort_type, *word_type, + *uword_type, *int_type, *uint_type, *long_type, *ulong_type, + *float_type, *double_type, *lngdbl_type, *void_type, *string_type, + *funint_type, *error_type; + +struct type *pa_type; /* Pointer-Arithmetic type */ + +struct type *create_type(int fund) { /* A brand new struct type is created, and its tp_fund set - to fund. - */ + to fund. + */ register struct type *ntp = new_type(); ntp->tp_fund = fund; - ntp->tp_size = (arith)-1; + ntp->tp_size = (arith) -1; return ntp; } -struct type * -promoted_type(tp) -struct type *tp; +struct type *promoted_type(struct type *tp) { - if (tp->tp_fund == CHAR || tp->tp_fund == SHORT) { + if (tp->tp_fund == CHAR || tp->tp_fund == SHORT) + { if (tp->tp_unsigned && (int) tp->tp_size == (int) int_size) return uint_type; - else return int_type; - } else if (tp->tp_fund == FLOAT) + else + return int_type; + } + else if (tp->tp_fund == FLOAT) return double_type; - else return tp; + else + return tp; } -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; +struct type *construct_type(int fund, register struct type *tp, int qual, +arith count, /* for fund == ARRAY only */ +register struct proto *pl) { /* fund must be a type constructor: FIELD, FUNCTION, POINTER or - ARRAY. The pointer to the constructed type is returned. - */ + ARRAY. The pointer to the constructed type is returned. + */ register struct type *dtp; - switch (fund) { + switch (fund) + { #ifndef NOBITFIELD case FIELD: dtp = field_of(tp, qual); @@ -85,11 +76,13 @@ construct_type(fund, tp, qual, count, pl) #endif /* NOBITFIELD */ case FUNCTION: - if (tp->tp_fund == FUNCTION) { + if (tp->tp_fund == FUNCTION) + { error("function cannot yield function"); return error_type; } - if (tp->tp_fund == ARRAY) { + if (tp->tp_fund == ARRAY) + { error("function cannot yield array"); return error_type; } @@ -100,7 +93,8 @@ construct_type(fund, tp, qual, count, pl) dtp = pointer_to(tp, qual); break; case ARRAY: - if (tp->tp_fund == VOID) { + if (tp->tp_fund == VOID) + { error("cannot construct array of void"); count = (arith) -1; } @@ -113,14 +107,10 @@ construct_type(fund, tp, qual, count, pl) return dtp; } -struct type * -function_of(tp, pl, qual) - register struct type *tp; - struct proto *pl; - int qual; +struct type *function_of(register struct type *tp, struct proto *pl, int qual) { #if 0 -/* See comment below */ + /* See comment below */ register struct type *dtp = tp->tp_function; #else register struct type *dtp; @@ -128,30 +118,31 @@ function_of(tp, pl, qual) /* look for a type with the right qualifier */ #if 0 -/* the code doesn't work in the following case: - int func(); - int func(int a, int b) { return q(a); } - because updating the type works inside the data-structures for that type - thus, a new type is created for very function. This may change in the - future, when declarations with empty parameter lists become obsolete. - When it does, change type.str, decspecs.c, and this routine. Search for - the function_of pattern to find the places. -*/ + /* the code doesn't work in the following case: + int func(); + int func(int a, int b) { return q(a); } + because updating the type works inside the data-structures for that type + thus, a new type is created for very function. This may change in the + future, when declarations with empty parameter lists become obsolete. + When it does, change type.str, decspecs.c, and this routine. Search for + the function_of pattern to find the places. + */ while (dtp && (dtp->tp_typequal != qual || dtp->tp_proto != pl)) - dtp = dtp->next; + dtp = dtp->next; #else dtp = 0; #endif - if (!dtp) { + if (!dtp) + { dtp = create_type(FUNCTION); dtp->tp_up = tp; - dtp->tp_size = -1; /* function size is not known */ + dtp->tp_size = -1; /* function size is not known */ dtp->tp_align = pointer_align; dtp->tp_typequal = qual; dtp->tp_proto = pl; #if 0 -/* See comment above */ + /* See comment above */ dtp->next = tp->tp_function; tp->tp_function = dtp; #endif @@ -159,10 +150,7 @@ function_of(tp, pl, qual) return dtp; } -struct type * -pointer_to(tp, qual) - register struct type *tp; - int qual; +struct type *pointer_to(register struct type *tp, int qual) { register struct type *dtp = tp->tp_pointer; @@ -170,7 +158,8 @@ pointer_to(tp, qual) while (dtp && dtp->tp_typequal != qual) dtp = dtp->next; - if (!dtp) { + if (!dtp) + { dtp = create_type(POINTER); dtp->tp_unsigned = 1; dtp->tp_up = tp; @@ -183,11 +172,7 @@ pointer_to(tp, qual) return dtp; } -struct type * -array_of(tp, count, qual) - register struct type *tp; - arith count; - int qual; +struct type * array_of(register struct type *tp, arith count, int qual) { register struct type *dtp = tp->tp_array; @@ -195,7 +180,8 @@ array_of(tp, count, qual) while (dtp && (dtp->tp_nel != count || dtp->tp_typequal != qual)) dtp = dtp->next; - if (!dtp) { + if (!dtp) + { dtp = create_type(ARRAY); dtp->tp_up = tp; dtp->tp_nel = count; @@ -203,19 +189,18 @@ array_of(tp, count, qual) dtp->tp_typequal = qual; dtp->next = tp->tp_array; tp->tp_array = dtp; - if (tp->tp_size >= 0 && count >= 0) { + if (tp->tp_size >= 0 && count >= 0) + { dtp->tp_size = count * tp->tp_size; } - else dtp->tp_size = -1; + else + dtp->tp_size = -1; } return dtp; } #ifndef NOBITFIELD -struct type * -field_of(tp, qual) - register struct type *tp; - int qual; +struct type * field_of(register struct type *tp, int qual) { register struct type *dtp = create_type(FIELD); @@ -227,53 +212,47 @@ field_of(tp, qual) } #endif /* NOBITFIELD */ -arith -size_of_type(tp, nm) - struct type *tp; - char nm[]; +arith size_of_type(struct type *tp, char nm[]) { arith sz = tp->tp_size; - if (sz < 0) { + if (sz < 0) + { error("size of %s unknown", nm); - sz = (arith)1; + sz = (arith) 1; } return sz; } -idf2type(idf, tpp) - struct idf *idf; - struct type **tpp; +void idf2type(struct idf *idf, struct type **tpp) { /* Decoding a typedef-ed identifier or basic type: 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. - */ + 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 (*tpp) error("multiple types in declaration"); - if ( tp->tp_size < (arith)0 && tp->tp_fund == ARRAY) { + if (*tpp) + error("multiple types in declaration"); + if (tp->tp_size < (arith) 0 && tp->tp_fund == ARRAY) + { *tpp = new_type(); **tpp = *tp; - /* this is really a structure assignment, AAGH!!! */ + /* this is really a structure assignment, AAGH!!! */ } - else { + else + { *tpp = tp; } } -arith -align(pos, al) - arith pos; - int al; +arith align(arith pos, int al) { return ((pos + al - 1) / al) * al; } -struct type * -standard_type(fund, sgn, algn, sz) - int algn; arith sz; +struct type * standard_type(int fund, int sgn, int algn, arith sz) { register struct type *tp = create_type(fund); @@ -284,25 +263,29 @@ standard_type(fund, sgn, algn, sz) return tp; } -completed(tp) - struct type *tp; +void completed(struct type *tp) { register struct type *atp = tp->tp_array; register struct type *etp = tp; - switch(etp->tp_fund) { + switch (etp->tp_fund) + { case STRUCT: case UNION: case ENUM: - while (etp = etp->next) { - if (! etp->tp_sdef) etp->tp_sdef = tp->tp_sdef; + while (etp = etp->next) + { + if (!etp->tp_sdef) + etp->tp_sdef = tp->tp_sdef; etp->tp_size = tp->tp_size; etp->tp_align = tp->tp_align; } break; } - while (atp) { - if (atp->tp_nel >= 0) { + while (atp) + { + if (atp->tp_nel >= 0) + { atp->tp_size = atp->tp_nel * tp->tp_size; } atp = atp->next; diff --git a/lang/cem/cemcom.ansi/type.str b/lang/cem/cemcom.ansi/type.str index 8796d61a4..b98ffbb6c 100644 --- a/lang/cem/cemcom.ansi/type.str +++ b/lang/cem/cemcom.ansi/type.str @@ -4,8 +4,13 @@ */ /* $Id$ */ /* TYPE DESCRIPTOR */ +#ifndef TYPE_H_ +#define TYPE_H_ #include "parameters.h" +#include "arith.h" + + struct type { struct type *next; /* used for ARRAY and for qualifiers */ @@ -59,13 +64,6 @@ struct type { #define TQ_VOLATILE 0x01 #define TQ_CONST 0x02 -extern struct type - *create_type(), *standard_type(), *construct_type(), *pointer_to(), - *array_of(), *function_of(), *promoted_type(); - -#ifndef NOBITFIELD -extern struct type *field_of(); -#endif /* NOBITFIELD */ extern struct type *schar_type, *uchar_type, @@ -79,6 +77,24 @@ extern struct type extern struct type *pa_type; /* type.c */ -extern arith size_of_type(), align(); +struct type *create_type(int fund); +struct type *promoted_type(struct type *tp); +struct type *construct_type(int fund, register struct type *tp, int qual, +arith count, /* for fund == ARRAY only */ + register struct proto *pl); +struct type *function_of(register struct type *tp, struct proto *pl, int qual); +struct type *pointer_to(register struct type *tp, int qual); +struct type * array_of(register struct type *tp, arith count, int qual); +#ifndef NOBITFIELD +struct type * field_of(register struct type *tp, int qual); +#endif /* NOBITFIELD */ +arith size_of_type(struct type *tp, char nm[]); +void idf2type(struct idf *idf, struct type **tpp); +arith align(arith pos, int al); +struct type * standard_type(int fund, int sgn, int algn, arith sz); +void completed(struct type *tp); + /* ALLOCDEF "type" 50 */ + +#endif \ No newline at end of file diff --git a/lang/cem/cemcom.ansi/util.c b/lang/cem/cemcom.ansi/util.c index 273fa8d78..6d3f084bf 100644 --- a/lang/cem/cemcom.ansi/util.c +++ b/lang/cem/cemcom.ansi/util.c @@ -41,16 +41,14 @@ static int loc_id; extern char options[]; -LocalInit() +void LocalInit(void) { #ifdef USE_TMP C_insertpart(loc_id = C_getid()); #endif /* USE_TMP */ } -arith -LocalSpace(sz, al) - arith sz; +arith LocalSpace(arith sz, int al) { register struct stack_level *stl = local_level; @@ -61,9 +59,7 @@ LocalSpace(sz, al) #define TABSIZ 32 static struct localvar *regs[TABSIZ]; -arith -NewLocal(sz, al, regtype, sc) - arith sz; +arith NewLocal(arith sz, int al, int regtype, int sc) { register struct localvar *tmp = FreeTmps; struct localvar *prev = 0; @@ -98,8 +94,7 @@ NewLocal(sz, al, regtype, sc) return tmp->t_offset; } -FreeLocal(off) - arith off; +void FreeLocal(arith off) { int index = (int) (off >> 2) & (TABSIZ - 1); register struct localvar *tmp = regs[index]; @@ -117,7 +112,7 @@ FreeLocal(off) } } -LocalFinish() +void LocalFinish(void) { register struct localvar *tmp, *tmp1; register int i; @@ -163,9 +158,7 @@ LocalFinish() #endif } -void -RegisterAccount(offset, size, regtype, sc) - arith offset, size; +void RegisterAccount(arith offset, arith size, int regtype, int sc) { register struct localvar *p; int index; @@ -183,9 +176,7 @@ RegisterAccount(offset, size, regtype, sc) regs[index] = p; } -static struct localvar * -find_reg(off) - arith off; +static struct localvar *find_reg(arith off) { register struct localvar *p = regs[(int)(off >> 2) & (TABSIZ - 1)]; @@ -193,8 +184,7 @@ find_reg(off) return p; } -LoadLocal(off, sz) - arith off, sz; +void LoadLocal(arith off, arith sz) { register struct localvar *p = find_reg(off); @@ -213,8 +203,7 @@ LoadLocal(off, sz) } } -StoreLocal(off, sz) - arith off, sz; +void StoreLocal(arith off, arith sz) { register struct localvar *p = find_reg(off); @@ -234,8 +223,7 @@ StoreLocal(off, sz) } #ifndef LINT -AddrLocal(off) - arith off; +void AddrLocal(arith off) { register struct localvar *p = find_reg(off); diff --git a/lang/cem/cemcom.ansi/util.str b/lang/cem/cemcom.ansi/util.str index 886432343..1e3855e3c 100644 --- a/lang/cem/cemcom.ansi/util.str +++ b/lang/cem/cemcom.ansi/util.str @@ -1,3 +1,8 @@ +#ifndef UTIL_H_ +#define UTIL_H_ + +#include "arith.h" + struct localvar { struct localvar *next; arith t_offset; /* offset from LocalBase */ @@ -9,3 +14,18 @@ struct localvar { }; /* ALLOCDEF "localvar" 10 */ + +void LocalInit(void); +arith LocalSpace(arith sz, int al); +arith NewLocal(arith sz, int al, int regtype, int sc); +void FreeLocal(arith off); +void LocalFinish(void); +void RegisterAccount(arith offset, arith size, int regtype, int sc); +void LoadLocal(arith off, arith sz); +void StoreLocal(arith off, arith sz); + +#ifndef LINT +void AddrLocal(arith off); +#endif + +#endif \ No newline at end of file -- 2.34.1