home *** CD-ROM | disk | FTP | other *** search
- /* C* high level output routines.
-
- source: out.c
- started: February 22, 1989
- version:
- February 22, 1989
- March 8, 1989
-
- PUBLIC DOMAIN SOFTWARE
-
- The CSTAR program was placed in the public domain on June 15, 1991,
- by its author and sole owner,
-
- Edward K. Ream
- 1617 Monroe Street
- Madison, WI 53711
- (608) 257-0802
-
- CSTAR may be used for any commercial or non-commercial purpose.
-
- See cstar.h or cstar.c for a DISCLAIMER OF WARRANTIES.
- */
-
- #include "cstar.h"
-
- extern int sa_push[8];
- extern int sd_push[8];
- extern struct type_node * intrn_decl;
-
- /*
- Externally visible functions
- */
-
- void out_arg (struct node * p);
- void out_decl (struct type_node *t);
- void out_function (struct fbody *p, unsigned long link_size,
- int r_push, int do_addq);
- void out_list (register struct node *p);
- void out_tree (struct node * p);
-
- /*
- Internal functions
- */
- static void out_init (struct iblock *ibp, char *name);
- static void out_loc (register struct node *p);
- static void out_rlist (void);
- static void out_seg (int seg);
- static void out_strs (char *name, char *s, unsigned long dim);
-
- /*
- Part I: ----- Code Generation Output Routines -----
- */
-
- /*
- Output code for segment declaration if there is a change
- */
- static void
- out_seg(int seg)
- {
- if (seg == segment) {
- return;
- }
- segment = seg;
- switch(seg) {
- case S_BSS:
- syssput(".bss");
- break;
- case S_DATA:
- syssput(".data");
- break;
- case S_TEXT:
- syssput(".text");
- break;
- default:
- g_error(NULL, "internal: out_seg: bad segment");
- }
- sysnlput();
- }
-
- /*
- Output or generate code for a list of definitions/declarations.
-
- WARNING: no code generation (auto initializers) yet.
- */
- void
- out_decl(struct type_node *t)
- {
- register int class;
- register char *name;
- register struct st_node *id;
- unsigned long size;
- char buf[LONG_DIGITS];
-
- TICK("out_decl");
-
- if (nogen_flag) {
- /* Suppress code generation and output. */
- return;
- }
- while (t && t -> t_typtok == DELEMENT_TYPE) {
- id = t -> t_parent;
- if (id == NULL) {
- switch (t -> t_link -> t_typtok) {
- default:
- t_error("internal: no decl parent");
- case STRUCT_TYPE:
- case UNION_TYPE:
- ;
- }
- t = t -> t_list;
- continue;
- }
- class = id -> st_sclass;
- /* CAUTION: name may be junk for register class */
- name = id -> st_alias;
- size = t -> t_link -> t_tsize;
-
- switch (class) {
- /* NOTE: initialized globals go into the data segment
- and get set up with dc directives */
- case AUTO_CLASS:
- case REGISTER_CLASS:
- if (id -> st_iniz) {
- g_error(NULL, "register/auto init not ready yet");
- }
- /* FALLTHROUGH */
-
- case FORMAL_CLASS:
- case FORMREG_CLASS:
- /* output explanatory comment */
- syssput("*\t");
- syssput(id -> st_name);
- if (id -> st_offset) {
- syssput(" = ");
- convl2s(id -> st_offset, buf);
- syssput(buf);
- }
- if (id -> st_misc & ST_REG) {
- syssput(" = ");
- syssput(arp_tab[id -> st_misc & ST_REG]);
- }
- sysnlput();
- break;
-
- case EXTERN_CLASS:
- syssput(".globl ");
- syssput(name);
- sysnlput();
- break;
-
- case STATICL_CLASS:
- /* output explanatory comment */
- syssput("*\t");
- syssput(id -> st_name);
- syssput(" = ");
- syssput(name);
- sysnlput();
- /* FALLTHROUGH */
-
- case STATICG_CLASS:
- if (id -> st_iniz) {
- out_seg(S_DATA);
- out_init(id -> st_iniz, name);
- }
- else {
- out_seg(S_BSS);
- syssput(name);
- syssput(":\tds.b ");
- convl2s(size, buf);
- syssput(buf);
- sysnlput();
- }
- break;
-
- case GLOBAL_CLASS:
- out_seg(S_DATA);
- syssput(".globl ");
- syssput(name);
- sysnlput();
-
- if (id -> st_iniz) {
- out_init(id -> st_iniz, name);
- }
- else {
- syssput(".comm ");
- syssput(name);
- syscput(',');
- convl2s(size, buf);
- syssput(buf);
- sysnlput();
- }
- break;
-
- default:
- t_error("internal: out_decl: unknown class");
-
- case CODE_CLASS:
- case SCODE_CLASS:
- case TAG_CLASS:
- case TYPEDEF_CLASS:
- ;
- }
- t = t -> t_list;
- }
- }
-
- /*
- output a memory initializer, which means into the data segment
- this is for statics and globals
-
- it is of course useless for auto variables, for which the
- initialization must actually generate code
-
- t is a DELEMENT node
- */
- #define LINELEN 70
-
- static void
- out_init(struct iblock *ibp, char *name)
- {
- register unsigned long i;
- register int n, f, l;
- register struct iblock *p, *q;
- register unsigned char *s;
- unsigned char buf[LONG_DIGITS];
-
- TICK("out_init");
-
- p = ibp;
-
- #ifdef DEBUG
- if (p == NULL) {
- g_error(NULL, "internal: out_init: no block");
- }
- #endif
- while(p) {
- switch(p -> itype) {
- case 0:
- buf[0] = '$';
- f = FALSE;
- for (n = LINELEN + 1, i = 0; i < p -> idim; i++) {
- /*
- CAUTION:
- if you wish for this to output in hex,
- you MUST truncate the data to the
- appropriate width; otherwise, a byte -1
- will be output as $FFFFFFFF
- */
- if (q = (struct iblock* ) p -> idata[i] . ipt) {
- switch (q -> itype) {
- case ISTRS_DEC:
- s = (void *) q -> idata[1] . ipt;
- break;
- case ITAG_DEC:
- s = (void *) q -> idata[0] . ipt;
- break;
- default:
- g_error(NULL, "internal: out_init: unknown iblock type");
- }
- }
- else {
- convl2s(p -> idata [i] . icn, &buf[1]);
- s = &buf[1]; /* leave off $ for decimal */
- }
- l = str_len(s);
- if (n + l > LINELEN) {
- /* essentially, issue a line */
- f = FALSE;
- n = 5;
- if (name) {
- syssput(name);
- syscput(':');
- if (str_len(name) >= 7) {
- n += 8;
- }
- name = NULL;
- }
- else if (i) {
- sysnlput();
- }
- switch (p -> isize) {
- case 1:
- syssput("\tdc.b ");
- break;
- case 2:
- syssput("\tdc.w ");
- break;
- case 4:
- syssput("\tdc.l ");
- break;
- default:
- g_error(NULL, "internal: out_init: bad size");
- }
- }
- else {
- if (f) {
- syscput(',');
- n++;
- }
- }
- f = TRUE;
- n += l;
- syssput(s);
- } /* end for */
-
- /* end block */
- break;
-
- case IBSSZB_DEC:
- conul2sc(p -> idim, buf, 1);
- syssput("\tds.b ");
- syssput(buf);
- break;
-
- case ISTRA_DEC:
- out_strs( name,
- (char *) p -> idata[0] . ipt,
- (unsigned long) p -> idim);
- break;
-
- default:
- g_error(NULL, "internal: out_init: unknown block in series");
- } /* end switch */
- sysnlput();
-
- p = p -> ilink;
- } /* end while */
-
- /* now reiterate the loop to output secondary declarators */
- p = ibp;
- while (p) {
- if (p -> itype == 0) {
- for (i = 0; i < p -> idim; i++) {
- if (q = (struct iblock *)p->idata[i].ipt)
- switch(q -> itype) {
- case ISTRS_DEC:
- out_strs( (char *) q -> idata[1] . ipt,
- (char *) q -> idata[0] . ipt,
- (unsigned long) q -> idim);
- sysnlput();
- }
- }
- }
- p = p -> ilink;
- }
- }
-
- /*
- output a string-array declarator
- */
- static void
- out_strs(char *name, char *s, unsigned long dim)
- {
- register unsigned long i;
- int f, n, l;
- unsigned char buf[LONG_DIGITS];
-
- f = 0;
- buf[0] = '$';
- for (n = LINELEN + 1, i = 0; ; i++) {
- /* deal with chars one at a time */
- if (n > LINELEN - 5) {
- if (f & 2) {
- /* close quote before initiating line */
- syscput('\"');
- }
- if (name) {
- syssput(name);
- syscput(':');
- name = NULL;
- }
- else if (i) {
- sysnlput();
- }
- syssput("\tdc.b ");
- n = 5;
- }
- if (s[i] >= ' ' && s[i] < 0x7f && s[i] != '\"') {
- /* printable */
- if (!(f & 2)) {
- /* flip to printable (quote mode) */
- if (f & 1) {
- syscput(',');
- n++;
- }
- syscput('\"');
- f |= 2;
- n++;
- }
- syscput(s[i]);
- }
- else {
- if (f & 2) {
- /* flip to nonprintable */
- syscput('\"');
- f ^= 2;
- n++;
- }
- if (f & 1) {
- syscput(',');
- n++;
- }
- conl2h( (unsigned long) s[i], &buf[1], 1);
- syssput(buf);
- n += str_len(buf);
- }
- f |= 1; /* char out so flag comma required */
- if (i + 1 >= dim) {
- /* close any quote and exit */
- if (f & 2) {
- syscput('\"');
- }
- break;
- }
- } /* end for */
- }
-
- /* actual file output */
- void
- out_function(struct fbody *p, unsigned long link_size, int r_push, int do_addq)
- {
- char buf[LONG_DIGITS];
-
- /* output the function header */
- syssput("** function ");
- syssput(p -> fname);
- sysnlput();
-
- /* output the strings and block decls */
- out_decl(intrn_decl);
-
- if (p -> fclass == CODE_CLASS) {
- syssput(".globl "); /* declaration of the function name */
- syssput(p -> fname);
- sysnlput();
- }
-
- out_decl(p -> formals); /* definition of the formals */
- out_decl(p -> locals); /* and the locals */
- out_seg(S_TEXT);
- syssput(p -> fname); /* label for the first instruction in the fn */
- syscput(':');
- sysnlput();
-
- /* Output the entry code. */
- if (link_size || p -> fml_size) {
- conul2sc(link_size, buf, 1);
- if (link_size < 32768L) {
- syssput("\tlink a6,#-");
- syssput(buf);
- sysnlput();
- }
- else {
- syssput("\tmove.l a6,-(a7)");
- sysnlput();
- syssput("\tmove.l a7,a6");
- sysnlput();
- syssput("\tsuba.l #");
- syssput(buf);
- syssput(",a7");
- sysnlput();
- }
- }
-
- /* output the register saves */
- if (r_push) {
- syssput("\tmovem.l\t");
- out_rlist();
- syssput(",-(a7)");
- sysnlput();
- }
- if (do_addq) {
- syssput("\tsubq.l #4, a7");
- }
-
- /*
- Call the peep hole optimizer.
- The nopeep_flag disables the peephole,
- so there is no need for a before and after picture.
- */
- if (!nopeep_flag) {
- if (code1_flag) {
- sysnlput();
- syssput("* >>>>> code prior to peephole:");
- sysnlput();
- sysnlput();
- out_list(code_head);
- sysnlput();
- }
- peep_hole();
-
- if (code2_flag) {
- sysnlput();
- syssput("* >>>>> code after peephole:");
- sysnlput();
- sysnlput();
- /* Print function name for reference. */
- syssput(p -> fname);
- syscput(':');
- sysnlput();
- }
- }
-
- /* output the code list */
- out_list(code_head);
-
- /* output the register restores and actual exit */
- if (do_addq) {
- syssput("\taddq.l #4,a7");
- sysnlput();
- }
- if (r_push) {
- syssput("\tmovem.l\t");
- syssput("(a7)+,");
- out_rlist();
- sysnlput();
- }
- if (link_size || p -> fml_size) {
- if (link_size < 32768L) {
- syssput("\tunlk a6");
- sysnlput();
- }
- else {
- syssput("\tmove.l a6,a7");
- sysnlput();
- syssput("\tmove.l (a7)+,a6");
- sysnlput();
- }
- }
- syssput("\trts");
- sysnlput();
- }
-
- static void
- out_rlist(void)
- {
- register int i, f;
-
- f = FALSE;
- for (i = 0; i <= 7; i++) {
- if (sd_push[i]) {
- if (f) {
- syscput('/');
- }
- syssput(arp_tab[d_reg(i)]);
- f = TRUE;
- }
- }
- for (i = 0; i <= 7; i++) {
- if (sa_push[i]) {
- if (f) {
- syscput('/');
- }
- syssput(arp_tab[a_reg(i)]);
- f = TRUE;
- }
- }
- }
-
- /*
- Part II: ----- Output routines to dump parse trees -----
- */
- static void out_expr(struct node *p);
- static void out_stat(struct node *p);
- static void out_stat(struct node *p);
- static void out_type(struct type_node *p);
- static void out_1type(struct type_node *t, bool usexpand, bool fnexpand);
-
- /*
- Print a list of parse nodes.
-
- See the file par.h for the definitions of these nodes.
- */
- void
- out_tree(struct node * p)
- {
- register int i;
- register int type;
- register struct type_node *id;
- register struct node *q;
- char buffer [100];
-
- SL_DISABLE();
-
- if (p == NULL) {
- syssput("<NO CODE LIST>");
- sysnlput();
- return;
- }
-
- do {
-
- switch (p -> n_type) {
-
- case CALL_TOK:
- syssput("CALL[");
- out_expr(p -> n_arg1);
- syssput(",");
- sysnlput();
- syssput("[");
- out_expr(p -> n_arg2);
- syssput("]]");
- sysnlput();
- break;
-
- case Z_TOK:
- sprintf(&buffer[0], "pseudo: %s: ", xzp_tab [p -> n_ztype]);
- syssput(buffer);
- out_expr(p -> n_zarg1);
- sysnlput();
- break;
-
- case X_TOK:
- type = p -> n_xtype;
- sprintf(&buffer[0], "x_tok: %s(", xzp_tab [type]);
- syssput(buffer);
- if (type == X_BRA || type == X_BSR || is_bxx(type)) {
- syssput("label: ");
- syssput(p -> n_arg1 -> c_labsym);
- }
- else if (is_dbxx(type)) {
- out_expr(p -> n_xarg1);
- syssput(",label: ");
- syssput(p -> n_arg2 -> c_labsym);
- }
- else if (type == X_JMP || type == X_JSR) {
- if (p -> n_xarg1) {
- out_expr(p -> n_xarg1);
- }
- if (p -> n_arg2) {
- syssput("label: ");
- syssput(p -> n_arg2 -> c_labsym);
- }
- }
- else if (p -> n_xarg1) {
- out_expr(p -> n_xarg1);
- if (p -> n_xarg2) {
- syssput(", ");
- out_expr(p -> n_xarg2);
- }
- }
- syssput(")");
- sysnlput();
- break;
-
- case K_IF:
- syssput("if (");
- out_expr(p -> n_ibool);
- syssput(")");
- sysnlput();
- out_stat(p -> n_ithen);
- sysnlput();
- if (p -> n_ielse) {
- syssput("else ");
- out_stat(p -> n_ielse);
- sysnlput();
- }
- break;
-
- case K_DO:
- syssput("do ");
- out_stat(p -> n_dbdy);
- syssput(" while (");
- out_expr(p -> n_dbool);
- syssput(")");
- sysnlput();
- break;
-
- case K_WHILE:
- syssput("while (");
- out_expr(p -> n_wbool);
- syssput(")");
- out_stat(p -> n_wbdy);
- sysnlput();
- break;
-
- case K_FOR:
- syssput("for(");
- out_tree(p -> n_f1list);
- syssput(";");
- out_expr(p -> n_fbool);
- syssput(";");
- out_tree(p -> n_f2list);
- syssput(") ");
- out_stat(p -> n_fbdy);
- sysnlput();
- break;
-
- case K_SWITCH:
- syssput("switch(");
- out_expr(p -> n_sval);
- syssput(") ");
- out_stat(p -> n_sbdy);
- sysnlput();
- break;
-
- case K_BREAK:
- syssput("break;");
- sysnlput();
- break;
-
- case K_CONTINUE:
- syssput("continue;");
- sysnlput();
- break;
-
- case K_CASE:
- sprintf(&buffer[0], "case %ld:", p -> n_ccon);
- syssput(buffer);
- sysnlput();
- break;
-
- case K_DEFAULT:
- syssput("default:");
- sysnlput();
- break;
-
- case K_RETURN:
- syssput("return");
- if (p -> n_rval) {
- syssput("(");
- out_expr(p -> n_rval);
- syssput(")");
- }
- syssput(";");
- sysnlput();
- break;
-
- case LABEL_TOK:
- syssput("<LABEL> ");
- syssput(p -> n_plab -> c_labsym);
- syssput(":");
- sysnlput();
- break;
-
- case K_GOTO:
- syssput("goto ");
- syssput(p -> n_plab -> c_labsym);
- syssput(";");
- sysnlput();
- break;
-
- /* uop_node and binop_node */
- default:
-
- i = p -> n_type;
- if (is_op(i) || i == ID_TOK) {
- out_expr(p);
- sysnlput();
- }
- else {
- sprintf(&buffer[0], "<INAPPROPRIATE NODE %d>",
- p -> n_type);
- syssput(buffer);
- sysnlput();
- }
- break;
- } /* end switch */
- } /* end dowhile */
- while ( (p = p -> n_next) != NULL);
- }
-
- /*
- Print an expression.
- See the file par.h for the definitions of these nodes.
- */
- static void
- out_expr(register struct node * p)
- {
- register struct st_node * id;
- register int i;
- char buffer [100];
-
- TICK("out_expr");
- if (p == NULL) {
- syssput("<NULL>");
- return;
- }
-
- switch (p -> n_type) {
-
- case ID_TOK:
- if (p -> n_cid != NULL) {
- id = p -> n_cid;
- if ((long)id & 1) {
- sprintf(&buffer[0], "id: <%p>", id);
- syssput(buffer);
- }
- else {
- sprintf(&buffer[0], "id: %s", id -> st_name);
- syssput(buffer);
- }
- }
- else if (p -> n_reg1) {
- sprintf(&buffer[0], "reg: %s", arp_tab[p -> n_reg1]);
- syssput(buffer);
- }
- else if (p -> n_cltype != NULL) {
- switch( (p -> n_cltype) -> t_typtok) {
-
- case INT_TYPE:
- i = p -> n_cltype -> t_mclass;
- if (i & UNSIGNED_MOD) {
- syssput("(u ");
- }
- else {
- syssput("(s ");
- }
-
- if (i & LONG_MOD) {
- syssput("long)");
- }
- else if (i & SHORT_MOD) {
- syssput("short)");
- }
- else if (i & CHAR_MOD) {
- syssput("char)");
- }
- else {
- syssput("int)");
- }
-
- if (i & UNSIGNED_MOD) {
- sprintf(&buffer[0], "%lu", p -> n_const);
- syssput(buffer);
- }
- else {
- sprintf(&buffer[0], "%ld", p -> n_const);
- syssput(buffer);
- }
- break;
-
- case SELEMENT_TYPE:
- case UELEMENT_TYPE:
- case DELEMENT_TYPE:
- sprintf(&buffer[0], "(elt) %lu", p -> n_const);
- syssput(buffer);
- break;
-
- case ARRAY_TYPE:
- /* one should possibly check further */
- sprintf(&buffer[0], "\"%s\"", p -> n_const);
- syssput(buffer);
- break;
-
- case POINTER_TYPE:
- sprintf(&buffer[0], "(pointer)%ld", p -> n_const);
- syssput(buffer);
- break;
-
- default:
- sprintf(&buffer[0], "%ld<unknown type>", p -> n_const);
- syssput(buffer);
- break;
- }
- }
- else {
- sprintf(&buffer[0], "%ld<missing type>", p -> n_const);
- syssput(buffer);
- }
- break;
-
- case CALL_TOK:
- syssput("CALL[");
- out_expr(p -> n_arg1);
- syssput(",");
- sysnlput();
- syssput("[");
- out_expr(p -> n_arg2);
- syssput("]]");
- break;
-
- case CC_TOK:
- sprintf(&buffer[0], "cc: %s", arp_tab [p -> n_xtype]);
- syssput(buffer);
- break;
-
- case SEPARATOR_TOK:
- out_expr(p -> n_car);
- syssput(" @ ");
- sysnlput();
- out_expr(p -> n_next); /* n_next acts like n_arg2? */
- break;
-
- case K_CHAR:
- case K_INT:
- case K_LONG:
- case K_STRUCT:
- case K_UNION:
- case K_TYPEDEF:
- syssput("out_expr: what is this??");
- sysnlput();
- out_type((struct type_node *)p);
- break;
-
- case QUESTION_TOK:
- /* Ternary OP. */
- syssput("?:[");
- out_expr(p -> n_arg1);
- syssput(",");
- sysnlput();
- out_expr(p -> n_arg2);
- syssput(",");
- sysnlput();
- out_expr(p -> n_arg3);
- syssput("]");
- break;
-
- /* uop_node and binop_node */
- default:
-
- i = p -> n_type;
- if (is_op(i)) {
- syssput(ps_tok(i));
- if (is_unop(i)) {
- /* Unary OP. */
- if (i == CAST_TOK) {
- syssput("(");
- out_1type(p -> n_cltype, TRUE, TRUE);
- syssput(")");
- }
- syssput("[");
- out_expr(p -> n_arg1);
- syssput("]");
- }
- else {
- /* Binary OP. */
- syssput("[");
- out_expr(p -> n_arg1);
- syssput(",");
- sysnlput();
- out_expr(p -> n_arg2);
- syssput("]");
- }
- }
- else {
- sprintf(&buffer[0],
- "node \"%s\" (%d) doesn't belong in expression",
- ps_tok(i), i);
- syssput(buffer);
- sysnlput();
- }
- } /* (end switch) */
- }
-
- /*
- Print a statement list enclosed in curly braces.
- */
- static void
- out_stat(struct node * p)
- {
- syssput("{");
- if (p != NULL) {
- sysnlput();
- out_tree(p);
- }
- syssput("}");
- }
-
- /*
- Print a type.
- */
- static void
- out_type(struct type_node *t)
- {
- TICK("prtype");
- out_1type(t, TRUE, TRUE);
- sysnlput();
- }
-
- static void
- out_1type(register struct type_node * t, bool usexpand, bool fnexpand)
- {
- int i;
- char buffer [100];
-
- for(;;) {
- if (t == NULL) {
- syssput("<NO TYPE>");
- return;
- }
-
- /* first the primary printout */
- i = t -> t_typtok;
- if (t -> t_mclass & CONST_MOD) {
- syssput("const ");
- }
- if (t -> t_mclass & VOLATILE_MOD) {
- syssput("volatile ");
- }
- switch (i) {
- case NULL_TYPE:
- syssput("NULLtype");
- return;
-
- case BOOL_TYPE:
- case FLOAT_TYPE:
- case INT_TYPE:
- case VOID_TYPE:
- if (t -> t_mclass & UNSIGNED_MOD) {
- syssput("unsigned ");
- }
- if (t -> t_mclass & CHAR_MOD) {
- if (!(t -> t_mclass & UNSIGNED_MOD)) {
- syssput("signed ");
- }
- syssput("char");
- }
- if (t -> t_mclass & SHORT_MOD) {
- syssput("short ");
- }
- if (t -> t_mclass & LONG_MOD) {
- syssput("long ");
- }
- break;
-
- case ARRAY_TYPE:
- sprintf(&buffer[0], "array [%ld] of ", t -> t_tdim);
- syssput(buffer);
- break;
-
- case FUNCTION_TYPE: syssput("function"); break;
- case POINTER_TYPE: syssput("pointer to "); break;
- case CAST_TYPE: syssput("cast into "); break;
-
- case STRUCT_TYPE:
- sprintf(&buffer[0], "struct %p {%ld}:",
- t, t -> t_tsize);
- syssput(buffer);
- break;
-
- case UNION_TYPE:
- sprintf(&buffer[0], "union %p {%ld}:",
- t, t -> t_tsize);
- syssput(buffer);
- break;
-
- case DECL_TYPE:
- sprintf(&buffer[0], "DECL <%ld>:", t -> t_tsize);
- syssput(buffer);
- sysnlput();
- break;
-
- case DELEMENT_TYPE:
- syssput("delement--");
- break;
-
- case SELEMENT_TYPE:
- syssput(" selement--");
- break;
-
- case UELEMENT_TYPE:
- syssput(" uelement--");
- break;
-
- default:
- sprintf(&buffer[0], "out_type: unknown type %d", t -> t_typtok);
- syssput(buffer);
- return;
- }
-
- /* then further explanation and linkage */
- switch (i) {
- case DECL_TYPE:
- t = t -> t_list;
- break;
-
- case FUNCTION_TYPE:
- if (t -> t_list == NULL) {
- syssput(" returning ");
- }
- else {
- syssput("--");
- sysnlput();
- out_1type(t -> t_list, usexpand, FALSE);
- sysnlput();
- syssput("--which returns ");
- }
- t = t -> t_link;
- break;
-
- case STRUCT_TYPE:
- case UNION_TYPE:
- if (t -> t_list == NULL) {
- syssput(" <NO LIST>");
- }
- else if (usexpand) {
- sysnlput();
- out_1type(t -> t_list, FALSE, fnexpand);
- }
- else {
- syssput(" ...");
- }
- return;
-
- case DELEMENT_TYPE:
- case SELEMENT_TYPE:
- case UELEMENT_TYPE:
- if (t -> t_parent) {
- if (t -> t_parent -> st_name) {
- syssput(t -> t_parent -> st_name);
- syssput(" ");
- if (t -> t_parent -> st_alias) {
- syssput(t -> t_parent -> st_alias);
- }
- }
- sprintf(&buffer[0], "@%ld: ",
- t -> t_parent -> st_offset);
- syssput(buffer);
- }
- out_1type(t -> t_link, usexpand, fnexpand);
- t = t -> t_list;
- if (t == NULL) {
- return;
- }
- if (t -> t_typtok != i) {
- syssput("<t_list structure error>");
- }
- sysnlput();
- break;
-
- case ARRAY_TYPE:
- case POINTER_TYPE:
- t = t -> t_link;
- break;
-
- case BOOL_TYPE: syssput("bool"); return;
- case VOID_TYPE: syssput("void"); return;
-
- case INT_TYPE:
- if (!(t -> t_mclass & CHAR_MOD)) {
- syssput("int");
- }
- if (t -> t_link) {
- sprintf(&buffer[0], "<<error> link=%p>",
- t->t_link);
- syssput(buffer);
- }
- return;
-
- case FLOAT_TYPE:
- syssput("float");
- return;
-
- default:
- syssput("out_type: internal");
- sysnlput();
- return;
- }
- }
- }
-
- /*
- Part III: ----- Output routines to dump code nodes -----
- */
-
- /*
- Go down the global code list and output code.
- */
- void
- out_list(register struct node *p)
- {
- register int type;
- char buffer [40];
-
- TICK("out_list");
-
- for(; p; p = p -> c_next) {
- type = p -> c_code;
- if (is_xtok(type)) {
-
- /* Output machine code to file. */
- syscput('\t');
- syssput(xzp_tab [type]);
-
- if (p -> c_len1) {
- syssput(xlentab[p -> c_len1]);
- }
-
- /* Output 0, 1 or 2 arguments. */
- if (p -> c_arg1) {
- syscput('\t');
- out_arg(p -> c_arg1);
- }
- if (p -> c_arg2) {
- if (!(p -> c_arg1)) {
- syscput('\t');
- syssput("<NULL>");
- }
- syscput(',');
- out_arg(p -> c_arg2);
- }
- }
- else if (is_ztok(type)) {
- /* Output pseudo op to file. */
- syscput('\t');
- syssput(xzp_tab [type]);
- }
- else {
- switch (type) {
- case O_LITERAL:
- out_arg(p);
- break;
-
- case O_LINENUM:
- syssput("* ----- line ");
- conv2s(p -> c_linenum, buffer);
- syssput(buffer);
- break;
-
- case O_LABEL:
- case O_ULABEL:
- out_arg(p);
- syscput(':');
- break;
-
- default:
- g_error(NULL, "unknown code type");
-
- /* Include error message in the file. */
- syssput("* unknown code type: ");
- conv2s(type, buffer);
- syssput(buffer);
- }
- }
- sysnlput();
- }
- }
-
- /*
- Output an argument, which is a label or a loc_node.
- */
- void
- out_arg(struct node * p)
- {
- char buffer [40];
- struct st_node *id;
- /* WARNING: the label nodes and the id nodes aren't the same kind */
-
- TICK("out_arg");
-
- if (p == NULL) {
- return;
- }
-
- switch(p -> c_code) {
-
- case O_LABEL:
- syscput('L');
- conv2s(p -> c_labnum, buffer);
- syssput(buffer);
- return;
-
- case O_ULABEL:
- /* Output internal label to file. */
- if (p -> c_labnum) {
- syscput('U');
- conv2s(p -> c_labnum, buffer);
- syssput(buffer);
- }
- else {
- syssput(p -> c_labsym);
- }
- break;
-
- case O_LITERAL:
- syssput(p -> c_lit);
- return;
-
- case ID_TOK:
- out_loc(p);
- return;
-
- default:
- g_error(p, "out_arg: internal: bad node\n");
- printf("bad node %p: c_code=%d %s\n",
- p, p -> c_code, ps_tok(p->c_code));
- }
- }
-
- /*
- Output a loc node.
- */
- static void
- out_loc(register struct node *p)
- {
- char buffer[40];
- register char mode;
- register struct st_node *id;
-
- mode = p -> n_mode;
- if (mode == VALUE_MODE) {
- if (!p -> n_reg1) {
- syscput('#');
- }
- }
- if (id = p -> n_cid) {
- syssput(id -> st_alias);
- }
- if (p -> n_const || (!p -> n_cid &&
- ((p -> n_reg1 && p -> n_reg2) || (!p -> n_reg1 && !p -> n_reg2)) ) ) {
- if (p -> n_cid && p -> n_const >= 0) {
- syscput('+');
- }
- convl2s(p -> n_const, buffer);
- syssput(buffer);
- }
- if (mode && p -> n_reg1) {
- if (mode == EAPRD_MODE) {
- syscput('-');
- }
- syscput('(');
- }
-
- if (p -> n_reg1) {
- syssput(arp_tab [p -> n_reg1]);
-
- if (p -> n_reg2) {
- syscput(',');
- syssput(arp_tab [p -> n_reg2]);
- switch (p -> n_scflag) {
- case X2_WORD:
- syssput(".w");
- break;
- case X2_LONG:
- syssput(".l");
- break;
- default:
- g_error(p, "out_loc: internal: unscaled reg2\n");
- break;
- case 0:
- case X2_OK:
- ;
- }
- }
- }
- if (mode && p -> n_reg1) {
- syscput(')');
- if (mode == EAPSI_MODE) {
- syscput('+');
- }
- }
- }
-
- char *
- ps_tok(int tok)
- {
- if (tok > 0 && tok <= LABEL_TOK) {
- return kp_tab[tok];
- }
- else {
- return "<bad TOKEN>";
- }
- }
-