Annotation of 43BSD/contrib/icon/functions/image.c, revision 1.1.1.1

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:    }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.