From: ceriel Date: Sat, 29 Mar 1986 01:04:49 +0000 (+0000) Subject: Newer version, safety commit X-Git-Tag: release-5-5~5328 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=fac31cce0738109bce0c4744296d37fb8a8e591d;p=ack.git Newer version, safety commit --- diff --git a/lang/m2/comp/Makefile b/lang/m2/comp/Makefile index d8a5804ec..ef03535ec 100644 --- a/lang/m2/comp/Makefile +++ b/lang/m2/comp/Makefile @@ -74,8 +74,8 @@ symbol2str.o: Lpars.h tokenname.o: Lpars.h idf.h tokenname.h idf.o: idf.h input.o: f_info.h input.h -type.o: Lpars.h def.h def_sizes.h idf.h type.h -def.o: Lpars.h debug.h def.h idf.h main.h scope.h +type.o: Lpars.h def.h def_sizes.h idf.h misc.h type.h +def.o: Lpars.h debug.h def.h idf.h main.h misc.h scope.h scope.o: LLlex.h debug.h def.h idf.h scope.h type.h misc.o: LLlex.h f_info.h idf.h misc.h enter.o: def.h idf.h misc.h scope.h type.h diff --git a/lang/m2/comp/declar.g b/lang/m2/comp/declar.g index 3989bb682..f6c492e9d 100644 --- a/lang/m2/comp/declar.g +++ b/lang/m2/comp/declar.g @@ -31,13 +31,17 @@ ProcedureHeading(struct def **pdf; int type;) struct paramlist *params = 0; } : PROCEDURE IDENT - { assert(type == D_PROCEDURE || type == D_PROCHEAD); + { assert(type & (D_PROCEDURE | D_PROCHEAD)); *pdf = define(dot.TOK_IDF, CurrentScope, type); if (type == D_PROCEDURE) { open_scope(OPENSCOPE, 0); } } FormalParameters(type, ¶ms, &tp)? + { + (*pdf)->df_type = tp = construct_type(PROCEDURE, tp); + tp->prc_params = params; + } ; block: @@ -63,54 +67,47 @@ FormalParameters(int doparams; struct paramlist **pr; struct type **tp;) } : '(' [ - FPSection(doparams, pr) + FPSection(doparams, pr) + { pr1 = *pr; } [ - { for (pr1 = *pr; pr1->next; pr1 = pr1->next) ; } + { for (; pr1->next; pr1 = pr1->next) ; } ';' FPSection(doparams, &(pr1->next)) ]* ]? ')' { *tp = 0; } - [ ':' qualident(D_TYPE | D_HTYPE, &df, "type") - { /* ???? *tp = df->df_type; */ } + [ ':' qualident(D_TYPE | D_HTYPE, &df, "type") + { *tp = df->df_type; } ]? ; +/* In the next nonterminal, "doparams" is a flag indicating whether + the identifiers representing the parameters must be added to the + symbol table. We must not do so when reading a Definition Module, + because in this case we only read the header. The Implementation + might contain different identifiers representing the same paramters. +*/ FPSection(int doparams; struct paramlist **ppr;) { struct id_list *FPList; - register struct id_list *pid; - register struct paramlist *pr = 0; - int VARflag = 0; + struct paramlist *ParamList(); + struct type *tp; + int VARp = 0; } : [ - VAR { VARflag = 1; } + VAR { VARp = 1; } ]? - IdentList(&FPList) ':' FormalType - { - if (doparams) { - EnterIdList(FPList, - D_VARIABLE, - VARflag, - (struct type *) 0 /* ???? */, - CurrentScope - ); - } - *ppr = pr = new_paramlist(); - pr->par_type = 0; /* ??? */ - pr->par_var = VARflag; - for (pid = FPList->next; pid; pid = pid->next) { - pr->next = new_paramlist(); - pr = pr->next; - pr->par_type = 0; /* ??? */ - pr->par_var = VARflag; - } - pr->next = 0; - FreeIdList(FPList); - } + IdentList(&FPList) ':' FormalType(&tp) + { + if (doparams) { + EnterIdList(FPList, D_VARIABLE, VARp, tp, CurrentScope); + } + *ppr = ParamList(FPList, tp); + FreeIdList(FPList); + } ; -FormalType +FormalType(struct type **tp;) { struct def *df; int ARRAYflag = 0; @@ -118,6 +115,12 @@ FormalType [ ARRAY OF { ARRAYflag = 1; } ]? qualident(D_TYPE | D_HTYPE, &df, "type") + { if (ARRAYflag) { + *tp = construct_type(ARRAY, NULLTYPE); + (*tp)->arr_elem = df->df_type; + } + else *tp = df->df_type; + } ; TypeDeclaration @@ -127,8 +130,7 @@ TypeDeclaration }: IDENT { df = define(dot.TOK_IDF, CurrentScope, D_TYPE); } '=' type(&tp) - { df->df_type = tp; - } + { df->df_type = tp; } ; type(struct type **ptp;): @@ -148,17 +150,19 @@ type(struct type **ptp;): SimpleType(struct type **ptp;) { struct def *df; + struct type *tp; } : qualident(D_TYPE | D_HTYPE, &df, "type") [ - + /* nothing */ | SubrangeType(ptp) - /* - * The subrange type is given a base type by the - * qualident (this is new modula-2). - */ - { /* ???? (*ptp)->next = df->df_type; */ } + /* The subrange type is given a base type by the + qualident (this is new modula-2). + */ + { + chk_basesubrange(*ptp, tp); + } ] | enumeration(ptp) @@ -228,11 +232,11 @@ ArrayType(struct type **ptp;) } [ ',' SimpleType(&tp) - { tp2 = tp2->tp_value.tp_arr.ar_elem = + { tp2 = tp2->arr_elem = construct_type(ARRAY, tp); } ]* OF type(&tp) - { tp2->tp_value.tp_arr.ar_elem = tp; } + { tp2->arr_elem = tp; } ; RecordType(struct type **ptp;) @@ -245,7 +249,7 @@ RecordType(struct type **ptp;) FieldListSequence(scopenr) { *ptp = standard_type(RECORD, record_align, (arith) 0 /* ???? */); - (*ptp)->tp_value.tp_record.rc_scopenr = scopenr; + (*ptp)->rec_scopenr = scopenr; } END ; @@ -310,48 +314,87 @@ SetType(struct type **ptp;) } ; +/* In a pointer type definition, the type pointed at does not + have to be declared yet, so be careful about identifying + type-identifiers +*/ PointerType(struct type **ptp;) { struct type *tp; - register struct def *df; + struct def *df; struct def *lookfor(); } : POINTER TO [ %if ( (df = lookup(dot.TOK_IDF, CurrentScope))) - IDENT + /* Either a Module or a Type, but in both cases defined + in this scope, so this is the correct identification + */ + qualident(D_TYPE|D_HTYPE, &df, "type") { - if (!(df->df_kind & (D_TYPE | D_HTYPE))) { - error("\"%s\" is not a type identifier", - df->df_idf->id_text); - } if (!df->df_type) { error("type \"%s\" not declared", df->df_idf->id_text); + tp = error_type; } - *ptp = df->df_type; + else tp = df->df_type; } | %if (df = lookfor(dot.TOK_IDF, 0), df->df_kind == D_MODULE) type(&tp) - { *ptp = construct_type(POINTER, tp); } | IDENT - { *ptp = construct_type(POINTER, NULLTYPE); - Forward(&dot, &((*ptp)->next)); - } + { tp = NULLTYPE; } ] + { + *ptp = construct_type(POINTER, tp); + if (!tp) Forward(&dot, &((*ptp)->next)); + } ; -ProcedureType(struct type **ptp;): - PROCEDURE FormalTypeList? - { *ptp = 0; } +ProcedureType(struct type **ptp;) +{ + struct paramlist *pr = 0; + struct type *tp = 0; +} : + PROCEDURE FormalTypeList(&pr, &tp)? + { *ptp = construct_type(PROCEDURE, tp); + (*ptp)->prc_params = pr; + } ; -FormalTypeList +FormalTypeList(struct paramlist **ppr; struct type **ptp;) { struct def *df; + struct type *tp; + struct paramlist *p; + int VARp; } : - '(' [ VAR? FormalType [ ',' VAR? FormalType ]* ]? ')' - [ ':' qualident(1, &df, "type") + '(' { *ppr = 0; } + [ + [ VAR { VARp = 1; } + | { VARp = 0; } + ] + FormalType(&tp) + { *ppr = p = new_paramlist(); + p->par_type = tp; + p->par_var = VARp; + } + [ + ',' + [ VAR {VARp = 1; } + | {VARp = 0; } + ] + FormalType(&tp) + { p->next = new_paramlist(); + p = p->next; + p->par_type = tp; + p->par_var = VARp; + } + ]* + { p->next = 0; } + ]? + ')' + [ ':' qualident(D_TYPE|D_HTYPE, &df, "type") + { *ptp = df->df_type; } ]? ; diff --git a/lang/m2/comp/def.H b/lang/m2/comp/def.H index 24abd7985..49d5bc05e 100644 --- a/lang/m2/comp/def.H +++ b/lang/m2/comp/def.H @@ -5,48 +5,58 @@ struct module { int mo_priority; /* Priority of a module */ int mo_scope; /* Scope of this module */ +#define mod_priority df_value.df_module.mo_priority +#define mod_scope df_value.df_module.mo_scope }; struct variable { - char va_fixedaddress; /* Flag, set if an address was given */ arith va_off; /* Address or offset of variable */ +#define var_off df_value.df_variable.va_off }; struct constant { - struct expr *co_const; /* A constant expression */ + arith co_const; /* result of a constant expression */ +#define con_const df_value.df_variable.con_const }; struct enumval { unsigned int en_val; /* Value of this enumeration literal */ struct def *en_next; /* Next enumeration literal */ +#define enm_val df_value.df_enum.en_val +#define enm_next df_value.df_enum.en_next }; struct field { - arith fld_off; + arith fd_off; struct variant { - struct caselabellist *fld_cases; - label fld_casedescr; - struct def *fld_varianttag; - } *fld_variant; + struct caselabellist *v_cases; + label v_casedescr; + struct def *v_varianttag; + } *fd_variant; +#define fld_off df_value.df_field.fd_off +#define fld_variant df_value.df_field.fd_variant }; struct import { int im_scopenr; /* Scope number from which imported */ +#define imp_scopenr df_value.df_import.im_scopenr }; struct def { /* list of definitions for a name */ - struct def *next; + struct def *next; /* next definition in definitions chain */ + struct def *df_nextinscope; + /* link all definitions in a scope */ struct idf *df_idf; /* link back to the name */ int df_scope; /* Scope in which this definition resides */ short df_kind; /* The kind of this definition: */ -#define D_MODULE 0x0001 -#define D_PROCEDURE 0x0002 -#define D_VARIABLE 0x0004 -#define D_FIELD 0x0008 -#define D_TYPE 0x0010 -#define D_ENUM 0x0020 -#define D_CONST 0x0040 -#define D_IMPORT 0x0080 +#define D_MODULE 0x0001 /* A module */ +#define D_PROCEDURE 0x0002 /* Procedure of function */ +#define D_VARIABLE 0x0004 /* A variable */ +#define D_FIELD 0x0008 /* A field in a record */ +#define D_TYPE 0x0010 /* A type */ +#define D_ENUM 0x0020 /* An enumeration literal */ +#define D_CONST 0x0040 /* A constant */ +#define D_IMPORT 0x0080 /* An imported definition */ #define D_PROCHEAD 0x0100 /* A procedure heading in a definition module */ #define D_HIDDEN 0x0200 /* A hidden type */ #define D_HTYPE 0x0400 /* Definition of a hidden type seen */ diff --git a/lang/m2/comp/def.c b/lang/m2/comp/def.c index 5a815e9a6..2d4bfc240 100644 --- a/lang/m2/comp/def.c +++ b/lang/m2/comp/def.c @@ -5,9 +5,11 @@ static char *RcsId = "$Header$"; #include #include #include +#include #include "Lpars.h" #include "def.h" #include "idf.h" +#include "misc.h" #include "main.h" #include "scope.h" #include "debug.h" @@ -15,7 +17,7 @@ static char *RcsId = "$Header$"; struct def *h_def; /* Pointer to free list of def structures */ static struct def illegal_def = - {0, 0, -20 /* Illegal scope */, D_ERROR}; + {0, 0, 0, -20 /* Illegal scope */, D_ERROR}; struct def *ill_df = &illegal_def; @@ -27,6 +29,7 @@ define(id, scope, kind) already has been defined. If so, error message. */ register struct def *df; + register struct scope *sc; DO_DEBUG(debug(4,"Defining identifier %s in scope %d", id->id_text, scope)); df = lookup(id, scope); @@ -66,6 +69,15 @@ define(id, scope, kind) df->df_kind = kind; df->next = id->id_def; id->id_def = df; + + /* enter the definition in the list of definitions in this scope */ + sc = currscope; + while (sc->sc_scope != scope) { + sc = sc->next; + assert(sc != 0); + } + df->df_nextinscope = sc->sc_def; + sc->sc_def = df; return df; } @@ -85,6 +97,14 @@ lookup(id, scope) DO_DEBUG(debug(4,"Looking for identifier %s in scope %d", id->id_text, scope)); while (df) { if (df->df_scope == scope) { + if (df->df_kind == D_IMPORT) { + df = lookup(id, df->imp_scopenr); + assert(df != 0); + return df; + /* ??? But this does damage to the self- + organizing character of the list + */ + } if (df1) { df1->next = df->next; df->next = id->id_def; @@ -97,3 +117,78 @@ lookup(id, scope) } return 0; } + +/* From the current scope, the list of identifiers "ids" is + exported. Note this fact. If the export is not qualified, make + all the "ids" visible in the enclosing scope by defining them + in this scope as "imported". +*/ +Export(ids, qualified) + register struct id_list *ids; +{ + register struct def *df; + + while (ids) { + df = define(ids->id_ptr, CurrentScope, D_ISEXPORTED); + if (qualified) { + df->df_flags |= D_QEXPORTED; + } + else { + df->df_flags |= D_EXPORTED; + df = define(ids->id_ptr, enclosing(currscope)->sc_scope, + D_IMPORT); + } + ids = ids->next; + } +} + +/* "ids" is a list of imported identifiers. + If "id" is a null-pointer, the identifiers are imported from the + enclosing scope. Otherwise they are imported from the module + indicated by "id", ehich must be visible in the enclosing scope. + An exception must be made for imports of the Compilation Unit. + This case is indicated by the value 0 of the flag "local". + In this case, if "id" is a null pointer, the "ids" identifiers + are all module identifiers. Their Definition Modules must be read. + Otherwise "id" is a module identifier whose Definition Module must + be read. "ids" then represents a list of identifiers defined in + this module. +*/ +Import(ids, id, local) + register struct id_list *ids; + struct idf *id; +{ + register struct def *df; + int scope; + int kind; + struct def *lookfor(); + + if (local) { + kind = D_IMPORT; + if (!id) scope = enclosing(currscope)->sc_scope; + else { + df = lookfor(id, 1); + if (df->df_kind != D_MODULE) { + if (df->df_kind != D_ERROR) { +error("identifier \"%s\" does not represent a module", id->id_text); + } + /* enter all "ids" with type D_ERROR */ + kind = D_ERROR; + scope = enclosing(currscope)->sc_scope; + } + else scope = df->mod_scope; + } + while (ids) { + df = lookup(ids->id_ptr, scope); + if (!df) { + error("identifier \"%s\" not declared", + ids->id_ptr->id_text); + } + df = define(ids->id_ptr, CurrentScope, D_IMPORT); + df->imp_scopenr = scope; + ids = ids->next; + } + return; + } + /* ???? */ +} diff --git a/lang/m2/comp/enter.c b/lang/m2/comp/enter.c index d5c1322e6..03b983301 100644 --- a/lang/m2/comp/enter.c +++ b/lang/m2/comp/enter.c @@ -55,8 +55,8 @@ EnterIdList(idlist, kind, flags, type, scope) if (last) { /* Also meaning : enumeration */ last->df_value.df_enum.en_next = 0; - type->tp_value.tp_enum.en_enums = first; - type->tp_value.tp_enum.en_ncst = assval; + type->enm_enums = first; + type->enm_ncst = assval; } } diff --git a/lang/m2/comp/expression.g b/lang/m2/comp/expression.g index 38c08a763..9d4357980 100644 --- a/lang/m2/comp/expression.g +++ b/lang/m2/comp/expression.g @@ -25,11 +25,8 @@ qualident(int types; struct def **pdf; char *str;) struct def *lookfor(); } : IDENT { if (types) { - df = lookfor(dot.TOK_IDF, 1); - if (df->df_kind == D_ERROR) { - *pdf = df; - types = 0; - } + *pdf = df = lookfor(dot.TOK_IDF, 1); + if (df->df_kind == D_ERROR) types = 0; } } [ @@ -53,7 +50,7 @@ qualident(int types; struct def **pdf; char *str;) ]* { if (types && !(types & df->df_kind)) { error("identifier \"%s\" is not a %s", - dot.TOK_IDF, str); + df->df_idf->id_text, str); } } ; diff --git a/lang/m2/comp/main.c b/lang/m2/comp/main.c index 7ff75edfd..2bd33a04b 100644 --- a/lang/m2/comp/main.c +++ b/lang/m2/comp/main.c @@ -158,8 +158,8 @@ add_standards() construct_type(PROCEDURE, NULLTYPE), 0); tp = construct_type(SUBRANGE, int_type); - tp->tp_value.tp_subrange.su_lb = 0; - tp->tp_value.tp_subrange.su_ub = wrd_size * 8 - 1; + tp->sub_lb = 0; + tp->sub_ub = wrd_size * 8 - 1; df = Enter("BITSET", D_TYPE, construct_type(SET, tp), 0); df->df_type->tp_size = wrd_size; df = Enter("FALSE", D_ENUM, bool_type, 0); diff --git a/lang/m2/comp/program.g b/lang/m2/comp/program.g index 77751d7a7..691b08ce6 100644 --- a/lang/m2/comp/program.g +++ b/lang/m2/comp/program.g @@ -32,8 +32,20 @@ static char *RcsId = "$Header$"; %start CompUnit, CompilationUnit; -ModuleDeclaration: - MODULE IDENT priority? ';' import(1)* export? block IDENT +ModuleDeclaration +{ + struct idf *id; +} : + MODULE IDENT { open_scope(CLOSEDSCOPE, 0); + id = dot.TOK_IDF; + } + priority? ';' + import(1)* + export? + block + IDENT { close_scope(); + match_id(id, dot.TOK_IDF); + } ; priority: @@ -51,6 +63,7 @@ export ]? IdentList(&ExportList) ';' { + Export(ExportList, QUALflag); FreeIdList(ExportList); } ; @@ -71,6 +84,7 @@ import(int local;) name, otherwise the names in the import list are module names. */ { + Import(ImportList, id, local); FreeIdList(ImportList); } ; @@ -78,12 +92,13 @@ import(int local;) DefinitionModule { struct def *df; + struct idf *id; } : DEFINITION { state = DEFINITION; } - MODULE IDENT { - df = define(dot.TOK_IDF, CurrentScope, D_MODULE); + MODULE IDENT { id = dot.TOK_IDF; + df = define(id, CurrentScope, D_MODULE); open_scope(CLOSEDSCOPE, 0); - df->df_value.df_module.mo_scope = CurrentScope; + df->mod_scope = CurrentScope; } ';' import(0)* @@ -92,7 +107,9 @@ DefinitionModule New Modula-2 does not have export lists in definition modules. */ definition* END IDENT '.' - { close_scope(); } + { close_scope(); + match_id(id, dot.TOK_IDF); + } ; definition @@ -120,7 +137,9 @@ definition ProcedureHeading(&df, D_PROCHEAD) ';' ; -ProgramModule: +ProgramModule { + struct idf *id; +} : MODULE { if (state != IMPLEMENTATION) state = PROGRAM; } IDENT { if (state == IMPLEMENTATION) { /* ???? @@ -128,12 +147,16 @@ ProgramModule: Look for current identifier, and find out its scope number */ - open_scope(CLOSEDSCOPE, 0); } - else open_scope(CLOSEDSCOPE, 0); + id = dot.TOK_IDF; + open_scope(CLOSEDSCOPE, 0); + } + priority? + ';' import(0)* + block IDENT + { close_scope(); + match_id(id, dot.TOK_IDF); } - priority? ';' import(0)* block IDENT - { close_scope(); } '.' ; diff --git a/lang/m2/comp/scope.h b/lang/m2/comp/scope.h index f924b6b8f..35253bec8 100644 --- a/lang/m2/comp/scope.h +++ b/lang/m2/comp/scope.h @@ -8,6 +8,7 @@ struct scope { struct scope *next; struct forwards *sc_forw; + struct def *sc_def; /* list of definitions in this scope */ int sc_scope; /* The scope number. Scope number 0 indicates both the pervasive scope and the end of a visibility range @@ -19,5 +20,5 @@ extern struct scope #define nextvisible(x) ((x)->sc_scope ? (x)->next : (struct scope *) 0) #define scopeclosed(x) ((x)->next->sc_scope == 0) -#define enclosing(x) ((x)->next->scope != 0 ? (struct scope *) 0 : (x)->next->next) +#define enclosing(x) (scopeclosed(x) ? (x)->next->next : (x)->next) #define CurrentScope (currscope->sc_scope) diff --git a/lang/m2/comp/type.H b/lang/m2/comp/type.H index 942fcbf90..0f2a2ee40 100644 --- a/lang/m2/comp/type.H +++ b/lang/m2/comp/type.H @@ -14,26 +14,38 @@ struct enume { struct def *en_enums; /* Definitions of enumeration literals */ unsigned int en_ncst; /* Number of constants */ label en_rck; /* Label of range check descriptor */ +#define enm_enums tp_value.tp_enum.en_enums +#define enm_ncst tp_value.tp_enum.en_ncst +#define enm_rck tp_value.tp_enum.enm_rck }; struct subrange { arith su_lb, su_ub; /* Lower bound and upper bound */ label su_rck; /* Label of range check descriptor */ +#define sub_lb tp_value.tp_subrange.su_lb +#define sub_ub tp_value.tp_subrange.su_ub +#define sub_rck tp_value.tp_subrange.su_rck }; struct array { struct type *ar_elem; /* Type of elements */ arith ar_lb, ar_ub; /* Lower bound and upper bound */ label ar_descr; /* Label of array descriptor */ +#define arr_elem tp_value.tp_arr.ar_elem +#define arr_lb tp_value.tp_arr.ar_lb +#define arr_ub tp_value.tp_arr.ar_ub +#define arr_descr tp_value.tp_arr.ar_descr }; struct record { int rc_scopenr; /* Scope number of this record */ /* Members are in the symbol table */ +#define rec_scopenr tp_value.tp_record.rc_scopenr }; struct proc { struct paramlist *pr_params; +#define prc_params tp_value.tp_proc.pr_params }; struct type { diff --git a/lang/m2/comp/type.c b/lang/m2/comp/type.c index a8eb5566c..ae9aa6fb6 100644 --- a/lang/m2/comp/type.c +++ b/lang/m2/comp/type.c @@ -11,6 +11,7 @@ static char *RcsId = "$Header$"; #include "def.h" #include "type.h" #include "idf.h" +#include "misc.h" /* To be created dynamically in main() from defaults or from command line parameters. @@ -143,7 +144,7 @@ has_selectors(df) register struct type *tp = df->df_type; if (tp->tp_fund == RECORD) { - return tp->tp_value.tp_record.rc_scopenr; + return tp->rec_scopenr; } break; } @@ -151,3 +152,58 @@ has_selectors(df) error("no selectors for \"%s\"", df->df_idf->id_text); return 0; } + +/* Create a parameterlist of a procedure and return a pointer to it. + "ids" indicates the list of identifiers, "tp" their type, and + "VARp" is set when the parameters are VAR-parameters. + Actually, "ids" is only used because it tells us how many parameters + there were with this type. +*/ +struct paramlist * +ParamList(ids, tp, VARp) + register struct id_list *ids; + struct type *tp; +{ + register struct paramlist *pr; + struct paramlist *pstart; + + pstart = pr = new_paramlist(); + pr->par_type = tp; + pr->par_var = VARp; + for (ids = ids->next; ids; ids = ids->next) { + pr->next = new_paramlist(); + pr = pr->next; + pr->par_type = tp; + pr->par_var = VARp; + } + pr->next = 0; + return pstart; +} + +/* A subrange had a specified base. Check that the bases conform ... +*/ +chk_basesubrange(tp, base) + register struct type *tp, *base; +{ + if (base->tp_fund == SUBRANGE) { + /* Check that the bounds of "tp" fall within the range + of "base" + */ + if (base->sub_lb > tp->sub_lb || base->sub_ub < tp->sub_ub) { + error("Base type has insufficient range"); + } + base = base->next; + } + if (base->tp_fund == ENUMERATION || base->tp_fund == CHAR) { + if (tp->next != base) { + error("Specified base does not conform"); + } + } + else if (base != card_type && base != int_type) { + error("Illegal base for a subrange"); + } + else if (base != tp->next && base != int_type) { + error("Specified base does not conform"); + } + tp->next = base; +}