|
|
1.1 ! root 1: #include "../h/rt.h" ! 2: #include "../h/record.h" ! 3: ! 4: /* ! 5: * image(x) - return string image of object x. Nothing fancy here, ! 6: * just plug and chug on a case-wise basis. ! 7: */ ! 8: ! 9: Ximage(nargs, arg1, arg0) ! 10: int nargs; ! 11: struct descrip arg1, arg0; ! 12: { ! 13: register int len, outlen, rnlen; ! 14: register char *s; ! 15: register union block *bp; ! 16: char *type; ! 17: extern char *alcstr(); ! 18: extern struct descrip *cstos(); ! 19: char sbuf[MAXSTRING]; ! 20: FILE *fd; ! 21: ! 22: DeRef(arg1) ! 23: ! 24: if (NULLDESC(arg1)) { /* &null */ ! 25: STRLOC(arg0) = "&null"; ! 26: STRLEN(arg0) = 5; ! 27: return; ! 28: } ! 29: ! 30: if (QUAL(arg1)) { ! 31: /* ! 32: * Get some string space. The magic 2 is for the double quote at each ! 33: * end of the resulting string. ! 34: */ ! 35: sneed(prescan(&arg1) + 2); ! 36: len = STRLEN(arg1); ! 37: s = STRLOC(arg1); ! 38: outlen = 2; ! 39: /* ! 40: * Form the image by putting a " in the string space, calling ! 41: * doimage with each character in the string, and then putting ! 42: * a " at then end. Note that doimage directly writes into the ! 43: * string space. (Hence the indentation.) This techinique is used ! 44: * several times in this routine. ! 45: */ ! 46: STRLOC(arg0) = alcstr("\"", 1); ! 47: while (len-- > 0) ! 48: outlen += doimage(*s++, '"'); ! 49: alcstr("\"", 1); ! 50: STRLEN(arg0) = outlen; ! 51: return; ! 52: } ! 53: ! 54: switch (TYPE(arg1)) { ! 55: case T_INTEGER: ! 56: #ifdef LONGS ! 57: case T_LONGINT: ! 58: #endif LONGS ! 59: case T_REAL: ! 60: /* ! 61: * Form a string representing the number and allocate it. ! 62: */ ! 63: cvstr(&arg1, sbuf); ! 64: len = STRLEN(arg1); ! 65: sneed(len); ! 66: STRLOC(arg0) = alcstr(STRLOC(arg1), len); ! 67: STRLEN(arg0) = len; ! 68: return; ! 69: ! 70: case T_CSET: ! 71: /* ! 72: * Check for distinguished csets by looking at the address of ! 73: * of the object to image. If one is found, make a string ! 74: * naming it and return. ! 75: */ ! 76: if (BLKLOC(arg1) == ((union block *) &k_ascii)) { ! 77: STRLOC(arg0) = "&ascii"; ! 78: STRLEN(arg0) = 6; ! 79: return; ! 80: } ! 81: else if (BLKLOC(arg1) == ((union block *) &k_cset)) { ! 82: STRLOC(arg0) = "&cset"; ! 83: STRLEN(arg0) = 5; ! 84: return; ! 85: } ! 86: else if (BLKLOC(arg1) == ((union block *) &k_lcase)) { ! 87: STRLOC(arg0) = "&lcase"; ! 88: STRLEN(arg0) = 6; ! 89: return; ! 90: } ! 91: else if (BLKLOC(arg1) == ((union block *) &k_ucase)) { ! 92: STRLOC(arg0) = "&ucase"; ! 93: STRLEN(arg0) = 6; ! 94: return; ! 95: } ! 96: /* ! 97: * Convert the cset to a string and proceed as is done for ! 98: * string images but use a ' rather than " to bound the ! 99: * result string. ! 100: */ ! 101: cvstr(&arg1, sbuf); ! 102: sneed(prescan(&arg1) + 2); ! 103: len = STRLEN(arg1); ! 104: s = STRLOC(arg1); ! 105: outlen = 2; ! 106: STRLOC(arg0) = alcstr("'", 1); ! 107: while (len-- > 0) ! 108: outlen += doimage(*s++, '\''); ! 109: alcstr("'", 1); ! 110: STRLEN(arg0) = outlen; ! 111: return; ! 112: ! 113: case T_FILE: ! 114: /* ! 115: * Check for distinguished files by looking at the address of ! 116: * of the object to image. If one is found, make a string ! 117: * naming it and return. ! 118: */ ! 119: if ((fd = BLKLOC(arg1)->file.fd) == stdin) { ! 120: STRLEN(arg0) = 6; ! 121: STRLOC(arg0) = "&input"; ! 122: } ! 123: else if (fd == stdout) { ! 124: STRLEN(arg0) = 7; ! 125: STRLOC(arg0) = "&output"; ! 126: } ! 127: else if (fd == stderr) { ! 128: STRLEN(arg0) = 7; ! 129: STRLOC(arg0) = "&errout"; ! 130: } ! 131: else { ! 132: /* ! 133: * The file is not a standard one, form a string of the form ! 134: * file(nm) where nm is the argument originally given to ! 135: * open. ! 136: */ ! 137: sneed(prescan(&BLKLOC(arg1)->file.fname)+6); ! 138: len = STRLEN(BLKLOC(arg1)->file.fname); ! 139: s = STRLOC(BLKLOC(arg1)->file.fname); ! 140: outlen = 6; ! 141: STRLOC(arg0) = alcstr("file(", 5); ! 142: while (len-- > 0) ! 143: outlen += doimage(*s++, '\0'); ! 144: alcstr(")", 1); ! 145: STRLEN(arg0) = outlen; ! 146: } ! 147: return; ! 148: ! 149: case T_PROC: ! 150: /* ! 151: * Produce one of: ! 152: * "procedure name" ! 153: * "function name" ! 154: * "record constructor name" ! 155: * ! 156: * Note that the number of dynamic locals is used to determine ! 157: * what type of "procedure" is at hand. ! 158: */ ! 159: len = STRLEN(BLKLOC(arg1)->proc.pname); ! 160: s = STRLOC(BLKLOC(arg1)->proc.pname); ! 161: switch (BLKLOC(arg1)->proc.ndynam) { ! 162: default: type = "procedure "; break; ! 163: case -1: type = "function "; break; ! 164: case -2: type = "record constructor "; break; ! 165: } ! 166: outlen = strlen(type); ! 167: sneed(len + outlen); ! 168: STRLOC(arg0) = alcstr(type, outlen); ! 169: alcstr(s, len); ! 170: STRLEN(arg0) = len + outlen; ! 171: return; ! 172: ! 173: case T_LIST: ! 174: /* ! 175: * Produce: ! 176: * "list(n)" ! 177: * where n is the current size of the list. ! 178: */ ! 179: bp = BLKLOC(arg1); ! 180: sprintf(sbuf, "list(%d)", bp->list.cursize); ! 181: len = strlen(sbuf); ! 182: sneed(len); ! 183: STRLOC(arg0) = alcstr(sbuf, len); ! 184: STRLEN(arg0) = len; ! 185: return; ! 186: ! 187: case T_LELEM: ! 188: STRLEN(arg0) = 18; ! 189: STRLOC(arg0) = "list element block"; ! 190: return; ! 191: ! 192: case T_TABLE: ! 193: /* ! 194: * Produce: ! 195: * "table(n)" ! 196: * where n is the size of the table. ! 197: */ ! 198: bp = BLKLOC(arg1); ! 199: sprintf(sbuf, "table(%d)", bp->table.cursize); ! 200: len = strlen(sbuf); ! 201: sneed(len); ! 202: STRLOC(arg0) = alcstr(sbuf, len); ! 203: STRLEN(arg0) = len; ! 204: return; ! 205: ! 206: case T_TELEM: ! 207: STRLEN(arg0) = 19; ! 208: STRLOC(arg0) = "table element block"; ! 209: return; ! 210: ! 211: #ifdef SETS ! 212: case T_SET: ! 213: /* ! 214: * Produce "set(n)" where n is size of the set. ! 215: */ ! 216: bp = BLKLOC(arg1); ! 217: sprintf(sbuf, "set(%d)", bp->set.setsize); ! 218: len = strlen(sbuf); ! 219: sneed(len); ! 220: STRLOC(arg0) = alcstr(sbuf,len); ! 221: STRLEN(arg0) = len; ! 222: return; ! 223: ! 224: case T_SELEM: ! 225: STRLEN(arg0) = 17; ! 226: STRLOC(arg0) = "set element block"; ! 227: return; ! 228: #endif SETS ! 229: ! 230: case T_RECORD: ! 231: /* ! 232: * Produce: ! 233: * "record name(n)" ! 234: * where n is the number of fields. ! 235: */ ! 236: bp = BLKLOC(arg1); ! 237: rnlen = STRLEN(bp->record.recptr->recname); ! 238: sneed(15 + rnlen); /* 15 = *"record " + *"(nnnnnn)" */ ! 239: bp = BLKLOC(arg1); ! 240: sprintf(sbuf, "(%d)", bp->record.recptr->nfields); ! 241: len = strlen(sbuf); ! 242: STRLOC(arg0) = alcstr("record ", 7); ! 243: alcstr(STRLOC(bp->record.recptr->recname), ! 244: rnlen); ! 245: alcstr(sbuf, len); ! 246: STRLEN(arg0) = 7 + len + rnlen; ! 247: return; ! 248: ! 249: case T_ESTACK: ! 250: /* ! 251: * Produce: ! 252: * "co-expression(n)" ! 253: * where n is the number of results that have been produced. ! 254: */ ! 255: sneed(22); ! 256: sprintf(sbuf, "(%d)", BLKLOC(arg1)->estack.nresults); ! 257: len = strlen(sbuf); ! 258: STRLOC(arg0) = alcstr("co-expression", 13); ! 259: alcstr(sbuf, len); ! 260: STRLEN(arg0) = 13 + len; ! 261: return; ! 262: ! 263: default: ! 264: syserr("image: unknown type."); ! 265: } ! 266: } ! 267: ! 268: Procblock(image,1) ! 269: ! 270: /* ! 271: * doimage(c,q) - allocate character c in string space, with escape ! 272: * conventions if c is unprintable, '\', or equal to q. ! 273: * Returns number of characters allocated. ! 274: */ ! 275: ! 276: doimage(c, q) ! 277: int c, q; ! 278: { ! 279: static char *cbuf = "\\\0\0\0"; ! 280: extern char *alcstr(); ! 281: ! 282: if (c >= ' ' && c < '\177') { ! 283: /* ! 284: * c is printable, but special case ", ', and \. ! 285: */ ! 286: switch (c) { ! 287: case '"': ! 288: if (c != q) goto def; ! 289: alcstr("\\\"", 2); ! 290: return (2); ! 291: case '\'': ! 292: if (c != q) goto def; ! 293: alcstr("\\'", 2); ! 294: return (2); ! 295: case '\\': ! 296: alcstr("\\\\", 2); ! 297: return (2); ! 298: default: ! 299: def: ! 300: cbuf[0] = c; ! 301: cbuf[1] = '\0'; ! 302: alcstr(cbuf,1); ! 303: return (1); ! 304: } ! 305: } ! 306: ! 307: /* ! 308: * c is some sort of unprintable character. If it is one of the common ! 309: * ones, produce a special representation for it, otherwise, produce ! 310: * its octal value. ! 311: */ ! 312: switch (c) { ! 313: case '\b': /* backspace */ ! 314: alcstr("\\b", 2); ! 315: return (2); ! 316: case '\177': /* delete */ ! 317: alcstr("\\d", 2); ! 318: return (2); ! 319: case '\33': /* escape */ ! 320: alcstr("\\e", 2); ! 321: return (2); ! 322: case '\f': /* form feed */ ! 323: alcstr("\\f", 2); ! 324: return (2); ! 325: case '\n': /* new line */ ! 326: alcstr("\\n", 2); ! 327: return (2); ! 328: case '\r': /* return */ ! 329: alcstr("\\r", 2); ! 330: return (2); ! 331: case '\t': /* horizontal tab */ ! 332: alcstr("\\t", 2); ! 333: return (2); ! 334: case '\13': /* vertical tab */ ! 335: alcstr("\\v", 2); ! 336: return (2); ! 337: default: /* octal constant */ ! 338: cbuf[0] = '\\'; ! 339: cbuf[1] = ((c&0300) >> 6) + '0'; ! 340: cbuf[2] = ((c&070) >> 3) + '0'; ! 341: cbuf[3] = (c&07) + '0'; ! 342: alcstr(cbuf, 4); ! 343: return (4); ! 344: } ! 345: } ! 346: ! 347: /* ! 348: * prescan(d) - return upper bound on length of expanded string. Note ! 349: * that the only time that prescan is wrong is when the string contains ! 350: * one of the "special" unprintable characters, e.g. tab. ! 351: */ ! 352: prescan(d) ! 353: struct descrip *d; ! 354: { ! 355: register int slen, len; ! 356: register char *s, c; ! 357: ! 358: s = STRLOC(*d); ! 359: len = 0; ! 360: for (slen = STRLEN(*d); slen > 0; slen--) ! 361: if ((c = (*s++)) < ' ' || c >= 0177) ! 362: len += 4; ! 363: else if (c == '"' || c == '\\' || c == '\'') ! 364: len += 2; ! 365: else ! 366: len++; ! 367: ! 368: return (len); ! 369: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.