/*hdr.c - output an assembler header file given a module defn*/ /*OSLib---efficient, type-safe, transparent, extensible,\n" register-safe A P I coverage of RISC O S*/ /*Copyright © 1994 Jonathan Coxhead*/ /* OSLib is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version. OSLib is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this programme; if not, write to the Free Software Foundation, Inc, 675 Mass Ave, Cambridge, MA 02139, U S A. */ #include #include #include #include #include "kernel.h" /* TV 980115 */ #include "macros.h" #include "os.h" #include "lookup.h" #include "def.h" #include "hdr.h" #define TAB 8 #define LABELLED_INST_COL 4 #define LABELLED_ARG_COL 5 #define UNLABELLED_INST_COL 1 #define UNLABELLED_ARG_COL 2 static char *Op [] = {":OR:", ":AND:", "+", ":EOR:"}; static int Emit ( FILE *file, char *label, char *inst ) { return label != NULL? fprintf (file, "%-*s %s\n", LABELLED_INST_COL*TAB - 1, label, inst): fprintf (file, "%-*s %s\n", UNLABELLED_INST_COL*TAB - 1, "", inst); } static int EmitS ( FILE *file, char *label, char *inst, char *s ) { return label != NULL? fprintf (file, "%-*s %-*s %s\n", LABELLED_INST_COL*TAB - 1, label, (LABELLED_ARG_COL - LABELLED_INST_COL)*TAB - 1, inst, s): fprintf (file, "%-*s %-*s %s\n", UNLABELLED_INST_COL*TAB - 1, "", (UNLABELLED_ARG_COL - UNLABELLED_INST_COL)*TAB - 1, inst, s); } static int EmitSS ( FILE *file, char *label, char *inst, char *s1, char *s2 ) { return label != NULL? fprintf (file, "%-*s %-*s %s%s\n", LABELLED_INST_COL*TAB - 1, label, (LABELLED_ARG_COL - LABELLED_INST_COL)*TAB - 1, inst, s1, s2): fprintf (file, "%-*s %-*s %s%s\n", UNLABELLED_INST_COL*TAB - 1, "", (UNLABELLED_ARG_COL - UNLABELLED_INST_COL)*TAB - 1, inst, s1, s2); } static int EmitSSS ( FILE *file, char *label, char *inst, char *s1, char *s2, char *s3 ) { return label != NULL? fprintf (file, "%-*s %-*s %s%s%s\n", LABELLED_INST_COL*TAB - 1, label, (LABELLED_ARG_COL - LABELLED_INST_COL)*TAB - 1, inst, s1, s2, s3): fprintf (file, "%-*s %-*s %s%s%s\n", UNLABELLED_INST_COL*TAB - 1, "", (UNLABELLED_ARG_COL - UNLABELLED_INST_COL)*TAB - 1, inst, s1, s2, s3); } static int EmitD ( FILE *file, char *label, char *inst, int d ) { return label != NULL? fprintf (file, "%-*s %-*s %d\n", LABELLED_INST_COL*TAB - 1, label, (LABELLED_ARG_COL - LABELLED_INST_COL)*TAB - 1, inst, d): fprintf (file, "%-*s %-*s %d\n", UNLABELLED_INST_COL*TAB - 1, "", (UNLABELLED_ARG_COL - UNLABELLED_INST_COL)*TAB - 1, inst, d); } static int EmitX ( FILE *file, char *label, char *inst, int x ) { return label != NULL? fprintf (file, "%-*s %-*s &%X\n", LABELLED_INST_COL*TAB - 1, label, (LABELLED_ARG_COL - LABELLED_INST_COL)*TAB - 1, inst, x): fprintf (file, "%-*s %-*s &%X\n", UNLABELLED_INST_COL*TAB - 1, "", (UNLABELLED_ARG_COL - UNLABELLED_INST_COL)*TAB - 1, inst, x); } /* Prints a declaration of |v| as an object of type |t|.*/ static int Emit_Decl ( FILE *file, def_t t, char *v, bool top_level, int count ) { int rc = 0; char cs [1 + DEC_WIDTH + 1]; if (count == 0) CLEAR (cs); else sprintf (cs, "%d*", count); switch (t->tag) { case def_TYPE_INT: if ((rc = EmitSS (file, v, top_level? "*": "#", cs, "Int")) < 0) goto finish; break; case def_TYPE_SHORT: if ((rc = EmitSS (file, v, top_level? "*": "#", cs, "Short")) < 0) goto finish; break; case def_TYPE_BYTE: if ((rc = EmitSS (file, v, top_level? "*": "#", cs, "Byte")) < 0) goto finish; break; case def_TYPE_CHAR: if ((rc = EmitSS (file, v, top_level? "*": "#", cs, "Char")) < 0) goto finish; break; case def_TYPE_BITS: if ((rc = EmitSS (file, v, top_level? "*": "#", cs, "Bits")) < 0) goto finish; break; case def_TYPE_BYTES: if ((rc = EmitSS (file, v, top_level? "*": "#", cs, "Bytes")) < 0) goto finish; break; case def_TYPE_BOOL: if ((rc = EmitSS (file, v, top_level? "*": "#", cs, "Bool")) < 0) goto finish; break; case def_TYPE_REF: if ((rc = EmitSS (file, v, top_level? "*": "#", cs, "Ptr")) < 0) goto finish; break; case def_TYPE_STRING: case def_TYPE_ASM: case def_TYPE_DATA: case def_TYPE_VOID: if ((rc = EmitS (file, v, top_level? "*": "#", "Skip")) < 0) goto finish; break; case def_TYPE_STRUCT: { int i; if (top_level) if ((rc = EmitD (file, "", "^", 0)) < 0) goto finish; for (i = 0; i < t->data AS list.count; i++) { char v1 [def_ID_LIMIT + 1]; if ((rc = sprintf (v1, "%s_%s", v, t->data AS list.members [i]->name)) < 0) goto finish; if ((rc = Emit_Decl (file, t->data AS list.members [i], v1, FALSE, 0)) < 0) goto finish; } if (top_level) if ((rc = EmitS (file, v, "*", "@")) < 0) goto finish; } break; case def_TYPE_UNION: { int i; if (top_level) if ((rc = EmitD (file, "", "^", 0)) < 0) goto finish; /*Use the union name itself to hold the offset of the start of the union.*/ if (!top_level) if ((rc = EmitS (file, v, "*", "@")) < 0) goto finish; for (i = 0; i < t->data AS list.count; i++) { char v1 [def_ID_LIMIT + 1]; if (i > 0) { /*Set {VAR} back to the origin of the union.*/ if (!top_level) { if ((rc = EmitS (file, "", "^", v)) < 0) goto finish; } else { if ((rc = EmitD (file, "", "^", 0)) < 0) goto finish; } } if ((rc = sprintf (v1, "%s_%s", v, t->data AS list.members [i]->name)) < 0) goto finish; if ((rc = Emit_Decl (file, t->data AS list.members [i], v1, FALSE, 0)) < 0) goto finish; } if (top_level) if ((rc = EmitS (file, v, "*", "@")) < 0) goto finish; } break; case def_TYPE_ROW: if ((rc = Emit_Decl (file, t->data AS row.base, v, FALSE, (count == 0? 1: count)*t->data AS row.count)) < 0) goto finish; break; case def_TYPE_ID: if ((rc = EmitS (file, v, top_level? "*": "#", t->data AS id)) < 0) goto finish; break; } if (top_level) if ((rc = fprintf (file, "\n")) < 0) goto finish; finish: return rc; } /* Prints a description of an object of type |t|.*/ static int Emit_Name ( FILE *file, def_t t ) { int rc = 0; switch (t->tag) { case def_TYPE_INT: if ((rc = fprintf (file, "Int")) < 0) goto finish; break; case def_TYPE_SHORT: if ((rc = fprintf (file, "Short")) < 0) goto finish; break; case def_TYPE_BYTE: if ((rc = fprintf (file, "Byte")) < 0) goto finish; break; case def_TYPE_CHAR: if ((rc = fprintf (file, "Char")) < 0) goto finish; break; case def_TYPE_BITS: if ((rc = fprintf (file, "Bits")) < 0) goto finish; break; case def_TYPE_BYTES: if ((rc = fprintf (file, "Bytes")) < 0) goto finish; break; case def_TYPE_BOOL: if ((rc = fprintf (file, "Bool")) < 0) goto finish; break; case def_TYPE_REF: if ((rc = fprintf (file, "pointer to ")) < 0) goto finish; if ((rc = Emit_Name (file, t->data AS ref)) < 0) goto finish; break; case def_TYPE_STRING: if ((rc = fprintf (file, "String")) < 0) goto finish; break; case def_TYPE_ASM: if ((rc = fprintf (file, "code")) < 0) goto finish; break; case def_TYPE_DATA: if ((rc = fprintf (file, "data")) < 0) goto finish; break; case def_TYPE_VOID: if ((rc = fprintf (file, "unspecified")) < 0) goto finish; break; case def_TYPE_STRUCT: case def_TYPE_UNION: { int i; if ((rc = fprintf (file, "%s of (", t->tag == def_TYPE_STRUCT? "sequence": "one")) < 0) goto finish; for (i = 0; i < t->data AS list.count; i++) { if (i > 0) if ((rc = fprintf (file, ", ")) < 0) goto finish; if ((rc = Emit_Name (file, t->data AS list.members [i])) < 0) goto finish; } if ((rc = fprintf (file, ")")) < 0) goto finish; } break; case def_TYPE_ROW: if ((rc = fprintf (file, "array of %d ", t->data AS row.count)) < 0) goto finish; if ((rc = Emit_Name (file, t->data AS row.base)) < 0) goto finish; break; case def_TYPE_ID: if ((rc = fprintf (file, "%s", t->data AS id)) < 0) goto finish; break; } finish: return rc; } static int Emit_Get (FILE *file, char *name) { int rc; char s [FILENAME_MAX + 1], get [FILENAME_MAX + 1], hdr [FILENAME_MAX + 1]; if ((rc = sprintf (get, "%s%s", "Get_", name)) < 0) goto finish; if ((rc = sprintf (hdr, "%s%s", name, "_Hdr")) < 0) goto finish; if ((rc = EmitSS (file, NULL, "[", ":LNOT: :DEF: ", get)) < 0) goto finish; if ((rc = EmitS (file, NULL, "GBLS", get)) < 0) goto finish; if ((rc = Emit (file, NULL, "]")) < 0) goto finish; #if 0 // Amended to reflect change of include path name *** TV 20000305 *** if ((rc = sprintf (s, "\"GET OS:Hdr.%s\"", name)) < 0) #else if ((rc = sprintf (s, "\"GET OSLibInclude:Hdr.%s\"", name)) < 0) #endif goto finish; if ((rc = EmitSS (file, NULL, "[", ":LNOT: :DEF: ", hdr)) < 0) goto finish; if ((rc = EmitS (file, get, "SETS", s)) < 0) goto finish; if ((rc = Emit (file, NULL, "|")) < 0) goto finish; if ((rc = EmitS (file, get, "SETS", "\"\"")) < 0) goto finish; if ((rc = Emit (file, NULL, "]")) < 0) goto finish; if ((rc = sprintf (s, "$Get_%s", name)) < 0) return rc; if ((rc = Emit (file, NULL, s)) < 0) goto finish; if ((rc = fprintf (file, "\n")) < 0) goto finish; finish: return rc; } os_error *hdr_output ( FILE *file, char *title, char *author, lookup_t needses, lookup_t consts, lookup_t types, lookup_t swis ) { os_error *error = NULL; char *needs, *cnst, *type, *swi; def_c c; def_t t; def_s s; void *context; int rc = 0; time_t now; bool start; /*Emit the TITLE declaration.*/ if ((rc = fprintf (file, ";Assembler header file for %s\n" ";written by DefMod (%s) on %s" ";%s\n" "\n", title, __DATE__, (time (&now), ctime (&now)), author)) < 0) goto finish; /*Make sure we have Hdr.Types.*/ if ((rc = Emit_Get (file, "Types")) < 0) goto finish; /*Emit the NEEDS declarations.*/ context = 0; while (TRUE) { if ((error = lookup_enumerate (needses, &needs, NULL, &context)) != NULL) goto finish; if (context == 0) break; if ((rc = Emit_Get (file, needs)) < 0) goto finish; } if ((rc = EmitSSS (file, NULL, "[", ":LNOT: :DEF: ", title, "_Hdr")) < 0) goto finish; if ((rc = EmitSS (file, NULL, "GBLS", title, "_Hdr")) < 0) goto finish; if ((rc = fprintf (file, "\n")) < 0) goto finish; /*Emit the CONST declarations.*/ start = TRUE; context = 0; while (TRUE) { if ((error = lookup_enumerate (consts, &cnst, (void **) &c, &context)) != NULL) goto finish; if (context == 0) break; if (start) { if ((rc = fprintf (file, ";Symbols for constants\n")) < 0) goto finish; start = FALSE; } switch (c->type->tag) { case def_TYPE_INT: case def_TYPE_SHORT: case def_TYPE_BYTE: if ((rc = EmitD (file, cnst, "*", c->value)) < 0) goto finish; break; case def_TYPE_CHAR: { char v1 [def_ID_LIMIT + 1]; if (isprint (c->value)) { if ((rc = sprintf (v1, "\"%c\"", c->value)) < 0) goto finish; } else { if ((rc = sprintf (v1, ":CHR: &%.2X", c->value)) < 0) goto finish; } if ((rc = EmitS (file, cnst, "*", v1)) < 0) goto finish; } break; case def_TYPE_BOOL: { char v1 [def_ID_LIMIT + 1]; if ((rc = sprintf (v1, "{%s}", WHETHER (c->value))) < 0) goto finish; if ((rc = EmitS (file, cnst, "*", v1)) < 0) goto finish; } break; default: if ((rc = EmitX (file, cnst, "*", c->value)) < 0) goto finish; break; } } if (!start) if ((rc = fprintf (file, "\n")) < 0) goto finish; /*Emit the TYPE declarations.*/ start = TRUE; context = 0; while (TRUE) { if ((error = lookup_enumerate (types, &type, (void **) &t, &context)) != NULL) goto finish; if (context == 0) break; if (start) { if ((rc = fprintf (file, ";Symbols for structure offsets and sizes\n")) < 0) goto finish; start = FALSE; } if (t != NULL && t->tag != def_TYPE_ABSTRACT) { if ((rc = Emit_Decl (file, t, type, TRUE, 0)) < 0) goto finish; } else { if ((rc = EmitS (file, type, "*", "4 ;abstract type")) < 0) goto finish; } } if (!start) if ((rc = fprintf (file, "\n")) < 0) goto finish; /*Emit the SWI definitions.*/ start = TRUE; context = 0; while (TRUE) { char title [def_ID_LIMIT + 1] = "X"; bool first, titled; int i; if ((error = lookup_enumerate (swis, &swi, (void **) &s, &context)) != NULL) goto finish; if (context == 0) break; if (start) { if ((rc = fprintf (file, ";Symbols for SWI's and SWI reason codes\n")) < 0) goto finish; start = FALSE; } strcat (title, swi); titled = FALSE; if (s->starred_swi) { if ((rc = EmitX (file, title, "*", s->swi | 1 << 17)) < 0) goto finish; if ((rc = EmitX (file, title + 1, "*", s->swi)) < 0) goto finish; titled = TRUE; } else for (i = 0; i < 10; i++) if (s->starred_constants [i]) { if ((rc = EmitX (file, title + 1, "*", s->constants [i])) < 0) goto finish; titled = TRUE; break; } if (titled) { if (!s->absent) { first = TRUE; for (i = 0; i < 10; i++) if ((s->k & 1 << i) != NONE) { if (first) { if ((rc = fprintf (file, " ;Entry\n")) < 0) goto finish; first = FALSE; } if ((s->i & 1 << i) != NONE) { /*there is an operation to involve*/ if ((rc = fprintf (file, " ; R%d = &%X %s %s (", i, s->constants [i], Op [s->op [i]], s->inputs [i]->name)) < 0) goto finish; if ((rc = Emit_Name (file, s->inputs [i])) < 0) goto finish; if ((rc = fprintf (file, ")\n")) < 0) goto finish; } else { if ((rc = fprintf (file, " ; R%d = &%X\n", i, s->constants [i])) < 0) goto finish; } } else if ((s->i & 1 << i) != NONE) { if (first) { if ((rc = fprintf (file, " ;Entry\n")) < 0) goto finish; first = FALSE; } if ((rc = fprintf (file, " ; R%d %s %s (", i, (s->ri & 1 << i) == 0? "=": "->", s->inputs [i]->name)) < 0) goto finish; if ((rc = Emit_Name (file, s->inputs [i])) < 0) goto finish; if ((rc = fprintf (file, ")\n")) < 0) goto finish; } first = TRUE; for (i = 0; i < 10; i++) if ((s->o & 1 << i) != NONE) { if (first) { if ((rc = fprintf (file, " ;Exit\n")) < 0) goto finish; first = FALSE; } if ((rc = fprintf (file, " ; R%d %s %s (", i, (s->ro & 1 << i) == 0? "=": "->", s->outputs [i]->name)) < 0) goto finish; if ((rc = Emit_Name (file, s->outputs [i])) < 0) goto finish; if ((rc = fprintf (file, ")\n")) < 0) goto finish; } else if ((s->c & 1 << i) != NONE) { if (first) { if ((rc = fprintf (file, " ;Exit\n")) < 0) goto finish; first = FALSE; } if ((rc = fprintf (file, " ; R%d corrupted\n", i)) < 0) goto finish; } } if ((rc = fprintf (file, "\n")) < 0) goto finish; } } if ((rc = Emit (file, NULL, "]")) < 0) goto finish; if ((rc = Emit (file, NULL, "END")) < 0) goto finish; finish: if (rc < 0) error = (os_error *)_kernel_last_oserror (); /* TV 980115 */ return error; }