#ifndef lint static char RCSid[] = "$Header: constantcode.c,v 2.0 85/11/21 07:21:32 jqj Exp $"; #endif /* $Log: constantcode.c,v $ * Revision 2.0 85/11/21 07:21:32 jqj * 4.3BSD standard release * * Revision 1.4 85/05/23 06:19:32 jqj * *** empty log message *** * * Revision 1.4 85/05/23 06:19:32 jqj * Public Beta-test version, released 24 May 1985 * * Revision 1.3 85/03/26 06:09:41 jqj * Revised public alpha-test version, released 26 March 1985 * * Revision 1.2 85/03/11 16:38:56 jqj * Public alpha-test version, released 11 March 1985 * * Revision 1.1 85/02/15 13:55:18 jqj * Initial revision * */ /* * Generate code for constant declarations. */ #include "compiler.h" /* * Generate code for constant declarations */ define_constant(name, typtr, value) struct object *name; struct type *typtr; struct constant *value; { char *fullname; name->o_class = O_CONSTANT; name->o_constant = value; fullname = make_full_name( name->o_module, name->o_modversion, name_of(name)); /* * Check for simple case of Foo: TypeBaz = Mumble; * where Mumble is another constant. In this case, * just use the existing declaration */ if (value->cn_name != NULL) { if (!recursive_flag) { fprintf(header,"#define %s %s\n", fullname, value->cn_name); /* open scope */ fprintf(header1,"#define %s %s\n", name_of(name), value->cn_name); } return; } /* * We have to generate some code for this one. We'll generate * the declaration in the header file of a static variable * initialized to the appropriate values. */ value->cn_name = fullname; if (recursive_flag) return; /* it's already been expanded elsewhere */ /* open scope */ fprintf(header1,"#define %s %s\n", name_of(name), fullname); /* make sure the type is defined */ if (typename(typtr) == NULL) { /* create an anonymous (not in symboltable) type and subtypes */ char * typenam; typenam = gensym("T_cn"); code_type(typenam, typtr); typename(typtr) = typenam; } /* depending on the type, generate appropriate initializer */ switch (typtr->type_constr) { case C_PROCEDURE: define_procedure_constant(name, typtr, value); break; case C_ERROR: define_error_constant(name, typtr, value); break; case C_NUMERIC: case C_BOOLEAN: case C_STRING: case C_ENUMERATION: /* these are simple, since they can't include sequences */ fprintf(header, "\nstatic %s %s = {%s};\n", typename(typtr), value->cn_name, value->cn_value); break; default: /* the general case */ scan_for_sequences(typtr, value); /* kludge */ fprintf(header, "\nstatic %s %s = ", typename(typtr), value->cn_name); code_constant(typtr, value); fprintf(header,";\n"); break; } return; } /* * Generate client and server code for error constants */ define_error_constant(symbol,typtr,value) struct object *symbol; struct type *typtr; struct constant *value; { char *errvalue; if (recursive_flag) return; /* can't happen */ if (typtr->type_constr != C_ERROR) error(FATAL, "internal error (define_error_constant): not an error"); if (value->cn_constr != C_NUMERIC) { error(ERROR,"Values of ERRORs must be numeric"); errvalue = "-1"; } else errvalue = value->cn_value; fprintf(header,"\n#define %s (ERROR_OFFSET+%s)\n\ #define %sArgs %s\n", value->cn_name, errvalue, value->cn_name, typename(typtr)); fprintf(header1,"#define %sArgs %sArgs\n", symbol->o_name, value->cn_name); value->cn_constr = C_ERROR; /* put this error in the constant's data structure */ /* also store this error on the global list */ if (typtr->type_list == NIL) { value->cn_list = cons((list) errvalue, NIL); Errors = cons( cons((list) value, NIL), Errors); } else { value->cn_list = cons((list) errvalue, (list) typtr); Errors = cons( cons((list) value, (list) typtr), Errors); } } /* * recursively generate the code for a constant */ code_constant(typtr, value) struct type *typtr; struct constant *value; { switch (typtr->type_constr) { case C_NUMERIC: case C_BOOLEAN: case C_STRING: case C_ENUMERATION: if (value == (struct constant*) 0) fprintf(header, "0"); else fprintf(header, "%s", value->cn_value); break; case C_ARRAY: code_array_constant(typtr,value); break; case C_SEQUENCE: code_sequence_constant(typtr,value); break; case C_RECORD: code_record_constant(typtr,value); break; case C_CHOICE: code_choice_constant(typtr,value); break; case C_ERROR: error(ERROR,"Error constants may not be part of a structure"); break; case C_PROCEDURE: error(ERROR,"Procedures may not be part of a structure"); } } /* * Given the name of a record field and a record constant, return * the corresponding component of the record constant. */ static struct constant * findcomponent(name,recvalue) char *name; struct constant *recvalue; { list p; if (recvalue->cn_constr != C_RECORD) error(FATAL,"internal error (findcomponent): constant is of type %d", recvalue->cn_constr); for (p = recvalue->cn_list; p != NIL; p = cdr(p)) if (streq((char *) caar(p), name)) return((struct constant *) cdar(p)); return((struct constant *) 0); } /* * kludge since PCC doesn't like initializations of the form * struct {int length; Seqtype *sequence} seq = {3,{1,2,3}}; * instead, use: * Seqtype anonymous[3] = {1,2,3}; * struct {int length; Seqtype *sequence} seq = {3,anonymous}; * We have to generate the sequence value before we walk the constant. */ scan_for_sequences(typtr, value) struct type *typtr; struct constant *value; { list p; switch (typtr->type_constr) { case C_ARRAY: for (p = value->cn_list; p != NIL; p = cdr(p)) scan_for_sequences(typtr->type_basetype, (struct constant *) car(p)); break; case C_RECORD: scan_record_for_sequences(typtr, value); break; case C_CHOICE: scan_choice_for_sequences(typtr, value); break; case C_SEQUENCE: for (p = value->cn_list; p != NIL; p = cdr(p)) scan_for_sequences(typtr->type_basetype, (struct constant *) car(p)); value->cn_seqvalname = gensym("S_v"); fprintf(header,"\nstatic %s %s[%d] = {\n\t", typename(typtr->type_basetype), value->cn_seqvalname, length(value->cn_list)); for (p = value->cn_list ; p != NIL ; p = cdr(p)) { code_constant(typtr->type_basetype, (struct constant *) car(p)); if (cdr(p) != NIL) fprintf(header,",\n\t"); } fprintf(header,"\n};\n"); break; default: /* other types don't have embedded sequences */ break; } } scan_record_for_sequences(typtr, value) struct type *typtr; struct constant *value; { list p, q; struct constant *component; for (p = typtr->type_list; p != NIL; p = cdr(p)) { q = car(p); component = findcomponent((char *) caar(q),value); if (component != (struct constant *) 0) scan_for_sequences((struct type *) cdr(q), component); } } /*ARGSUSED*/ scan_choice_for_sequences(typtr, value) struct type *typtr; struct constant *value; { /* constants of type CHOICE are not implemented */ } code_array_constant(typtr, value) struct type *typtr; struct constant *value; { list p; int i; if (value == (struct constant *) 0) { fprintf(header,"{0"); for (i = 1; i < typtr->type_size; i++) fprintf(header,",0"); fprintf(header,"}"); return; } if (typtr->type_size != length(value->cn_list)) error(WARNING,"wrong number of constant elements specified for array"); fprintf(header,"\n\t{"); for (p = value->cn_list; p != NIL; p = cdr(p)) { code_constant(typtr->type_basetype,(struct constant *) car(p)); if (cdr(p) != NIL) fprintf(header,","); } fprintf(header,"}"); } code_choice_constant(typtr, value) struct type *typtr; struct constant *value; { list p,q; struct type *bt; char *desigval; struct object *name; if (value == (struct constant *)0) desigval = "?"; /* caar(typtr->type_designator->type_list); */ else desigval = (char *) car(value->cn_list); fprintf(header,"\n\t{ %s", desigval); /* find the corresponding arm of the choice */ bt = TNIL; for (p = typtr->type_candidates; bt==TNIL && p!=NIL; p = cdr(p)) { for (q = caar(p); bt==TNIL && q!=NIL; q = cdr(q)) { name = (struct object *) caar(q); if (streq(name->o_enum->en_name,desigval)) bt = (struct type *) cdar(p); } } if (bt == TNIL) error(WARNING,"CHOICE designator %s is invalid here",desigval); else if (bt != NilRecord_type) error(WARNING,"Constants of type CHOICE are not supported"); fprintf(header,"\n\t}"); } code_sequence_constant(typtr, value) struct type *typtr; struct constant *value; { list p; int l; if (value == (struct constant *)0 || (p = value->cn_list) == NIL) { fprintf(header,"{0, 0}"); return; } l = length(p); if (typtr->type_size < l) error(WARNING,"too many constant elements specified for sequence"); fprintf(header,"{%d, %s}",l,value->cn_seqvalname); } code_record_constant(typtr, value) struct type *typtr; struct constant *value; { list p, q; struct constant *component; fprintf(header,"{"); for (p = typtr->type_list; p != NIL; p = cdr(p)) { q = car(p); if (value == (struct constant *) 0) component = value; else component = findcomponent((char *) caar(q), value); code_constant((struct type *) cdr(q), component); if (cdr(p) != NIL) fprintf(header,","); } fprintf(header,"\n\t}"); }