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.
This commit is contained in:
parent
e70690c510
commit
750a6bc684
|
@ -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 */
|
||||
|
||||
|
||||
|
|
318
lang/cem/cemcom.ansi/CMakeLists.txt
Normal file
318
lang/cem/cemcom.ansi/CMakeLists.txt
Normal file
|
@ -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)
|
||||
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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 <em_arith.h> /* obtain definition of "arith" */
|
||||
#include <em_arith.h> /* obtain definition of "arith" */
|
||||
#include <flt_arith.h>
|
||||
|
||||
#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_ */
|
||||
|
|
|
@ -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();
|
||||
|
|
20
lang/cem/cemcom.ansi/blocks.h
Normal file
20
lang/cem/cemcom.ansi/blocks.h
Normal file
|
@ -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_ */
|
|
@ -9,6 +9,7 @@
|
|||
#include "parameters.h"
|
||||
#include <flt_arith.h>
|
||||
#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:
|
||||
|
|
29
lang/cem/cemcom.ansi/ch3.h
Normal file
29
lang/cem/cemcom.ansi/ch3.h
Normal file
|
@ -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_ */
|
|
@ -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
|
||||
|
|
21
lang/cem/cemcom.ansi/ch3bin.h
Normal file
21
lang/cem/cemcom.ansi/ch3bin.h
Normal file
|
@ -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_ */
|
|
@ -5,6 +5,7 @@
|
|||
/* $Id$ */
|
||||
/* SEMANTIC ANALYSIS (CHAPTER 3.3) -- MONADIC OPERATORS */
|
||||
|
||||
#include "ch3mon.h"
|
||||
#include "parameters.h"
|
||||
#include <alloc.h>
|
||||
#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.
|
||||
*/
|
||||
|
|
22
lang/cem/cemcom.ansi/ch3mon.h
Normal file
22
lang/cem/cemcom.ansi/ch3mon.h
Normal file
|
@ -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_ */
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,11 +8,15 @@
|
|||
#include "parameters.h"
|
||||
#ifndef LINT
|
||||
|
||||
#include "conversion.h"
|
||||
#include <em.h>
|
||||
#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:
|
||||
|
|
15
lang/cem/cemcom.ansi/conversion.h
Normal file
15
lang/cem/cemcom.ansi/conversion.h
Normal file
|
@ -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_ */
|
|
@ -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 <assert.h>
|
||||
#include "cstoper.h"
|
||||
#include "parameters.h"
|
||||
#include <flt_arith.h>
|
||||
#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;
|
||||
|
|
17
lang/cem/cemcom.ansi/cstoper.h
Normal file
17
lang/cem/cemcom.ansi/cstoper.h
Normal file
|
@ -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_ */
|
|
@ -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;
|
||||
|
|
19
lang/cem/cemcom.ansi/dataflow.h
Normal file
19
lang/cem/cemcom.ansi/dataflow.h
Normal file
|
@ -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_ */
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -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 <alloc.h>
|
||||
#include <flt_arith.h>
|
||||
#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;
|
||||
|
||||
|
|
28
lang/cem/cemcom.ansi/declarator.h
Normal file
28
lang/cem/cemcom.ansi/declarator.h
Normal file
|
@ -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_ */
|
|
@ -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 <assert.h>
|
||||
#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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -8,12 +8,17 @@
|
|||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#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 <stb.h>
|
||||
|
@ -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);
|
||||
|
|
16
lang/cem/cemcom.ansi/domacro.h
Normal file
16
lang/cem/cemcom.ansi/domacro.h
Normal file
|
@ -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_ */
|
|
@ -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 <stdarg.h>
|
||||
#else
|
||||
|
@ -17,13 +18,15 @@
|
|||
#else
|
||||
#include "l_em.h"
|
||||
#endif /* LINT */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "tokenname.h"
|
||||
#include <flt_arith.h>
|
||||
#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");
|
||||
}
|
||||
|
|
94
lang/cem/cemcom.ansi/error.h
Normal file
94
lang/cem/cemcom.ansi/error.h
Normal file
|
@ -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_ */
|
|
@ -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
|
|
@ -14,6 +14,8 @@
|
|||
#include <em_reg.h>
|
||||
#include <alloc.h>
|
||||
#include <flt_arith.h>
|
||||
#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);
|
||||
|
|
37
lang/cem/cemcom.ansi/eval.h
Normal file
37
lang/cem/cemcom.ansi/eval.h
Normal file
|
@ -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 <em.h>
|
||||
|
||||
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_ */
|
|
@ -10,6 +10,7 @@
|
|||
#include "parameters.h"
|
||||
#include <alloc.h>
|
||||
#include <flt_arith.h>
|
||||
#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
|
||||
<idf> +/- <integral> or <integral>.
|
||||
*/
|
||||
<idf> +/- <integral> or <integral>.
|
||||
*/
|
||||
#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);
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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 <alloc.h>
|
||||
#include "parameters.h"
|
||||
#include <flt_arith.h>
|
||||
#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 <alloc.h>
|
||||
#include "parameters.h"
|
||||
#include <flt_arith.h>
|
||||
#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; }
|
||||
;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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_ */
|
|
@ -10,18 +10,19 @@
|
|||
#include "parameters.h"
|
||||
#include <alloc.h>
|
||||
#include <flt_arith.h>
|
||||
#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
|
||||
|
|
15
lang/cem/cemcom.ansi/fltcstoper.h
Normal file
15
lang/cem/cemcom.ansi/fltcstoper.h
Normal file
|
@ -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_ */
|
|
@ -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 <idf_pkg.body>
|
||||
|
||||
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"
|
||||
*/
|
||||
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 */
|
||||
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);
|
||||
warning("'%s' old-fashioned function definition",
|
||||
dc->dc_idf->id_text);
|
||||
|
||||
while (fm) {
|
||||
if (pl == 0) pl = lpl;
|
||||
else {
|
||||
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);
|
||||
|
|
|
@ -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 <idf_pkg.spec>
|
||||
|
||||
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
|
|
@ -10,6 +10,7 @@
|
|||
#include <string.h>
|
||||
#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;
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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 <em_label.h> /* 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_ */
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
1
lang/cem/cemcom.ansi/next.str
Normal file
1
lang/cem/cemcom.ansi/next.str
Normal file
|
@ -0,0 +1 @@
|
|||
#include "parameters.h"
|
|
@ -9,12 +9,14 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <alloc.h>
|
||||
#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.
|
||||
|
|
13
lang/cem/cemcom.ansi/options.h
Normal file
13
lang/cem/cemcom.ansi/options.h
Normal file
|
@ -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_ */
|
|
@ -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
|
||||
|
|
13
lang/cem/cemcom.ansi/pragma.h
Normal file
13
lang/cem/cemcom.ansi/pragma.h
Normal file
|
@ -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_ */
|
|
@ -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 <flt_arith.h>
|
||||
#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 <flt_arith.h>
|
||||
#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 */
|
||||
}
|
||||
;
|
||||
|
|
|
@ -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;
|
||||
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 */ )) {
|
||||
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.
|
||||
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);
|
||||
...
|
||||
}
|
||||
}
|
||||
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
|
||||
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) {
|
||||
...
|
||||
}
|
||||
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.
|
||||
*/
|
||||
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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
13
lang/cem/cemcom.ansi/skip.h
Normal file
13
lang/cem/cemcom.ansi/skip.h
Normal file
|
@ -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_ */
|
|
@ -20,6 +20,7 @@
|
|||
#include <flt_arith.h>
|
||||
#include <stb.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
20
lang/cem/cemcom.ansi/stab.h
Normal file
20
lang/cem/cemcom.ansi/stab.h
Normal file
|
@ -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_ */
|
|
@ -22,6 +22,9 @@
|
|||
#include "struct.h"
|
||||
#include "level.h"
|
||||
#include "mes.h"
|
||||
#include "code.h"
|
||||
#include "util.h"
|
||||
#include "error.h"
|
||||
|
||||
/* #include <em_reg.h> */
|
||||
|
||||
|
@ -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));
|
||||
|
|
|
@ -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
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
3
lang/cem/cemcom.ansi/tokcase.sed
Normal file
3
lang/cem/cemcom.ansi/tokcase.sed
Normal file
|
@ -0,0 +1,3 @@
|
|||
/{[A-Z]/!d
|
||||
s/.*{\(.*\),.*\(".*"\).*$/ case \1 :\
|
||||
return \2;/
|
16
lang/cem/cemcom.ansi/tokcasee.in
Normal file
16
lang/cem/cemcom.ansi/tokcasee.in
Normal file
|
@ -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];
|
||||
}
|
||||
}
|
12
lang/cem/cemcom.ansi/tokcaseh.in
Normal file
12
lang/cem/cemcom.ansi/tokcaseh.in
Normal file
|
@ -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) {
|
|
@ -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.
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
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 *pa_type; /* Pointer-Arithmetic type */
|
||||
|
||||
struct type *
|
||||
create_type(fund)
|
||||
int fund;
|
||||
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;
|
||||
|
|
|
@ -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
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in a new issue