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 <tag=%d>\n", b); break;
case 8: sprintf(result+strlen(result), "16-bit-enumerated format <tag=%d>\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 <tag=%d>\n", b); break;
case 8: sprintf(result+strlen(result), "16-bit-enumerated format <tag=%d>\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 <tag=%d>\n", b); break;
case 8: sprintf(result+strlen(result), "16-bit-enumerated format <tag=%d>\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 */
}