diff --git a/src/snc/gen_code.c b/src/snc/gen_code.c index 79af07a5493b155597a52b58eed6622a2dee14ed..74665ab0fb6ef325715cbddcb22e56ceda86fd46 100644 --- a/src/snc/gen_code.c +++ b/src/snc/gen_code.c @@ -22,6 +22,7 @@ in the file LICENSE that is included with this distribution. #include "gen_code.h" static void gen_preamble(char *prog_name); +static void gen_header_preamble(char *prog_name); static void gen_main(char *prog_name); static void gen_user_var(Program *p); static void gen_global_c_code(Expr *global_c_list); @@ -41,7 +42,7 @@ static int assert_var_declared(Expr *ep, Expr *scope, void *parg) } /* Generate C code from parse tree. */ -void generate_code(Program *p) +void generate_code(Program *p, const char *header_name) { /* assume there have been no errors, so all vars are declared */ traverse_expr_tree(p->prog, 1<<E_VAR, 0, 0, assert_var_declared, 0); @@ -50,24 +51,31 @@ void generate_code(Program *p) report("-------------------- Code Generation --------------------\n"); #endif -#ifdef DEBUG - report("gen_tables:\n"); - report(" num_event_flags = %d\n", p->num_event_flags); - report(" num_ss = %d\n", p->num_ss); -#endif - - /* Generate preamble code */ - gen_preamble(p->name); - /* Initialize tables in gen_ss_code module */ /* TODO: find a better way to do this */ init_gen_ss_code(p); + set_gen_h(); + + gen_code("/* Generated with snc from %s */\n", p->prog->src_file); + gen_code("#ifndef INCL%sh\n", p->name); + gen_code("#define INCL%sh\n", p->name); + + /* Generate preamble code */ + gen_header_preamble(p->name); + /* Generate literal C code intermixed with global definitions */ gen_defn_c_code(p->prog, 0); /* Generate global, state set, and state variable declarations */ gen_user_var(p); + gen_code("#endif /* INCL%sh */\n", p->name); + + set_gen_c(); + + gen_code("/* Generated with snc from %s */\n", p->prog->src_file); + gen_preamble(p->name); + gen_code("#include \"%s\"\n", header_name); /* Generate code for each state set */ gen_ss_code(p); @@ -88,23 +96,32 @@ void generate_code(Program *p) /* Generate main program */ static void gen_main(char *prog_name) { - printf("\n#define PROG_NAME %s\n", prog_name); - printf("#include \"seqMain.c\"\n"); + gen_code("\n#define PROG_NAME %s\n", prog_name); + gen_code("#include \"seqMain.c\"\n"); +} + +/* Generate header preamble (includes, defines, etc.) */ +static void gen_header_preamble(char *prog_name) +{ + /* Program name (comment) */ + gen_code("\n/* Header file for program \"%s\" */\n", prog_name); + + /* Includes */ + gen_code("#include \"epicsTypes.h\"\n"); + gen_code("#include \"seqCom.h\"\n"); } /* Generate preamble (includes, defines, etc.) */ static void gen_preamble(char *prog_name) { /* Program name (comment) */ - printf("\n/* Program \"%s\" */\n", prog_name); + gen_code("\n/* C code for program \"%s\" */\n", prog_name); /* Includes */ - printf("#include <string.h>\n"); - printf("#include <stddef.h>\n"); - printf("#include <stdio.h>\n"); - printf("#include <limits.h>\n"); - printf("#include \"epicsTypes.h\"\n"); - printf("#include \"seqCom.h\"\n"); + gen_code("#include <string.h>\n"); + gen_code("#include <stddef.h>\n"); + gen_code("#include <stdio.h>\n"); + gen_code("#include <limits.h>\n"); } void gen_var_decl(Var *vp) @@ -125,24 +142,24 @@ static void gen_user_var(Program *p) Var *vp; Expr *sp, *ssp; - printf("\n/* Variable declarations */\n"); + gen_code("\n/* Variable declarations */\n"); - if (opt_reent) printf("struct %s {\n", NM_VARS); + if (opt_reent) gen_code("struct %s {\n", NM_VARS); /* Convert internal type to `C' type */ foreach (vp, p->prog->extra.e_prog->first) { if (vp->decl && vp->type->tag >= V_CHAR) { gen_line_marker(vp->decl); - if (!opt_reent) printf("static"); + if (!opt_reent) gen_code("static"); indent(1); gen_var_decl(vp); if (!opt_reent) { - printf(" = "); + gen_code(" = "); gen_var_init(vp, 0); } - printf(";\n"); + gen_code(";\n"); } } foreach (ssp, p->prog->prog_statesets) @@ -164,10 +181,10 @@ static void gen_user_var(Program *p) if (!ss_empty) { - indent(level); printf("struct %s_%s {\n", NM_VARS, ssp->value); + indent(level); gen_code("struct %s_%s {\n", NM_VARS, ssp->value); foreach (vp, ssp->extra.e_ss->var_list->first) { - indent(level+1); gen_var_decl(vp); printf(";\n"); + indent(level+1); gen_var_decl(vp); gen_code(";\n"); } foreach (sp, ssp->ss_states) { @@ -175,26 +192,26 @@ static void gen_user_var(Program *p) if (!s_empty) { indent(level+1); - printf("struct {\n"); + gen_code("struct {\n"); foreach (vp, sp->extra.e_state->var_list->first) { - indent(level+2); gen_var_decl(vp); printf(";\n"); + indent(level+2); gen_var_decl(vp); gen_code(";\n"); } indent(level+1); - printf("} %s_%s;\n", NM_VARS, sp->value); + gen_code("} %s_%s;\n", NM_VARS, sp->value); } } - indent(level); printf("} %s_%s", NM_VARS, ssp->value); + indent(level); gen_code("} %s_%s", NM_VARS, ssp->value); if (!opt_reent) { - printf(" = "); + gen_code(" = "); gen_ss_user_var_init(ssp, level); } - printf(";\n"); + gen_code(";\n"); } } - if (opt_reent) printf("};\n"); - printf("\n"); + if (opt_reent) gen_code("};\n"); + gen_code("\n"); } /* Generate C code in definition section */ @@ -212,11 +229,11 @@ void gen_defn_c_code(Expr *scope, int level) { first = FALSE; indent(level); - printf("/* C code definitions */\n"); + gen_code("/* C code definitions */\n"); } gen_line_marker(ep); indent(level); - printf("%s\n", ep->value); + gen_code("%s\n", ep->value); } } } @@ -228,29 +245,29 @@ static void gen_global_c_code(Expr *global_c_list) if (global_c_list != 0) { - printf("\n/* Global C code */\n"); + gen_code("\n/* Global C code */\n"); foreach (ep, global_c_list) { assert(ep->type == T_TEXT); gen_line_marker(ep); - printf("%s\n", ep->value); + gen_code("%s\n", ep->value); } } } static void gen_init_reg(char *prog_name) { - printf("\n/* Register sequencer commands and program */\n"); - printf("#include \"epicsExport.h\"\n"); - printf("static void %sRegistrar (void) {\n", prog_name); - printf(" seqRegisterSequencerCommands();\n"); - printf(" seqRegisterSequencerProgram (&%s);\n", prog_name); - printf("}\n"); - printf("epicsExportRegistrar(%sRegistrar);\n", prog_name); + gen_code("\n/* Register sequencer commands and program */\n"); + gen_code("#include \"epicsExport.h\"\n"); + gen_code("static void %sRegistrar (void) {\n", prog_name); + gen_code(" seqRegisterSequencerCommands();\n"); + gen_code(" seqRegisterSequencerProgram (&%s);\n", prog_name); + gen_code("}\n"); + gen_code("epicsExportRegistrar(%sRegistrar);\n", prog_name); } void indent(int level) { while (level-- > 0) - printf("\t"); + gen_code("\t"); } diff --git a/src/snc/gen_code.h b/src/snc/gen_code.h index 56a54992fb44317bd061120c8ea8f7397d4bf6fe..19634144384ad1473f75cf53b5bad486a75ab393 100644 --- a/src/snc/gen_code.h +++ b/src/snc/gen_code.h @@ -15,7 +15,7 @@ in the file LICENSE that is included with this distribution. #include "types.h" -void generate_code(Program *p); +void generate_code(Program *p, const char *header_name); void gen_defn_c_code(Expr *scope, int level); void gen_var_decl(Var *vp); void indent(int level); diff --git a/src/snc/gen_ss_code.c b/src/snc/gen_ss_code.c index 23f6b00ee40d6f584d5c378028bd1d6395263f92..cf991c7b616b1d8fc9fe7240af9acc16ef9f7e05 100644 --- a/src/snc/gen_ss_code.c +++ b/src/snc/gen_ss_code.c @@ -104,7 +104,7 @@ void gen_ss_code(Program *program) /* For each state ... */ foreach (sp, ssp->ss_states) { - printf("\n/****** Code for state \"%s\" in state set \"%s\" ******/\n", + gen_code("\n/****** Code for state \"%s\" in state set \"%s\" ******/\n", sp->value, ssp->value); /* Generate entry and exit functions */ @@ -160,10 +160,10 @@ static void gen_local_var_decls(Expr *scope, int level) /* optional initialisation */ if (vp->init) { - printf(" = "); + gen_code(" = "); gen_expr(C_INIT, vp->init, level); } - printf(";\n"); + gen_code(";\n"); } } } @@ -176,19 +176,19 @@ static void gen_type_default(Type *type) switch(type->tag) { case V_STRING: - printf("\"\""); + gen_code("\"\""); break; case T_ARRAY: - printf("{"); + gen_code("{"); for (n=0; n<type->val.array.num_elems; n++) { gen_type_default(type->val.array.elem_type); - if (n+1<type->val.array.num_elems) printf(","); + if (n+1<type->val.array.num_elems) gen_code(","); } - printf("}"); + gen_code("}"); break; default: - printf("0"); + gen_code("0"); } } @@ -214,12 +214,12 @@ static void gen_state_func( const char *extra_args ) { - printf("\n/* %s function for state \"%s\" in state set \"%s\" */\n", + gen_code("\n/* %s function for state \"%s\" in state set \"%s\" */\n", title, state_name, ss_name); - printf("static %s %s_%s_%d_%s(SS_ID " NM_SS ", SEQ_VARS *const " NM_VARS "%s)\n{\n", + gen_code("static %s %s_%s_%d_%s(SS_ID " NM_SS ", SEQ_VARS *const " NM_VARS "%s)\n{\n", rettype, prefix, ss_name, ss_num, state_name, extra_args); gen_body(xp); - printf("}\n"); + gen_code("}\n"); } static void gen_entex_body(Expr *xp) @@ -260,11 +260,11 @@ static int gen_delay(Expr *ep, Expr *scope, void *parg) assert(ep->type == E_DELAY); gen_line_marker(ep); /* Generate 1-st part of function w/ 1-st 2 parameters */ - indent(1); printf("seq_delayInit(" NM_SS ", %d, (", ep->extra.e_delay); + indent(1); gen_code("seq_delayInit(" NM_SS ", %d, (", ep->extra.e_delay); /* generate the 3-rd parameter (an expression) */ gen_expr(C_COND, ep->delay_args, 0); /* Complete the function call */ - printf("));\n"); + gen_code("));\n"); return FALSE; /* no sense descending into children, as delay cannot be nested */ } @@ -278,8 +278,8 @@ static void gen_action_body(Expr *xp) const int level = 1; /* "switch" statment based on the transition number */ - indent(level); printf("switch(" NM_TRN ")\n"); - indent(level); printf("{\n"); + indent(level); gen_code("switch(" NM_TRN ")\n"); + indent(level); gen_code("{\n"); trans_num = 0; /* For each transition ("when" statement) ... */ @@ -289,29 +289,29 @@ static void gen_action_body(Expr *xp) assert(tp->type == D_WHEN); /* one case for each transition */ - indent(level); printf("case %d:\n", trans_num); + indent(level); gen_code("case %d:\n", trans_num); /* block within case permits local variables */ - indent(level+1); printf("{\n"); + indent(level+1); gen_code("{\n"); /* for each definition insert corresponding code */ gen_local_var_decls(tp, level+2); gen_defn_c_code(tp, level+2); if (tp->when_defns) - printf("\n"); + gen_code("\n"); /* for each action statement insert action code */ foreach (ap, tp->when_stmts) { gen_expr(C_TRANS, ap, level+2); } /* end of block */ - indent(level+1); printf("}\n"); + indent(level+1); gen_code("}\n"); /* end of case */ - indent(level+1); printf("return;\n"); + indent(level+1); gen_code("return;\n"); trans_num++; } /* end of switch stmt */ - indent(level); printf("}\n"); + indent(level); gen_code("}\n"); } /* Generate a C function that checks events for a particular state */ @@ -330,32 +330,32 @@ static void gen_event_body(Expr *xp) assert(tp->type == D_WHEN); if (tp->when_cond) gen_line_marker(tp->when_cond); - indent(level); printf("if ("); + indent(level); gen_code("if ("); if (tp->when_cond == 0) - printf("TRUE"); + gen_code("TRUE"); else gen_expr(C_COND, tp->when_cond, 0); - printf(")\n"); - indent(level); printf("{\n"); + gen_code(")\n"); + indent(level); gen_code("{\n"); next_sp = tp->extra.e_when->next_state; if (!next_sp) { /* "when(...) {...} exit" -> exit from program */ indent(level+1); - printf("seq_exit(" NM_SS ");\n"); + gen_code("seq_exit(" NM_SS ");\n"); } else { indent(level+1); - printf("*" NM_PNST " = %d;\n", next_sp->extra.e_state->index); + gen_code("*" NM_PNST " = %d;\n", next_sp->extra.e_state->index); } - indent(level+1);printf("*" NM_PTRN " = %d;\n", trans_num); - indent(level+1); printf("return TRUE;\n"); - indent(level); printf("}\n"); + indent(level+1);gen_code("*" NM_PTRN " = %d;\n", trans_num); + indent(level+1); gen_code("return TRUE;\n"); + indent(level); gen_code("}\n"); trans_num++; } - indent(level); printf("return FALSE;\n"); + indent(level); gen_code("return FALSE;\n"); } static void gen_var_access(Var *vp) @@ -373,29 +373,29 @@ static void gen_var_access(Var *vp) if (vp->type->tag == T_EVFLAG) { - printf("%d/*%s*/", vp->chan.evflag->index, vp->name); + gen_code("%d/*%s*/", vp->chan.evflag->index, vp->name); } else if (vp->type->tag == T_NONE) { - printf("%s", vp->name); + gen_code("%s", vp->name); } else if (vp->scope->type == D_PROG) { - printf("%s%s", pre, vp->name); + gen_code("%s%s", pre, vp->name); } else if (vp->scope->type == D_SS) { - printf("%s%s_%s.%s", pre, NM_VARS, vp->scope->value, vp->name); + gen_code("%s%s_%s.%s", pre, NM_VARS, vp->scope->value, vp->name); } else if (vp->scope->type == D_STATE) { - printf("%s%s_%s.%s_%s.%s", pre, NM_VARS, + gen_code("%s%s_%s.%s_%s.%s", pre, NM_VARS, vp->scope->extra.e_state->var_list->parent_scope->value, NM_VARS, vp->scope->value, vp->name); } else /* compound or when stmt => generate a local C variable */ { - printf("%s", vp->name); + gen_code("%s", vp->name); } } @@ -420,7 +420,7 @@ static void gen_expr( /* Statements */ case S_CMPND: indent(level); - printf("{\n"); + gen_code("{\n"); gen_local_var_decls(ep, level+1); gen_defn_c_code(ep, level+1); foreach (cep, ep->cmpnd_stmts) @@ -428,26 +428,26 @@ static void gen_expr( gen_expr(context, cep, level+1); } indent(level); - printf("}\n"); + gen_code("}\n"); break; case S_STMT: gen_line_marker(ep); indent(level); gen_expr(context, ep->stmt_expr, 0); - printf(";\n"); + gen_code(";\n"); break; case S_IF: gen_line_marker(ep); indent(level); - printf("if ("); + gen_code("if ("); gen_expr(context, ep->if_cond, 0); - printf(")\n"); + gen_code(")\n"); cep = ep->if_then; gen_expr(context, cep, cep->type == S_CMPND ? level : level+1); if (ep->if_else) { indent(level); - printf("else\n"); + gen_code("else\n"); cep = ep->if_else; gen_expr(context, cep, cep->type == S_CMPND ? level : level+1); } @@ -455,28 +455,28 @@ static void gen_expr( case S_WHILE: gen_line_marker(ep); indent(level); - printf("while ("); + gen_code("while ("); gen_expr(context, ep->while_cond, 0); - printf(")\n"); + gen_code(")\n"); cep = ep->while_stmt; gen_expr(context, cep, cep->type == S_CMPND ? level : level+1); break; case S_FOR: gen_line_marker(ep); indent(level); - printf("for ("); + gen_code("for ("); gen_expr(context, ep->for_init, 0); - printf("; "); + gen_code("; "); gen_expr(context, ep->for_cond, 0); - printf("; "); + gen_code("; "); gen_expr(context, ep->for_iter, 0); - printf(")\n"); + gen_code(")\n"); cep = ep->for_stmt; gen_expr(context, cep, cep->type == S_CMPND ? level : level+1); break; case S_JUMP: indent(level); - printf("%s;\n", ep->value); + gen_code("%s;\n", ep->value); break; case S_CHANGE: if (context != C_TRANS) @@ -485,7 +485,7 @@ static void gen_expr( break; } indent(level); - printf("{*" NM_PNST " = %d; return;}\n", ep->extra.e_change->extra.e_state->index); + gen_code("{*" NM_PNST " = %d; return;}\n", ep->extra.e_change->extra.e_state->index); break; /* Expressions */ case E_VAR: @@ -493,78 +493,78 @@ static void gen_expr( break; case E_SUBSCR: gen_expr(context, ep->subscr_operand, 0); - printf("["); + gen_code("["); gen_expr(context, ep->subscr_index, 0); - printf("]"); + gen_code("]"); break; case E_CONST: if (gen_builtin_const(ep)) break; - printf("%s", ep->value); + gen_code("%s", ep->value); break; case E_STRING: - printf("\"%s\"", ep->value); + gen_code("\"%s\"", ep->value); break; case E_DELAY: case E_FUNC: if (gen_builtin_func(context, ep)) break; - printf("%s(", ep->value); + gen_code("%s(", ep->value); foreach (cep, ep->func_args) { gen_expr(context, cep, 0); if (cep->next) - printf(", "); + gen_code(", "); } - printf(")"); + gen_code(")"); break; case E_INIT: - printf("{"); + gen_code("{"); foreach (cep, ep->init_elems) { gen_expr(context, cep, 0); if (cep->next) - printf(", "); + gen_code(", "); } - printf("}"); + gen_code("}"); break; case E_TERNOP: gen_expr(context, ep->ternop_cond, 0); - printf(" ? "); + gen_code(" ? "); gen_expr(context, ep->ternop_then, 0); - printf(" : "); + gen_code(" : "); gen_expr(context, ep->ternop_else, 0); break; case E_BINOP: gen_expr(context, ep->binop_left, 0); - printf(" %s ", ep->value); + gen_code(" %s ", ep->value); gen_expr(context, ep->binop_right, 0); break; case E_PAREN: - printf("("); + gen_code("("); gen_expr(context, ep->paren_expr, 0); - printf(")"); + gen_code(")"); break; case E_CAST: - printf("("); + gen_code("("); /* gen_type_expr(ep->cast_type); */ assert(ep->cast_type->type == D_DECL); gen_var_decl(ep->cast_type->extra.e_decl); - printf(")"); + gen_code(")"); gen_expr(context, ep->cast_operand, 0); break; case E_PRE: - printf("%s", ep->value); + gen_code("%s", ep->value); gen_expr(context, ep->pre_operand, 0); break; case E_POST: gen_expr(context, ep->post_operand, 0); - printf("%s", ep->value); + gen_code("%s", ep->value); break; /* C-code can be either definition, statement, or expression */ case T_TEXT: indent(level); - printf("%s\n", ep->value); + gen_code("%s\n", ep->value); break; default: assert(impossible); @@ -582,7 +582,7 @@ static int gen_builtin_const(Expr *ep) if (!sym) return CT_NONE; - printf("%s", const_name); + gen_code("%s", const_name); return sym->type; } @@ -603,11 +603,11 @@ static int gen_builtin_func(int context, Expr *ep) sym->ef_action_only, sym->ef_args); #endif /* All builtin functions require ssId as 1st parameter */ - printf("seq_%s(" NM_SS "", func_name); + gen_code("seq_%s(" NM_SS "", func_name); switch (sym->type) { case FT_DELAY: - printf(", %d)", ep->extra.e_delay); + gen_code(", %d)", ep->extra.e_delay); break; case FT_EVENT: /* Event flag functions */ @@ -621,10 +621,10 @@ static int gen_builtin_func(int context, Expr *ep) /* just fill in user-supplied parameters */ foreach (ap, ep->func_args) { - printf(", "); + gen_code(", "); gen_expr(context, ap, 0); } - printf(")"); + gen_code(")"); break; default: assert(impossible); @@ -684,9 +684,9 @@ static void gen_ef_func( "built-in function %s requires an argument\n", func_name); return; } - printf(", "); + gen_code(", "); gen_ef_arg(func_name, ap, 1); - printf(")"); + gen_code(")"); } /* Generate code for pv functions requiring a database variable. @@ -740,32 +740,32 @@ static void gen_pv_func( #ifdef DEBUG report("gen_pv_func: fun=%s, var=%s\n", ep->value, vp->name); #endif - printf(", "); + gen_code(", "); if (vp->assign == M_NONE) { error_at_expr(ep, "parameter 1 to '%s' was not assigned to a pv\n", func_name); - printf("?/*%s*/", vp->name); + gen_code("?/*%s*/", vp->name); } else if (ap->type == E_SUBSCR && vp->assign != M_MULTI) { error_at_expr(ep, "parameter 1 to '%s' is subscripted but the variable " "it refers to has not been assigned to multiple pvs\n", func_name); - printf("%d/*%s*/", vp->index, vp->name); + gen_code("%d/*%s*/", vp->index, vp->name); } else { - printf("%d/*%s*/", vp->index, vp->name); + gen_code("%d/*%s*/", vp->index, vp->name); } if (ap->type == E_SUBSCR) { /* e.g. pvPut(xyz[i+2]); => seq_pvPut(ssId, 3 + (i+2)); */ - printf(" + (VAR_ID)("); + gen_code(" + (VAR_ID)("); /* generate the subscript expression */ gen_expr(context, subscr, 0); - printf(")"); + gen_code(")"); } /* If requested, add length parameter (if subscripted variable, @@ -774,11 +774,11 @@ static void gen_pv_func( { if (ap->type != E_SUBSCR) { - printf(", %d", type_array_length1(vp->type)); + gen_code(", %d", type_array_length1(vp->type)); } else { - printf(", 1"); + gen_code(", 1"); } } @@ -786,7 +786,7 @@ static void gen_pv_func( foreach (ap, ap->next) { num_extra_parms++; - printf(", "); + gen_code(", "); if (ef_args) { /* special case: constant NOEVFLAG */ @@ -810,12 +810,12 @@ static void gen_pv_func( extra zero parameters */ while (num_extra_parms < num_params) { - printf(", 0"); + gen_code(", 0"); num_extra_parms++; } /* Close the parameter list */ - printf(")"); + gen_code(")"); #ifdef DEBUG report("gen_pv_func: done (fun=%s, var=%s)\n", ep->value, vp->name); #endif @@ -828,11 +828,11 @@ void gen_ss_user_var_init(Expr *ssp, int level) Expr *sp; assert(ssp->type == D_SS); - printf("{\n"); + gen_code("{\n"); foreach(vp, ssp->extra.e_ss->var_list->first) { if (vp->init) gen_line_marker(vp->init); - indent(level+1); gen_var_init(vp, level+1); printf(",\n"); + indent(level+1); gen_var_init(vp, level+1); gen_code(",\n"); } foreach (sp, ssp->ss_states) { @@ -842,18 +842,18 @@ void gen_ss_user_var_init(Expr *ssp, int level) s_empty = !sp->extra.e_state->var_list->first; if (!s_empty) { - indent(level+1); printf("{\n"); + indent(level+1); gen_code("{\n"); foreach (vp, sp->extra.e_state->var_list->first) { if (vp->init) gen_line_marker(vp->init); indent(level+2); gen_var_init(vp, level+2); - printf("%s\n", vp->next ? "," : ""); + gen_code("%s\n", vp->next ? "," : ""); } indent(level+1); - printf("}%s\n", sp->next ? "," : ""); + gen_code("}%s\n", sp->next ? "," : ""); } } - indent(level); printf("}"); + indent(level); gen_code("}"); } /* Generate initializer for the UserVar structs. */ @@ -863,14 +863,14 @@ static void gen_user_var_init(Expr *prog, int level) Expr *ssp; assert(prog->type == D_PROG); - printf("{\n"); + gen_code("{\n"); /* global variables */ foreach(vp, prog->extra.e_prog->first) { if (vp->type->tag >= V_CHAR) { if (vp->init) gen_line_marker(vp->init); - indent(level+1); gen_var_init(vp, level+1); printf(",\n"); + indent(level+1); gen_var_init(vp, level+1); gen_code(",\n"); } } @@ -893,24 +893,24 @@ static void gen_user_var_init(Expr *prog, int level) { indent(level+1); gen_ss_user_var_init(ssp, level+1); - printf("%s\n", ssp->next ? "," : ""); + gen_code("%s\n", ssp->next ? "," : ""); } } - indent(level); printf("}"); + indent(level); gen_code("}"); } static void gen_prog_init_func(Expr *prog, int opt_reent) { assert(prog->type == D_PROG); - printf("\n/* Program init func */\n"); - printf("static void " NM_INIT "(SEQ_VARS *const " NM_VARS ")\n{\n"); + gen_code("\n/* Program init func */\n"); + gen_code("static void " NM_INIT "(SEQ_VARS *const " NM_VARS ")\n{\n"); if (opt_reent) { - indent(1); printf("static struct %s pVarInit = ", NM_VARS); - gen_user_var_init(prog, 1); printf(";\n"); - indent(1); printf("*pVar = pVarInit;\n"); + indent(1); gen_code("static struct %s pVarInit = ", NM_VARS); + gen_user_var_init(prog, 1); gen_code(";\n"); + indent(1); gen_code("*pVar = pVarInit;\n"); } - printf("}\n"); + gen_code("}\n"); } static void gen_prog_func( @@ -921,9 +921,9 @@ static void gen_prog_func( void (*gen_body)(Expr *xp)) { assert(prog->type == D_PROG); - printf("\n/* Program %s func */\n", doc); - printf("static void %s(SS_ID " NM_SS ", SEQ_VARS *const " NM_VARS ")\n{\n", + gen_code("\n/* Program %s func */\n", doc); + gen_code("static void %s(SS_ID " NM_SS ", SEQ_VARS *const " NM_VARS ")\n{\n", name); if (xp && gen_body) gen_body(xp); - printf("}\n"); + gen_code("}\n"); } diff --git a/src/snc/gen_tables.c b/src/snc/gen_tables.c index 1ef6ba5de1cf722bbed966f5063aef011fe04545..d1685cb417da4b4a071b5caa5977cd38b4bcec64 100644 --- a/src/snc/gen_tables.c +++ b/src/snc/gen_tables.c @@ -50,7 +50,7 @@ static int iter_event_mask_array(Expr *ep, Expr *scope, void *parg); /* Generate all kinds of tables for a SNL program. */ void gen_tables(Program *p) { - printf("\n/************************ Tables ************************/\n"); + gen_code("\n/************************ Tables ************************/\n"); gen_channel_table(p->chan_list, p->num_event_flags, p->options.reent); gen_state_table(p->prog->prog_statesets, p->num_event_flags, p->chan_list->num_elems); gen_ss_table(p->prog->prog_statesets); @@ -64,20 +64,20 @@ static void gen_channel_table(ChanList *chan_list, uint num_event_flags, int opt if (chan_list->first) { - printf("\n/* Channel table */\n"); - printf("static seqChan " NM_CHANS "[] = {\n"); - printf("\t/* chName, offset, varName, varType, count, eventNum, efId, monitored, queueSize, queueIndex */\n"); + gen_code("\n/* Channel table */\n"); + gen_code("static seqChan " NM_CHANS "[] = {\n"); + gen_code("\t/* chName, offset, varName, varType, count, eventNum, efId, monitored, queueSize, queueIndex */\n"); foreach (cp, chan_list->first) { gen_channel(cp, num_event_flags, opt_reent); - printf(",\n"); + gen_code(",\n"); } - printf("};\n"); + gen_code("};\n"); } else { - printf("\n/* No channel definitions */\n"); - printf("#define " NM_CHANS " 0\n"); + gen_code("\n/* No channel definitions */\n"); + gen_code("#define " NM_CHANS " 0\n"); } } @@ -85,15 +85,15 @@ static void gen_var_name(Var *vp) { if (vp->scope->type == D_PROG) { - printf("%s", vp->name); + gen_code("%s", vp->name); } else if (vp->scope->type == D_SS) { - printf("%s_%s.%s", NM_VARS, vp->scope->value, vp->name); + gen_code("%s_%s.%s", NM_VARS, vp->scope->value, vp->name); } else if (vp->scope->type == D_STATE) { - printf("%s_%s.%s_%s.%s", NM_VARS, + gen_code("%s_%s.%s_%s.%s", NM_VARS, vp->scope->extra.e_state->var_list->parent_scope->value, NM_VARS, vp->scope->value, vp->name); } @@ -112,15 +112,15 @@ static void gen_channel(Chan *cp, uint num_event_flags, int opt_reent) enum prim_type_tag type = basetype->val.prim; if (type == P_LONG || type == P_ULONG) { - printf( + gen_code( "#if LONG_MAX > 0x7fffffffL\n" ); gen_line_marker(vp->decl); - printf( + gen_code( "#error variable '" ); gen_var_decl(vp); - printf("'" + gen_code("'" " cannot be assigned to a PV (on the chosen target system)\\\n" " because Channel Access does not support integral types longer than 4 bytes.\\\n" " You can use '%s' instead, or the fixed size type '%s'.\n" @@ -140,44 +140,44 @@ static void gen_channel(Chan *cp, uint num_event_flags, int opt_reent) ef_num = 0; if (!cp->name) - printf("\t{0, "); + gen_code("\t{0, "); else - printf("\t{\"%s\", ", cp->name); + gen_code("\t{\"%s\", ", cp->name); if (opt_reent) { - printf("offsetof(struct %s, ", NM_VARS); + gen_code("offsetof(struct %s, ", NM_VARS); gen_var_name(vp); - printf("%s), ", elem_str); + gen_code("%s), ", elem_str); } else { - printf("(size_t)&"); + gen_code("(size_t)&"); gen_var_name(vp); - printf("%s, ", elem_str); + gen_code("%s, ", elem_str); } /* variable name with optional elem num */ - printf("\"%s%s\", ", vp->name, elem_str); + gen_code("\"%s%s\", ", vp->name, elem_str); /* variable type */ assert(base_type(vp->type)->tag == T_PRIM); - printf("\"%s\", ", prim_type_name[base_type(vp->type)->val.prim]); + gen_code("\"%s\", ", prim_type_name[base_type(vp->type)->val.prim]); /* count, for requests */ - printf("%d, ", cp->count); + gen_code("%d, ", cp->count); /* event number */ - printf("%d, ", num_event_flags + vp->index + cp->index + 1); + gen_code("%d, ", num_event_flags + vp->index + cp->index + 1); /* event flag number (or 0) */ - printf("%d, ", ef_num); + gen_code("%d, ", ef_num); /* monitor flag */ - printf("%d, ", cp->monitor); + gen_code("%d, ", cp->monitor); /* syncQ queue */ if (!cp->syncq) - printf("0, 0"); + gen_code("0, 0"); else if (!cp->syncq->size) - printf("DEFAULT_QUEUE_SIZE, %d", cp->syncq->index); + gen_code("DEFAULT_QUEUE_SIZE, %d", cp->syncq->index); else - printf("%d, %d", cp->syncq->size, cp->syncq->index); - printf("}"); + gen_code("%d, %d", cp->syncq->size, cp->syncq->index); + gen_code("}"); } /* Generate state event mask and table */ @@ -202,25 +202,25 @@ static void gen_state_table(Expr *ss_list, uint num_event_flags, uint num_channe foreach (ssp, ss_list) { /* Generate event mask array */ - printf("\n/* Event masks for state set \"%s\" */\n", ssp->value); + gen_code("\n/* Event masks for state set \"%s\" */\n", ssp->value); foreach (sp, ssp->ss_states) { gen_state_event_mask(sp, num_event_flags, event_mask, num_event_words); - printf("static const seqMask " NM_MASK "_%s_%d_%s[] = {\n", + gen_code("static const seqMask " NM_MASK "_%s_%d_%s[] = {\n", ssp->value, ss_num, sp->value); for (n = 0; n < num_event_words; n++) - printf("\t0x%08x,\n", event_mask[n]); - printf("};\n"); + gen_code("\t0x%08x,\n", event_mask[n]); + gen_code("};\n"); } /* Generate table of state structures */ - printf("\n/* State table for state set \"%s\" */\n", ssp->value); - printf("static seqState " NM_STATES "_%s[] = {\n", ssp->value); + gen_code("\n/* State table for state set \"%s\" */\n", ssp->value); + gen_code("static seqState " NM_STATES "_%s[] = {\n", ssp->value); foreach (sp, ssp->ss_states) { fill_state_struct(sp, ssp->value, ss_num); } - printf("};\n"); + gen_code("};\n"); ss_num++; } } @@ -228,83 +228,83 @@ static void gen_state_table(Expr *ss_list, uint num_event_flags, uint num_channe /* Generate a state struct */ static void fill_state_struct(Expr *sp, char *ss_name, uint ss_num) { - printf("\t{\n"); - printf("\t/* state name */ \"%s\",\n", sp->value); - printf("\t/* action function */ " NM_ACTION "_%s_%d_%s,\n", ss_name, ss_num, sp->value); - printf("\t/* event function */ " NM_EVENT "_%s_%d_%s,\n", ss_name, ss_num, sp->value); - printf("\t/* delay function */ " NM_DELAY "_%s_%d_%s,\n", ss_name, ss_num, sp->value); - printf("\t/* entry function */ "); + gen_code("\t{\n"); + gen_code("\t/* state name */ \"%s\",\n", sp->value); + gen_code("\t/* action function */ " NM_ACTION "_%s_%d_%s,\n", ss_name, ss_num, sp->value); + gen_code("\t/* event function */ " NM_EVENT "_%s_%d_%s,\n", ss_name, ss_num, sp->value); + gen_code("\t/* delay function */ " NM_DELAY "_%s_%d_%s,\n", ss_name, ss_num, sp->value); + gen_code("\t/* entry function */ "); if (sp->state_entry) - printf(NM_ENTRY "_%s_%d_%s,\n", ss_name, ss_num, sp->value); + gen_code(NM_ENTRY "_%s_%d_%s,\n", ss_name, ss_num, sp->value); else - printf("0,\n"); - printf("\t/* exit function */ "); + gen_code("0,\n"); + gen_code("\t/* exit function */ "); if (sp->state_exit) - printf(NM_EXIT "_%s_%d_%s,\n", ss_name, ss_num, sp->value); + gen_code(NM_EXIT "_%s_%d_%s,\n", ss_name, ss_num, sp->value); else - printf("0,\n"); - printf("\t/* event mask array */ " NM_MASK "_%s_%d_%s,\n", ss_name, ss_num, sp->value); - printf("\t/* state options */ "); + gen_code("0,\n"); + gen_code("\t/* event mask array */ " NM_MASK "_%s_%d_%s,\n", ss_name, ss_num, sp->value); + gen_code("\t/* state options */ "); encode_state_options(sp->extra.e_state->options); - printf("\n\t},\n"); + gen_code("\n\t},\n"); } /* Generate the state option bitmask */ static void encode_state_options(StateOptions options) { - printf("(0"); + gen_code("(0"); if (!options.do_reset_timers) - printf(" | OPT_NORESETTIMERS"); + gen_code(" | OPT_NORESETTIMERS"); if (!options.no_entry_from_self) - printf(" | OPT_DOENTRYFROMSELF"); + gen_code(" | OPT_DOENTRYFROMSELF"); if (!options.no_exit_to_self) - printf(" | OPT_DOEXITTOSELF"); - printf(")"); + gen_code(" | OPT_DOEXITTOSELF"); + gen_code(")"); } /* Generate a single program structure ("seqProgram") */ static void gen_prog_table(Program *p) { - printf("\n/* Program table (global) */\n"); - printf("seqProgram %s = {\n", p->name); - printf("\t/* magic number */ %d,\n", MAGIC); - printf("\t/* program name */ \"%s\",\n", p->name); - printf("\t/* channels */ " NM_CHANS ",\n"); - printf("\t/* num. channels */ %d,\n", p->chan_list->num_elems); - printf("\t/* state sets */ " NM_STATESETS ",\n"); - printf("\t/* num. state sets */ %d,\n", p->num_ss); + gen_code("\n/* Program table (global) */\n"); + gen_code("seqProgram %s = {\n", p->name); + gen_code("\t/* magic number */ %d,\n", MAGIC); + gen_code("\t/* program name */ \"%s\",\n", p->name); + gen_code("\t/* channels */ " NM_CHANS ",\n"); + gen_code("\t/* num. channels */ %d,\n", p->chan_list->num_elems); + gen_code("\t/* state sets */ " NM_STATESETS ",\n"); + gen_code("\t/* num. state sets */ %d,\n", p->num_ss); if (p->options.reent) - printf("\t/* user var size */ sizeof(struct %s),\n", NM_VARS); + gen_code("\t/* user var size */ sizeof(struct %s),\n", NM_VARS); else - printf("\t/* user var size */ 0,\n"); - printf("\t/* param */ \"%s\",\n", p->param); - printf("\t/* num. event flags */ %d,\n", p->num_event_flags); - printf("\t/* encoded options */ "); encode_options(p->options); - printf("\t/* init func */ " NM_INIT ",\n"); - printf("\t/* entry func */ %s,\n", p->prog->prog_entry ? NM_ENTRY : "0"); - printf("\t/* exit func */ %s,\n", p->prog->prog_exit ? NM_EXIT : "0"); - printf("\t/* num. queues */ %d\n", p->syncq_list->num_elems); - printf("};\n"); + gen_code("\t/* user var size */ 0,\n"); + gen_code("\t/* param */ \"%s\",\n", p->param); + gen_code("\t/* num. event flags */ %d,\n", p->num_event_flags); + gen_code("\t/* encoded options */ "); encode_options(p->options); + gen_code("\t/* init func */ " NM_INIT ",\n"); + gen_code("\t/* entry func */ %s,\n", p->prog->prog_entry ? NM_ENTRY : "0"); + gen_code("\t/* exit func */ %s,\n", p->prog->prog_exit ? NM_EXIT : "0"); + gen_code("\t/* num. queues */ %d\n", p->syncq_list->num_elems); + gen_code("};\n"); } static void encode_options(Options options) { - printf("(0"); + gen_code("(0"); if (options.async) - printf(" | OPT_ASYNC"); + gen_code(" | OPT_ASYNC"); if (options.conn) - printf(" | OPT_CONN"); + gen_code(" | OPT_CONN"); if (options.debug) - printf(" | OPT_DEBUG"); + gen_code(" | OPT_DEBUG"); if (options.newef) - printf(" | OPT_NEWEF"); + gen_code(" | OPT_NEWEF"); if (options.reent) - printf(" | OPT_REENT"); + gen_code(" | OPT_REENT"); if (options.safe) - printf(" | OPT_SAFE"); + gen_code(" | OPT_SAFE"); if (options.main) - printf(" | OPT_MAIN"); - printf("),\n"); + gen_code(" | OPT_MAIN"); + gen_code("),\n"); } /* Generate state set table, one entry for each state set */ @@ -313,22 +313,22 @@ static void gen_ss_table(Expr *ss_list) Expr *ssp; int num_ss; - printf("\n/* State set table */\n"); - printf("static seqSS " NM_STATESETS "[] = {\n"); + gen_code("\n/* State set table */\n"); + gen_code("static seqSS " NM_STATESETS "[] = {\n"); num_ss = 0; foreach (ssp, ss_list) { if (num_ss > 0) - printf("\n"); + gen_code("\n"); num_ss++; - printf("\t{\n"); - printf("\t/* state set name */ \"%s\",\n", ssp->value); - printf("\t/* states */ " NM_STATES "_%s,\n", ssp->value); - printf("\t/* number of states */ %d,\n", ssp->extra.e_ss->num_states); - printf("\t/* number of delays */ %d\n", ssp->extra.e_ss->num_delays); - printf("\t},\n"); + gen_code("\t{\n"); + gen_code("\t/* state set name */ \"%s\",\n", ssp->value); + gen_code("\t/* states */ " NM_STATES "_%s,\n", ssp->value); + gen_code("\t/* number of states */ %d,\n", ssp->extra.e_ss->num_states); + gen_code("\t/* number of delays */ %d\n", ssp->extra.e_ss->num_delays); + gen_code("\t},\n"); } - printf("};\n"); + gen_code("};\n"); } /* Generate event mask for a single state. The event mask has a bit set for each diff --git a/src/snc/main.c b/src/snc/main.c index 264e3d242306dae360b83bacac0f78aff6683645..cf7bc13d4550d14a24fd202911cb041273fbec28 100644 --- a/src/snc/main.c +++ b/src/snc/main.c @@ -25,64 +25,65 @@ in the file LICENSE that is included with this distribution. static Options options = DEFAULT_OPTIONS; -static char *in_file; /* input file name */ -static char *out_file; /* output file name */ +static char *input_name; /* input file name */ +static char *c_output_name; /* c output file name */ +static char *h_output_name; /* h output file name */ + +static FILE *c_out, *h_out; /* output file handles */ +static FILE *out = NULL; /* current output file handle */ static int err_cnt; static void parse_args(int argc, char *argv[]); static void parse_option(char *s); static void print_usage(void); +static char *replace_extension(const char *in, const char *ext); /* The streams stdin and stdout are redirected to files named in the command parameters. */ int main(int argc, char *argv[]) { - FILE *infp, *outfp; + FILE *in; Program *prg; Expr *exp; /* Get command arguments */ parse_args(argc, argv); - /* Redirect input stream from specified file */ - infp = freopen(in_file, "r", stdin); - if (infp == NULL) + in = fopen(input_name, "r"); + if (in == NULL) { - perror(in_file); + perror(input_name); return EXIT_FAILURE; } - - /* Redirect output stream to specified file */ - outfp = freopen(out_file, "w", stdout); - if (outfp == NULL) + c_out = fopen(c_output_name, "w"); + if (c_out == NULL) + { + perror(c_output_name); + return EXIT_FAILURE; + } + h_out = fopen(h_output_name, "w"); + if (h_out == NULL) { - perror(out_file); + perror(h_output_name); return EXIT_FAILURE; } - /* stdin: the input file should be unbuffered, + /* the input file should be unbuffered, since the lexer maintains its own buffer */ - setvbuf(stdin, NULL, _IONBF, 0); - /* stdout: the generated C program should be - block buffered with standard buffer size */ - setvbuf(stdout, NULL, _IOFBF, BUFSIZ); - /* stderr: messages should be output immediately */ - setvbuf(stderr, NULL, _IONBF, 0); - - printf("/* Generated with snc from %s */\n", in_file); + setvbuf(in, NULL, _IONBF, 0); - exp = parse_program(in_file); + exp = parse_program(in, input_name); prg = analyse_program(exp, options); if (err_cnt == 0) - generate_code(prg); + generate_code(prg, h_output_name); return err_cnt ? EXIT_FAILURE : EXIT_SUCCESS; } -/* Initialize options, in_file, and out_file from arguments. */ +/* Initialize options, input_name, c_output_name, and h_output_name from arguments. */ static void parse_args(int argc, char *argv[]) { int i; @@ -108,13 +109,13 @@ static void parse_args(int argc, char *argv[]) else { i++; - out_file = argv[i]; + c_output_name = argv[i]; continue; } } else if (s[0] != '+' && s[0] != '-') { - in_file = s; + input_name = s; continue; } else @@ -126,30 +127,30 @@ static void parse_args(int argc, char *argv[]) options.reent = TRUE; } - if (!in_file) + if (!input_name) { report("no input file argument given\n"); print_usage(); exit(EXIT_FAILURE); } - if (!out_file) /* no -o option given */ + if (!c_output_name) /* no -o option given */ { - unsigned l = strlen(in_file); - char *ext = strrchr(in_file, '.'); - - if (ext && strcmp(ext,".st") == 0) - { - out_file = (char*)malloc(l); - strcpy(out_file, in_file); - strcpy(out_file+(ext-in_file), ".c\n"); - } - else - { - out_file = (char*)malloc(l+3); - sprintf(out_file, "%s.c", in_file); - } + c_output_name = replace_extension(input_name, ".c"); } + h_output_name = replace_extension(c_output_name, ".h"); +} + +static char *replace_extension(const char *in, const char *ext) +{ + char *in_ext = strrchr(in, '.'); + size_t ext_len = strlen(ext); + size_t in_len = in_ext ? (in_ext - in) : strlen(in); + char *out = (char*)malloc(in_len+ext_len+1); + + strncpy(out, in, in_len); + strcpy(out+in_len, ext); + return out; } static void parse_option(char *s) @@ -212,10 +213,31 @@ static void print_usage(void) report("example:\n snc +a -c vacuum.st\n"); } +/* Code generation support */ + +void set_gen_c(void) +{ + out = c_out; +} + +void set_gen_h(void) +{ + out = h_out; +} + void gen_line_marker_prim(int line_num, const char *src_file) { if (options.line) - printf("# line %d \"%s\"\n", line_num, src_file); + fprintf(out, "# line %d \"%s\"\n", line_num, src_file); +} + +void gen_code(const char *format, ...) +{ + va_list args; + + va_start(args, format); + vfprintf(out, format, args); + va_end(args); } /* Errors and warnings */ diff --git a/src/snc/main.h b/src/snc/main.h index 274515b72c196b706152e04155b47ef288bed4e4..e6d1fe3a7e1c6893a3cdf94f4393b0649c7e17ac 100644 --- a/src/snc/main.h +++ b/src/snc/main.h @@ -14,6 +14,12 @@ in the file LICENSE that is included with this distribution. #define __attribute__(x) #endif +void gen_code(const char *format, ...) +__attribute__((format(printf,1,2))); + +void set_gen_c(void); +void set_gen_h(void); + /* append '# <line_num> "<src_file>"\n' to output (if not disabled by cmd-line option) */ void gen_line_marker_prim(int line_num, const char *src_file); diff --git a/src/snc/parser.h b/src/snc/parser.h index 53c619d45bca6c2b6e9e1120ca8ad63ce17ff0ee..91364088f1330a2e0efd0442c4a43beef8c27ed0 100644 --- a/src/snc/parser.h +++ b/src/snc/parser.h @@ -10,9 +10,11 @@ in the file LICENSE that is included with this distribution. #ifndef INCLparserh #define INCLparserh +#include <stdio.h> + #include "types.h" -Expr *parse_program(const char *src_file); +Expr *parse_program(FILE *in, const char *src_file); void snlParser( void *yyp, /* the parser */ diff --git a/src/snc/snl.re b/src/snc/snl.re index db3a2c2540e3f17356b2c1c50467a96cee334a10..d29843410f980fabb358f590ba49fcb6436ecc58 100644 --- a/src/snc/snl.re +++ b/src/snc/snl.re @@ -56,6 +56,7 @@ typedef struct Scanner { uchar *eof; /* pointer to (one after) last char in file (or 0) */ const char *file; /* source file name */ int line; /* line number */ + FILE *in; } Scanner; static void scan_report(Scanner *s, const char *format, ...) @@ -134,12 +135,12 @@ static uchar *fill(Scanner *s, uchar *cursor) { } /* fill the buffer, starting at s->lim, by reading a chunk of BSIZE bytes (or less if eof is encountered) */ - if ((read_cnt = fread(s->lim, sizeof(uchar), BSIZE, stdin)) != BSIZE) { - if (ferror(stdin)) { + if ((read_cnt = fread(s->lim, sizeof(uchar), BSIZE, s->in)) != BSIZE) { + if (ferror(s->in)) { perror("error reading input"); exit(EXIT_FAILURE); } - if (feof(stdin)) { + if (feof(s->in)) { s->eof = &s->lim[read_cnt]; /* insert sentinel and increase s->eof */ *(s->eof)++ = '\n'; @@ -456,7 +457,7 @@ c_code_line: DONE; /* dead code, only here to make compiler warning go away */ } -Expr *parse_program(const char *src_file) +Expr *parse_program(FILE *in, const char *src_file) { Scanner s; int tt; /* token type */ @@ -467,6 +468,7 @@ Expr *parse_program(const char *src_file) memset(&s, 0, sizeof(s)); s.file = src_file; s.line = 1; + s.in = in; parser = snlParserAlloc(malloc); do diff --git a/src/snc/var_types.c b/src/snc/var_types.c index f0d7a6edff40a850457296c182647af8576d690d..f50028440352cc524bac00f844979445187d5634 100644 --- a/src/snc/var_types.c +++ b/src/snc/var_types.c @@ -231,19 +231,19 @@ static void gen_array_pointer(Type *t, enum type_tag last_tag, char *name) switch (t->tag) { case T_POINTER: if (paren) - printf("("); - printf("*"); + gen_code("("); + gen_code("*"); gen_array_pointer(t->parent, t->tag, name); if (paren) - printf(")"); + gen_code(")"); break; case T_ARRAY: gen_array_pointer(t->parent, t->tag, name); - printf("[%d]", t->val.array.num_elems); + gen_code("[%d]", t->val.array.num_elems); break; default: if (name) - printf("%s", name); + gen_code("%s", name); break; } } @@ -254,13 +254,13 @@ void gen_type(Type *t, char *name) switch (bt->tag) { case T_EVFLAG: - printf("evflag "); + gen_code("evflag "); break; case T_PRIM: - printf("%s ", prim_type_name[bt->val.prim]); + gen_code("%s ", prim_type_name[bt->val.prim]); break; case T_FOREIGN: - printf("%s%s ", foreign_type_prefix[bt->val.foreign.tag], bt->val.foreign.name); + gen_code("%s%s ", foreign_type_prefix[bt->val.foreign.tag], bt->val.foreign.name); break; default: assert(impossible);