char *makelower(char *s) { char *copy; char *p; copy = p = strdup(s); /* heap lossage */ while (*p != '\0') { if (isalpha(*p) && isupper(*p)) *p = tolower(*p); p += 1; } return copy; } void localtag(char *result, int tagnum, char *name) { if (name == NULL) { sprintf(result+strlen(result), "V_%04x_ERROR", tagnum); return; } if (opt_safenames) { sprintf(result+strlen(result), "V_%04x_%s", tagnum, name); } else { sprintf(result+strlen(result), "%s", makelower(name)); /* HEAP LOSSAGE */ /* better to make lower in the DEF call! */ } } /* RAWTAG is the debug version that fully decodes a tag. (But *only* a tag) */ char *rawtag(int tagnum) { int a, b, c, t, f, u, i, s, x; char *name; static char result[1024]; /* hacky */ if (tagnum < 0) { return "{**COMPLEX OP**}"; /* for now */ } /* See http://www.gtoal.com/athome/edinburgh/imp/imp77/icode.html#define */ name = (char *)tag[tagnum].data; /* Don't know if this is valid yet */ a = tag[tagnum].a; b = tag[tagnum].b; c = tag[tagnum].c; *result = '\0'; t = a>>4; f = a&15; x = c&7; c >>= 3; s = c&1; c >>= 1; i = c&1; c >>= 1; u = c&1; sprintf(result, "/*t=%d f=%d x=%d s=%d i=%d u=%d*/",t,f,x,s,i,u); switch(x) { case 0: break; case 1: strcat(result, "%own "); break; case 2: strcat(result, "%constant "); break; case 3: strcat(result, "%external "); break; case 4: strcat(result, "%system "); break; case 5: strcat(result, "%dynamic "); break; case 6: strcat(result, "%prim "); break; case 7: strcat(result, "%perm "); break; } switch (t&15) { case 0: break; case 1: switch (b) { case 1: break; case 2: strcat(result, "%byte "); break; case 3: strcat(result, "%short/*A*/ "); break; default: strcat(result, "{error} "); break; } strcat(result, "%integer "); break; case 2: switch (b) { case 1: break; case 4: strcat(result, "%long "); break; default: strcat(result, "{error} "); break; } strcat(result, "%real "); break; case 3: sprintf(result+strlen(result), "%%string (%d) ", b); break; case 4: sprintf(result+strlen(result), "%%record {%s} ", (char *)tag[b].data); break; case 5: strcat(result, "%boolean "); break; case 6: strcat(result, "set\n"); break; case 7: sprintf(result+strlen(result), "8-bit-enumerated format \n", b); break; case 8: sprintf(result+strlen(result), "16-bit-enumerated format \n", b); break; case 9: strcat(result, "%name "); break; case 10: strcat(result, "%char "); break; default: strcat(result, "{undefined} "); break; } switch (f) { case 0: strcat(result, "{void} "); break; case 1: break; case 2: strcat(result, "%name "); break; case 3: strcat(result, "%label "); break; case 4: strcat(result, "%format "); break; case 5: strcat(result, "{undefined} "); break; case 6: strcat(result, "%switch/*a*/ "); break; case 7: strcat(result, "%routine "); break; case 8: strcat(result, "%function "); break; case 9: strcat(result, "%map "); break; case 10: strcat(result, "%predicate "); break; case 11: strcat(result, "%array "); break; case 12: strcat(result, "%arrayname "); break; case 13: strcat(result, "%namearray "); break; case 14: strcat(result, "%namearrayname "); break; case 15: strcat(result, "{undefined} "); break; } switch (s) { case 0: break; case 1: strcat(result, "%spec "); break; } if ((x == 2) && (f == 1)) { sprintf(result+strlen(result), "%d {tag %04x} ", tag[tagnum].data, tagnum); } else { sprintf(result+strlen(result), "%s {tag %04x} ", name, tagnum); } switch (i) { /* An indirect object (I=1) differs from F=2 in that F=2 implies that the actual object created will be a pointer and will be dereferenced whenever used unless explicit action is taken (e.g. use of Assign-Reference). If I=1 a pointer will be created (usually as an integer) and will be treated as an integer (or address) with no automatic dereferencing taking place. */ case 0: break; case 1: /*strcat(result, "{ind obj} "); */ break; } /* switch (u) { case 0: memprintf("{no unass check} "); break; case 1: memprintf("{unass check} "); break; } */ result[1023] = '\0'; return strdup(result); /* SHOULD BE: caller copies if needed */ } char *rawcell(int celltag) /* para must be positive */ { char result[1024]; int op, opdcount; if (celltag < 0) { memprintf("/*be careful with the signs there buddy -rawcell(%d)*/\n", celltag); celltag = -celltag; } op = code[celltag].op; opdcount = code[celltag].opdcount_or_tag; sprintf(result, "{code[%d].op=%c,.count/tag=%d}", celltag, op, opdcount); return strdup(result); } /* cdecl generates a C version of declarations */ char *cdecl(int tagnum) { int a, b, c, t, f, u, i, s, x; char *name; static char result[1024]; /* hacky */ if (tagnum < 0) { return "{**COMPLEX OP**}"; /* for now */ } /* See http://www.gtoal.com/athome/edinburgh/imp/imp77/icode.html#define */ name = (char *)tag[tagnum].data; /* Don't know if this is valid yet */ a = tag[tagnum].a; b = tag[tagnum].b; c = tag[tagnum].c; *result = '\0'; t = a>>4; f = a&15; x = c&7; c >>= 3; s = c&1; c >>= 1; i = c&1; c >>= 1; u = c&1; //if (debug_input) memprintf("/*t=%d f=%d x=%d s=%d i=%d u=%d b=%d c=%d*/",t,f,x,s,i,u,b,c); switch(x) { case 0: break; case 1: strcat(result, "static "); break; case 2: strcat(result, "const "); break; case 3: { /* TODO - if s == 1, then this is a forward declaration and should be followed by ';' after the parameter list, otherwise should be followed by "{" preceding the actual code */ strcat(result, "extern "); break; } case 4: strcat(result, "%system "); break; case 5: strcat(result, "%dynamic "); break; case 6: strcat(result, "extern "); break; /* prim */ case 7: strcat(result, "extern "); break; /* perm */ } switch (t&15) { case 0: if (f == 2) sprintf(result+strlen(result), "int typeof_%s, void ", name); /*HACK*/ break; case 1: switch (b) { case 1: strcat(result, "int "); break; case 2: strcat(result, "char "); break; case 3: strcat(result, "short "); break; default: strcat(result, "{error} "); break; } break; case 2: switch (b) { case 1: break; case 4: strcat(result, "long "); break; default: strcat(result, "{error} "); break; } strcat(result, "real "); break; case 3: sprintf(result+strlen(result), "char *"/* maxlen = b+1*/); break; case 4: { if (f == 4) { strcat(result, "typedef ");/* and append type after the members */ RECORDFORMAT = TRUE; } sprintf(result+strlen(result), "struct %s ", (char *)tag[b].data); if (f == 2) { if ((t&15) == 4 /* pointer */) { sprintf(result+strlen(result), "*"); } } else if (f == 11) { /* only if array */ sprintf(result+strlen(result), "*"); /* array mapped to pointer */ } else { /* YYY3 */ } if ((x == 2) && (t == 1) && (f == 1)) { sprintf(result+strlen(result), "%d {ERROR?}", tag[tagnum].data); } else { /* ***NOT*** if external etc. only for locals */ localtag(result, tagnum, name); } /* for the momeny include all of the 'f' code. remove once tested */ switch (f) { case 0: strcat(result, "/*void1*/ "); break; case 1: break; case 2: if ((t&15) != 4) strcat(result, " * /*QQQ*/ "); break; /* eg %integername fred -> int *fred */ case 3: strcat(result, "label "); break; case 4: strcat(result, ""); break; /* moved to before the name above */ case 5: strcat(result, "{undefined} "); break; case 6: strcat(result, "%switch/*0*/ "); break; case 7: strcat(result, "void "); break; case 8: strcat(result, " "); break; case 9: strcat(result, " "); break; case 10: strcat(result, "int "); break; case 11: if ((t&15) != 4) strcat(result, " * /*WWW*/ "); break; /* int array decl */ case 12: strcat(result, "* /*12*/ "); break; case 13: strcat(result, "*[] /*13*/ "); break; case 14: strcat(result, "**[] /*14*/ "); break; case 15: strcat(result, "{undefined} "); break; } // sprintf(result+strlen(result), // " %s ", (char *)tag[b].data); return(strdup(result)); } case 5: strcat(result, "%boolean "); break; case 6: strcat(result, "set\n"); break; case 7: sprintf(result+strlen(result), "8-bit-enumerated format \n", b); break; case 8: sprintf(result+strlen(result), "16-bit-enumerated format \n", b); break; case 9: strcat(result, "* /*%name2*/"); break; case 10: strcat(result, "%char "); break; default: strcat(result, "{undefined} "); break; } switch (f) { case 0: strcat(result, "/*void1*/ "); break; case 1: break; case 2: strcat(result, " *"); break; /* eg %integername fred -> int *fred */ case 3: strcat(result, "label "); break; case 4: strcat(result, "%format "); break; case 5: strcat(result, "{undefined} "); break; /* http://docs.freebsd.org/info/gcc/gcc.info.Labels_as_Values.html */ case 6: strcat(result, "/*todo: gcc jump table extension*/ void **"); break; case 7: strcat(result, "void "); break; case 8: strcat(result, " "); break; case 9: strcat(result, " *"); break; /* %map */ case 10: strcat(result, "int "); break; case 11: sprintf(result+strlen(result), " *"); break; /* array mapped to pointer */ case 12: strcat(result, "* /*12*/ "); break; case 13: strcat(result, "*[] /*13*/ "); break; case 14: strcat(result, "**[] /*14*/ "); break; case 15: strcat(result, "{undefined} "); break; } if (f < 7 || f > 10) switch (s) { case 0: break; case 1: { strcat(result, "/*spec*/ "); break; } } else if (s == 1) SPEC = TRUE; if ((x == 2) && (t == 1) && (f == 1)) { sprintf(result+strlen(result), "%d {ERROR?}", tag[tagnum].data); } else { /* ***NOT*** if external etc. only for locals */ localtag(result, tagnum, name); } switch (i) { /* An indirect object (I=1) differs from F=2 in that F=2 implies that the actual object created will be a pointer and will be dereferenced whenever used unless explicit action is taken (e.g. use of Assign-Reference). If I=1 a pointer will be created (usually as an integer) and will be treated as an integer (or address) with no automatic dereferencing taking place. */ case 0: break; case 1: /*strcat(result, "{ind obj} "); */ break; } /* switch (u) { case 0: memprintf("{no unass check} "); break; case 1: memprintf("{unass check} "); break; } */ return strdup(result); /* heap lossage */ /* SHOULD BE: caller copies if needed */ } /* this is meant to be the short version that gets the value of a tag into a string; however any cases not yet handled still have the full debugging text present, so that I don't overlook them if they're invoked. Final code should throw most of this away */ void appendchar(char *s, int c) { int l = strlen(s); s[l] = c; s[l+1] = '\0'; } char *tag_rhs_value(int tagnum) { int a, b, c, t, f, u, i, s, x; char *name; static char result[1024]; /* hacky */ /* See http://www.gtoal.com/athome/edinburgh/imp/imp77/icode.html#define */ *result = '\0'; name = (char *)tag[tagnum].data; /* Don't know if this is valid yet */ a = tag[tagnum].a; b = tag[tagnum].b; c = tag[tagnum].c; t = a>>4; f = a&15; x = c&7; c >>= 3; s = c&1; c >>= 1; i = c&1; c >>= 1; u = c&1; if (tagnum < 0) { sprintf(result, "%s", evalexpr(tagnum)); return strdup(result); /* heap lossage */ } switch (t&15) { case 3: if ((x == 2) && (b < 0 /* length=-1 for internal consts */)) { int i; char *s = (char *)tag[tagnum].data; /* ONLY IF CONST??? */ assert(s != NULL); appendchar(result, '"'); for (i = 1; i <= *s; i++) { if (s[i] == '"') appendchar(result, '\\'); if (s[i] == '\\') appendchar(result, '\\'); appendchar(result, s[i]); } appendchar(result, '"'); /*break;*/ return strdup(result); /* no more to do? */ } else { localtag(result, tagnum, name); // sprintf(result, "***STRING VAR t=%d f=%d x=%d s=%d ***", // t,f,x,s); return(strdup(result)); } case 4: /* record format */; break; default: break; } switch (f) { case 0: strcat(result, "{void} "); break; case 1: break; case 2: { /* TODO: if we have a recordname parameter and we access a field of the record in a procedure, this code currently generates *v.f rather than v->f - this is bad C although I suspect probably allowed under the gcc extensions */ strcat(result, "*"); /* imp's auto deref of pointers */ break; } case 3: strcat(result, "%label "); break; case 4: strcat(result, "%format "); break; case 5: strcat(result, "{undefined} "); break; case 6: break; /* %switch */ case 7: break; case 8: break; case 9: strcat(result, "*"); break; /* map */ case 10: break; case 11: break; case 12: break; case 13: strcat(result, "%namearray "); break; case 14: strcat(result, "%namearrayname "); break; case 15: strcat(result, "{undefined} "); break; } if ((x == 2) && (f == 1)) { sprintf(result+strlen(result), "%d", tag[tagnum].data); } else { /* ***NOT*** if external etc. only for locals */ localtag(result, tagnum, name); } return strdup(result); /* heap lossage */ /* SHOULD BE: caller copies if needed */ } char *tag_lhs_value(int tagnum) { int a, b, c, t, f, u, i, s, x; char *name; static char result[1024]; /* hacky */ *result = '\0'; if (tagnum < 0) { sprintf(result, "%s", evalexpr(tagnum)); return strdup(result); } /* See http://www.gtoal.com/athome/edinburgh/imp/imp77/icode.html#define */ name = (char *)tag[tagnum].data; /* Don't know if this is valid yet */ a = tag[tagnum].a; b = tag[tagnum].b; c = tag[tagnum].c; t = a>>4; f = a&15; x = c&7; c >>= 3; s = c&1; c >>= 1; i = c&1; c >>= 1; u = c&1; switch (t&15) { case 3: // sprintf(result+strlen(result), "%%string/*1*/ (%d) ", b); sprintf(result+strlen(result), "?S%d;", b); break; case 4: // sprintf(result+strlen(result), "/*LHSval*/%%record {%s} ", (char *)tag[b].data); sprintf(result+strlen(result), "?Rsizeof struct %s;", (char *)tag[b].data); break; default: break; } switch (f) { case 0: strcat(result, "{void} "); break; case 1: break; case 2: strcat(result, "*"); break; /* Imp's auto de-ref on storing to a ptr */ case 3: strcat(result, "%label "); break; case 4: strcat(result, "%format "); break; case 5: strcat(result, "{undefined} "); break; case 6: strcat(result, "%switch/*c*/ "); break; case 7: strcat(result, "%routine "); break; case 8: strcat(result, "%function "); break; case 9: strcat(result, "%map "); break; case 10: strcat(result, "%predicate "); break; case 11: strcat(result, "%array "); break; case 12: strcat(result, "%arrayname "); break; case 13: strcat(result, "%namearray "); break; case 14: strcat(result, "%namearrayname "); break; case 15: strcat(result, "{undefined} "); break; } switch (s) { case 0: break; case 1: strcat(result, "%spec "); break; } if ((x == 2) && (f == 1)) { sprintf(result+strlen(result), "%d", tag[tagnum].data); } else { /* ***NOT*** if external etc. only for locals */ localtag(result, tagnum, name); } switch (i) { /* An indirect object (I=1) differs from F=2 in that F=2 implies that the actual object created will be a pointer and will be dereferenced whenever used unless explicit action is taken (e.g. use of Assign-Reference). If I=1 a pointer will be created (usually as an integer) and will be treated as an integer (or address) with no automatic dereferencing taking place. */ case 0: break; case 1: /*strcat(result, "{ind obj} "); */ break; } /* switch (u) { case 0: memprintf("{no unass check} "); break; case 1: memprintf("{unass check} "); break; } */ return strdup(result); /* heap lossage */ /* SHOULD BE: caller copies if needed */ } char *tag_rhs_addr(int tagnum) { int a, b, c, t, f, u, i, s, x; char *name; static char result[1024]; /* hacky */ *result = '\0'; if (tagnum < 0) { /* does this need "&" prepended to the result??? */ sprintf(result, "&%s", evalexpr(tagnum)); return strdup(result); } /* See http://www.gtoal.com/athome/edinburgh/imp/imp77/icode.html#define */ name = (char *)tag[tagnum].data; /* Don't know if this is valid yet */ a = tag[tagnum].a; b = tag[tagnum].b; c = tag[tagnum].c; result[0] = '&'; result[1] = '\0'; t = a>>4; f = a&15; x = c&7; c >>= 3; s = c&1; c >>= 1; i = c&1; c >>= 1; u = c&1; switch(x) { case 0: break; /* auto */ case 1: break; /* %own */ case 2: break; /* %constant */ case 3: break; /* %external */ case 4: break; /* %system */ case 5: break; /* %dynamic */ case 6: break; /* %prim */ case 7: break; /* %perm */ } switch (t&15) { case 0: break; case 1: switch (b) { case 1: break; case 2: /*strcat(result, "%byte ");*/ break; case 3: /*strcat(result, "%short ");*/ break; default: strcat(result, "{error} "); break; } break; case 2: switch (b) { case 1: break; case 4: strcat(result, "%long "); break; default: strcat(result, "{error} "); break; } strcat(result, "%real "); break; case 3: /*sprintf(result+strlen(result), "%%string (%d) ", b); */ break; case 4: { // sprintf(result+strlen(result), // "%%record {%s} ", (char *)tag[b].data); break; } case 5: strcat(result, "%boolean "); break; case 6: strcat(result, "set\n"); break; case 7: sprintf(result+strlen(result), "8-bit-enumerated format \n", b); break; case 8: sprintf(result+strlen(result), "16-bit-enumerated format \n", b); break; case 9: strcat(result, "%name{Y} "); break; case 10: strcat(result, "%char "); break; default: strcat(result, "{undefined} "); break; } switch (f) { case 0: strcat(result, "{void} "); break; case 1: break; case 2: { /* undo the '&' which took the address of what follows */ *result = '\0'; } break; case 3: strcat(result, "%label "); break; case 4: strcat(result, "%format "); break; case 5: strcat(result, "{undefined} "); break; case 6: strcat(result, "%switch/*d*/ "); break; case 7: strcat(result, "%routine "); break; case 8: strcat(result, "%function "); break; case 9: strcat(result, "%map "); break; case 10: strcat(result, "%predicate "); break; case 11: strcat(result, "%array "); break; case 12: strcat(result, "%arrayname "); break; case 13: strcat(result, "%namearray "); break; case 14: strcat(result, "%namearrayname "); break; case 15: strcat(result, "{undefined} "); break; } switch (s) { case 0: break; case 1: strcat(result, "%spec "); break; } if ((x == 2) && (f == 1)) { sprintf(result+strlen(result), "%d", tag[tagnum].data); } else { /* ***NOT*** if external etc. only for locals */ localtag(result, tagnum, name); } switch (i) { /* An indirect object (I=1) differs from F=2 in that F=2 implies that the actual object created will be a pointer and will be dereferenced whenever used unless explicit action is taken (e.g. use of Assign-Reference). If I=1 a pointer will be created (usually as an integer) and will be treated as an integer (or address) with no automatic dereferencing taking place. */ case 0: break; case 1: /*strcat(result, "{ind obj} "); */ break; } /* switch (u) { case 0: memprintf("{no unass check} "); break; case 1: memprintf("{unass check} "); break; } */ return strdup(result); /* SHOULD BE: caller copies if needed */ } char *tag_lhs_addr(int tagnum) { int a, b, c, t, f, u, i, s, x; char *name; static char result[1024]; /* hacky */ *result = '\0'; if (tagnum < 0) { /* it may not be wise to use evalexpr here. the only complex case should be a map call, and it needs to be handled specially anyway. Also, still have to do stuff like: byteinteger(cp) = 1 => *(char *)cp = 1; */ return evalexpr(tagnum); } /* See http://www.gtoal.com/athome/edinburgh/imp/imp77/icode.html#define */ name = (char *)tag[tagnum].data; /* Don't know if this is valid yet */ a = tag[tagnum].a; b = tag[tagnum].b; c = tag[tagnum].c; t = a>>4; f = a&15; x = c&7; c >>= 3; s = c&1; c >>= 1; i = c&1; c >>= 1; u = c&1; switch (t&15) { case 3: sprintf(result+strlen(result), "%%string/*3*/ (%d) ", b); break; case 4: /*sprintf(result+strlen(result), "..LHSaddr..%%record {%s} ", (char *)tag[b].data);*/ break; default: break; } switch (f) { case 0: strcat(result, "{void} "); break; case 1: break; case 2: strcat(result, ""); break; /* %name */ case 3: strcat(result, "%label "); break; case 4: strcat(result, "%format "); break; case 5: strcat(result, "{undefined} "); break; case 6: strcat(result, "%switch/*d*/ "); break; case 7: strcat(result, "%routine "); break; case 8: strcat(result, "%function "); break; case 9: strcat(result, "%map "); break; case 10: strcat(result, "%predicate "); break; case 11: strcat(result, "%array "); break; case 12: strcat(result, "%arrayname "); break; case 13: strcat(result, "%namearray "); break; case 14: strcat(result, "%namearrayname "); break; case 15: strcat(result, "{undefined} "); break; } switch (s) { case 0: break; case 1: strcat(result, "%spec "); break; } if ((x == 2) && (f == 1)) { sprintf(result+strlen(result), "%d", tag[tagnum].data); } else { /* ***NOT*** if external etc. only for locals */ localtag(result, tagnum, name); } switch (i) { /* An indirect object (I=1) differs from F=2 in that F=2 implies that the actual object created will be a pointer and will be dereferenced whenever used unless explicit action is taken (e.g. use of Assign-Reference). If I=1 a pointer will be created (usually as an integer) and will be treated as an integer (or address) with no automatic dereferencing taking place. */ case 0: break; case 1: /*strcat(result, "{ind obj} "); */ break; } /* switch (u) { case 0: memprintf("{no unass check} "); break; case 1: memprintf("{unass check} "); break; } */ return strdup(result); /* SHOULD BE: caller copies if needed */ }