Annotation of researchv10no/cmd/f2c/output.c, revision 1.1.1.1

1.1       root        1: /****************************************************************
                      2: Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories and Bellcore.
                      3: 
                      4: Permission to use, copy, modify, and distribute this software
                      5: and its documentation for any purpose and without fee is hereby
                      6: granted, provided that the above copyright notice appear in all
                      7: copies and that both that the copyright notice and this
                      8: permission notice and warranty disclaimer appear in supporting
                      9: documentation, and that the names of AT&T Bell Laboratories or
                     10: Bellcore or any of their entities not be used in advertising or
                     11: publicity pertaining to distribution of the software without
                     12: specific, written prior permission.
                     13: 
                     14: AT&T and Bellcore disclaim all warranties with regard to this
                     15: software, including all implied warranties of merchantability
                     16: and fitness.  In no event shall AT&T or Bellcore be liable for
                     17: any special, indirect or consequential damages or any damages
                     18: whatsoever resulting from loss of use, data or profits, whether
                     19: in an action of contract, negligence or other tortious action,
                     20: arising out of or in connection with the use or performance of
                     21: this software.
                     22: ****************************************************************/
                     23: 
                     24: #include "defs.h"
                     25: #include "names.h"
                     26: #include "output.h"
                     27: 
                     28: #ifndef TRUE
                     29: #define TRUE 1
                     30: #endif
                     31: #ifndef FALSE
                     32: #define FALSE 0
                     33: #endif
                     34: 
                     35: char _assoc_table[] = { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
                     36: 
                     37: /* Opcode table -- This array is indexed by the OP_____ macros defined in
                     38:    defines.h; these macros are expected to be adjacent integers, so that
                     39:    this table is as small as possible. */
                     40: 
                     41: table_entry opcode_table[] = {
                     42:                                { 0, 0, NULL },
                     43:        /* OPPLUS 1 */          { BINARY_OP, 12, "%l + %r" },
                     44:        /* OPMINUS 2 */         { BINARY_OP, 12, "%l - %r" },
                     45:        /* OPSTAR 3 */          { BINARY_OP, 13, "%l * %r" },
                     46:        /* OPSLASH 4 */         { BINARY_OP, 13, "%l / %r" },
                     47:        /* OPPOWER 5 */         { BINARY_OP,  0, "power (%l, %r)" },
                     48:        /* OPNEG 6 */           { UNARY_OP,  14, "-%l" },
                     49:        /* OPOR 7 */            { BINARY_OP,  4, "%l || %r" },
                     50:        /* OPAND 8 */           { BINARY_OP,  5, "%l && %r" },
                     51:        /* OPEQV 9 */           { BINARY_OP,  9, "%l == %r" },
                     52:        /* OPNEQV 10 */         { BINARY_OP,  9, "%l != %r" },
                     53:        /* OPNOT 11 */          { UNARY_OP,  14, "! %l" },
                     54:        /* OPCONCAT 12 */       { BINARY_OP,  0, "concat (%l, %r)" },
                     55:        /* OPLT 13 */           { BINARY_OP, 10, "%l < %r" },
                     56:        /* OPEQ 14 */           { BINARY_OP,  9, "%l == %r" },
                     57:        /* OPGT 15 */           { BINARY_OP, 10, "%l > %r" },
                     58:        /* OPLE 16 */           { BINARY_OP, 10, "%l <= %r" },
                     59:        /* OPNE 17 */           { BINARY_OP,  9, "%l != %r" },
                     60:        /* OPGE 18 */           { BINARY_OP, 10, "%l >= %r" },
                     61:        /* OPCALL 19 */         { BINARY_OP, 15, SPECIAL_FMT },
                     62:        /* OPCCALL 20 */        { BINARY_OP, 15, SPECIAL_FMT },
                     63: 
                     64: /* Left hand side of an assignment cannot have outermost parens */
                     65: 
                     66:        /* OPASSIGN 21 */       { BINARY_OP,  2, "%l = %r" },
                     67:        /* OPPLUSEQ 22 */       { BINARY_OP,  2, "%l += %r" },
                     68:        /* OPSTAREQ 23 */       { BINARY_OP,  2, "%l *= %r" },
                     69:        /* OPCONV 24 */         { BINARY_OP, 14, "%l" },
                     70:        /* OPLSHIFT 25 */       { BINARY_OP, 11, "%l << %r" },
                     71:        /* OPMOD 26 */          { BINARY_OP, 13, "%l %% %r" },
                     72:        /* OPCOMMA 27 */        { BINARY_OP,  1, "%l, %r" },
                     73: 
                     74: /* Don't want to nest the colon operator in parens */
                     75: 
                     76:        /* OPQUEST 28 */        { BINARY_OP, 3, "%l ? %r" },
                     77:        /* OPCOLON 29 */        { BINARY_OP, 3, "%l : %r" },
                     78:        /* OPABS 30 */          { UNARY_OP,  0, "abs(%l)" },
                     79:        /* OPMIN 31 */          { BINARY_OP,   0, SPECIAL_FMT },
                     80:        /* OPMAX 32 */          { BINARY_OP,   0, SPECIAL_FMT },
                     81:        /* OPADDR 33 */         { UNARY_OP, 14, "&%l" },
                     82: 
                     83:        /* OPCOMMA_ARG 34 */    { BINARY_OP, 15, SPECIAL_FMT },
                     84:        /* OPBITOR 35 */        { BINARY_OP,  6, "%l | %r" },
                     85:        /* OPBITAND 36 */       { BINARY_OP,  8, "%l & %r" },
                     86:        /* OPBITXOR 37 */       { BINARY_OP,  7, "%l ^ %r" },
                     87:        /* OPBITNOT 38 */       { UNARY_OP,  14, "~ %l" },
                     88:        /* OPRSHIFT 39 */       { BINARY_OP, 11, "%l >> %r" },
                     89: 
                     90: /* This isn't quite right -- it doesn't handle arrays, for instance */
                     91: 
                     92:        /* OPWHATSIN 40 */      { UNARY_OP,  14, "*%l" },
                     93:        /* OPMINUSEQ 41 */      { BINARY_OP,  2, "%l -= %r" },
                     94:        /* OPSLASHEQ 42 */      { BINARY_OP,  2, "%l /= %r" },
                     95:        /* OPMODEQ 43 */        { BINARY_OP,  2, "%l %%= %r" },
                     96:        /* OPLSHIFTEQ 44 */     { BINARY_OP,  2, "%l <<= %r" },
                     97:        /* OPRSHIFTEQ 45 */     { BINARY_OP,  2, "%l >>= %r" },
                     98:        /* OPBITANDEQ 46 */     { BINARY_OP,  2, "%l &= %r" },
                     99:        /* OPBITXOREQ 47 */     { BINARY_OP,  2, "%l ^= %r" },
                    100:        /* OPBITOREQ 48 */      { BINARY_OP,  2, "%l |= %r" },
                    101:        /* OPPREINC 49 */       { UNARY_OP,  14, "++%l" },
                    102:        /* OPPREDEC 50 */       { UNARY_OP,  14, "--%l" },
                    103:        /* OPDOT 51 */          { BINARY_OP, 15, "%l.%r" },
                    104:        /* OPARROW 52 */        { BINARY_OP, 15, "%l -> %r"},
                    105:        /* OPNEG1 53 */         { UNARY_OP,  14, "-%l" },
                    106:        /* OPDMIN 54 */         { BINARY_OP, 0, "dmin(%l,%r)" },
                    107:        /* OPDMAX 55 */         { BINARY_OP, 0, "dmax(%l,%r)" },
                    108:        /* OPASSIGNI 56 */      { BINARY_OP,  2, "%l = &%r" },
                    109:        /* OPIDENTITY 57 */     { UNARY_OP, 15, "%l" },
                    110:        /* OPCHARCAST 58 */     { UNARY_OP, 14, "(char *)&%l" },
                    111:        /* OPDABS 59 */         { UNARY_OP, 0, "dabs(%l)" },
                    112:        /* OPMIN2 60 */         { BINARY_OP,   0, "min(%l,%r)" },
                    113:        /* OPMAX2 61 */         { BINARY_OP,   0, "max(%l,%r)" },
                    114: 
                    115: /* kludge to imitate (under forcedouble) f77's bizarre treatement of OPNEG... */
                    116: 
                    117:        /* OPNEG KLUDGE */      { UNARY_OP,  14, "-(doublereal)%l" }
                    118: }; /* opcode_table */
                    119: 
                    120: #define OPNEG_KLUDGE (sizeof(opcode_table)/sizeof(table_entry) - 1)
                    121: 
                    122: static char opeqable[sizeof(opcode_table)/sizeof(table_entry)];
                    123: 
                    124: 
                    125: static void output_prim ();
                    126: static void output_unary (), output_binary (), output_arg_list ();
                    127: static void output_list (), output_literal ();
                    128: 
                    129: 
                    130: void expr_out (fp, e)
                    131: FILE *fp;
                    132: expptr e;
                    133: {
                    134:     if (e == (expptr) NULL)
                    135:        return;
                    136: 
                    137:     switch (e -> tag) {
                    138:        case TNAME:     out_name (fp, (struct Nameblock *) e);
                    139:                        return;
                    140: 
                    141:        case TCONST:    out_const(fp, &e->constblock);
                    142:                        goto end_out;
                    143:        case TEXPR:
                    144:                        break;
                    145: 
                    146:        case TADDR:     out_addr (fp, &(e -> addrblock));
                    147:                        goto end_out;
                    148: 
                    149:        case TPRIM:     warn ("expr_out: got TPRIM");
                    150:                        output_prim (fp, &(e -> primblock));
                    151:                        return;
                    152: 
                    153:        case TLIST:     output_list (fp, &(e -> listblock));
                    154:  end_out:              frexpr(e);
                    155:                        return;
                    156: 
                    157:        case TIMPLDO:   err ("expr_out: got TIMPLDO");
                    158:                        return;
                    159: 
                    160:        case TERROR:
                    161:        default:
                    162:                        erri ("expr_out: bad tag '%d'", e -> tag);
                    163:     } /* switch */
                    164: 
                    165: /* Now we know that the tag is TEXPR */
                    166: 
                    167: /* Optimize on simple expressions, such as "a = a + b" ==> "a += b" */
                    168: 
                    169:     if (e -> exprblock.opcode == OPASSIGN && e -> exprblock.rightp &&
                    170:        e -> exprblock.rightp -> tag == TEXPR) {
                    171:        int opcode;
                    172: 
                    173:        opcode = e -> exprblock.rightp -> exprblock.opcode;
                    174: 
                    175:        if (opeqable[opcode]) {
                    176:            expptr leftp, rightp;
                    177: 
                    178:            if ((leftp = e -> exprblock.leftp) &&
                    179:                (rightp = e -> exprblock.rightp -> exprblock.leftp)) {
                    180: 
                    181:                if (same_ident (leftp, rightp)) {
                    182:                    expptr temp = e -> exprblock.rightp;
                    183: 
                    184:                    e -> exprblock.opcode = op_assign(opcode);
                    185: 
                    186:                    e -> exprblock.rightp = temp -> exprblock.rightp;
                    187:                    temp->exprblock.rightp = 0;
                    188:                    frexpr(temp);
                    189:                } /* if same_ident (leftp, rightp) */
                    190:            } /* if leftp && rightp */
                    191:        } /* if opcode == OPPLUS || */
                    192:     } /* if e -> exprblock.opcode == OPASSIGN */
                    193: 
                    194: 
                    195: /* Optimize on increment or decrement by 1 */
                    196: 
                    197:     {
                    198:        int opcode = e -> exprblock.opcode;
                    199:        expptr leftp = e -> exprblock.leftp;
                    200:        expptr rightp = e -> exprblock.rightp;
                    201: 
                    202:        if (leftp && rightp && (leftp -> headblock.vstg == STGARG ||
                    203:                ISINT (leftp -> headblock.vtype)) &&
                    204:                (opcode == OPPLUSEQ || opcode == OPMINUSEQ) &&
                    205:                ISINT (rightp -> headblock.vtype) &&
                    206:                ISICON (e -> exprblock.rightp) &&
                    207:                (ISONE (e -> exprblock.rightp) ||
                    208:                e -> exprblock.rightp -> constblock.Const.ci == -1)) {
                    209: 
                    210: /* Allow for the '-1' constant value */
                    211: 
                    212:            if (!ISONE (e -> exprblock.rightp))
                    213:                opcode = (opcode == OPPLUSEQ) ? OPMINUSEQ : OPPLUSEQ;
                    214: 
                    215: /* replace the existing opcode */
                    216: 
                    217:            if (opcode == OPPLUSEQ)
                    218:                e -> exprblock.opcode = OPPREINC;
                    219:            else
                    220:                e -> exprblock.opcode = OPPREDEC;
                    221: 
                    222: /* Free up storage used by the right hand side */
                    223: 
                    224:            frexpr (e -> exprblock.rightp);
                    225:            e->exprblock.rightp = 0;
                    226:        } /* if opcode == OPPLUS */
                    227:     } /* block */
                    228: 
                    229: 
                    230:     if (is_unary_op (e -> exprblock.opcode))
                    231:        output_unary (fp, &(e -> exprblock));
                    232:     else if (is_binary_op (e -> exprblock.opcode))
                    233:        output_binary (fp, &(e -> exprblock));
                    234:     else
                    235:        erri ("expr_out: bad opcode '%d'", (int) e -> exprblock.opcode);
                    236: 
                    237:     free((char *)e);
                    238: 
                    239: } /* expr_out */
                    240: 
                    241: 
                    242: void out_and_free_statement (outfile, expr)
                    243: FILE *outfile;
                    244: expptr expr;
                    245: {
                    246:     if (expr)
                    247:        expr_out (outfile, expr);
                    248: 
                    249:     nice_printf (outfile, ";\n");
                    250: } /* out_and_free_statement */
                    251: 
                    252: 
                    253: 
                    254: int same_ident (left, right)
                    255: expptr left, right;
                    256: {
                    257:     if (!left || !right)
                    258:        return 0;
                    259: 
                    260:     if (left -> tag == TNAME && right -> tag == TNAME && left == right)
                    261:        return 1;
                    262: 
                    263:     if (left -> tag == TADDR && right -> tag == TADDR &&
                    264:            left -> addrblock.uname_tag == right -> addrblock.uname_tag)
                    265:        switch (left -> addrblock.uname_tag) {
                    266:            case UNAM_REF:
                    267:            case UNAM_NAME:
                    268: 
                    269: /* Check for array subscripts */
                    270: 
                    271:                if (left -> addrblock.user.name -> vdim ||
                    272:                        right -> addrblock.user.name -> vdim)
                    273:                    if (left -> addrblock.user.name !=
                    274:                            right -> addrblock.user.name ||
                    275:                            !same_expr (left -> addrblock.memoffset,
                    276:                            right -> addrblock.memoffset))
                    277:                        return 0;
                    278: 
                    279:                return same_ident ((expptr) (left -> addrblock.user.name),
                    280:                        (expptr) right -> addrblock.user.name);
                    281:            case UNAM_IDENT:
                    282:                return strcmp(left->addrblock.user.ident,
                    283:                                right->addrblock.user.ident) == 0;
                    284:            case UNAM_CHARP:
                    285:                return strcmp(left->addrblock.user.Charp,
                    286:                                right->addrblock.user.Charp) == 0;
                    287:            default:
                    288:                return 0;
                    289:        } /* switch */
                    290: 
                    291:     if (left->tag == TEXPR && left->exprblock.opcode == OPWHATSIN
                    292:        && right->tag == TEXPR && right->exprblock.opcode == OPWHATSIN)
                    293:                return same_ident(left->exprblock.leftp,
                    294:                                 right->exprblock.leftp);
                    295: 
                    296:     return 0;
                    297: } /* same_ident */
                    298: 
                    299:  static int
                    300: samefpconst(c1, c2, n)
                    301:  register Constp c1, c2;
                    302:  register int n;
                    303: {
                    304:        char *s1, *s2;
                    305:        if (!c1->vstg && !c2->vstg)
                    306:                return c1->Const.cd[n] == c2->Const.cd[n];
                    307:        s1 = c1->vstg ? c1->Const.cds[n] : dtos(c1->Const.cd[n]);
                    308:        s2 = c2->vstg ? c2->Const.cds[n] : dtos(c2->Const.cd[n]);
                    309:        return !strcmp(s1, s2);
                    310:        }
                    311: 
                    312:  static int
                    313: sameconst(c1, c2)
                    314:  register Constp c1, c2;
                    315: {
                    316:        switch(c1->vtype) {
                    317:                case TYCOMPLEX:
                    318:                case TYDCOMPLEX:
                    319:                        if (!samefpconst(c1,c2,1))
                    320:                                return 0;
                    321:                case TYREAL:
                    322:                case TYDREAL:
                    323:                        return samefpconst(c1,c2,0);
                    324:                case TYCHAR:
                    325:                        return c1->Const.ccp1.blanks == c2->Const.ccp1.blanks
                    326:                            &&     c1->vleng->constblock.Const.ci
                    327:                                == c2->vleng->constblock.Const.ci
                    328:                            && !memcmp(c1->Const.ccp, c2->Const.ccp,
                    329:                                        (int)c1->vleng->constblock.Const.ci);
                    330:                case TYSHORT:
                    331:                case TYINT:
                    332:                case TYLOGICAL:
                    333:                        return c1->Const.ci == c2->Const.ci;
                    334:                }
                    335:        err("unexpected type in sameconst");
                    336:        return 0;
                    337:        }
                    338: 
                    339: /* same_expr -- Returns true only if   e1 and e2   match.  This is
                    340:    somewhat pessimistic, but can afford to be because it's just used to
                    341:    optimize on the assignment operators (+=, -=, etc). */
                    342: 
                    343: int same_expr (e1, e2)
                    344: expptr e1, e2;
                    345: {
                    346:     if (!e1 || !e2)
                    347:        return !e1 && !e2;
                    348: 
                    349:     if (e1 -> tag != e2 -> tag || e1 -> headblock.vtype != e2 -> headblock.vtype)
                    350:        return 0;
                    351: 
                    352:     switch (e1 -> tag) {
                    353:         case TEXPR:
                    354:            if (e1 -> exprblock.opcode != e2 -> exprblock.opcode)
                    355:                return 0;
                    356: 
                    357:            return same_expr (e1 -> exprblock.leftp, e2 -> exprblock.leftp) &&
                    358:                   same_expr (e1 -> exprblock.rightp, e2 -> exprblock.rightp);
                    359:        case TNAME:
                    360:        case TADDR:
                    361:            return same_ident (e1, e2);
                    362:        case TCONST:
                    363:            return sameconst(&e1->constblock, &e2->constblock);
                    364:        default:
                    365:            return 0;
                    366:     } /* switch */
                    367: } /* same_expr */
                    368: 
                    369: 
                    370: 
                    371: void out_name (fp, namep)
                    372:  FILE *fp;
                    373:  Namep namep;
                    374: {
                    375:     extern int usedefsforcommon;
                    376:     Extsym *comm;
                    377: 
                    378:     if (namep == NULL)
                    379:        return;
                    380: 
                    381: /* DON'T want to use oneof_stg() here; need to find the right common name
                    382:    */
                    383: 
                    384:     if (namep->vstg == STGCOMMON && !namep->vcommequiv && !usedefsforcommon) {
                    385:        comm = &extsymtab[namep->vardesc.varno];
                    386:        extern_out(fp, comm);
                    387:        nice_printf(fp, "%d.", comm->curno);
                    388:     } /* if namep -> vstg == STGCOMMON */
                    389: 
                    390:     if (namep->vprocclass == PTHISPROC && namep->vtype != TYSUBR)
                    391:        nice_printf(fp, xretslot[namep->vtype]->user.ident);
                    392:     else
                    393:        nice_printf (fp, "%s", namep->cvarname);
                    394: } /* out_name */
                    395: 
                    396: 
                    397: static char *Longfmt = "%ld";
                    398: 
                    399: #define cpd(n) cp->vstg ? cp->Const.cds[n] : dtos(cp->Const.cd[n])
                    400: 
                    401: void out_const(fp, cp)
                    402:  FILE *fp;
                    403:  register Constp cp;
                    404: {
                    405:     static char real_buf[50], imag_buf[50];
                    406:     unsigned int k;
                    407:     int type = cp->vtype;
                    408: 
                    409:     switch (type) {
                    410:        case TYINT1:
                    411:         case TYSHORT:
                    412:            nice_printf (fp, "%ld", cp->Const.ci);      /* don't cast ci! */
                    413:            break;
                    414:        case TYLONG:
                    415: #ifdef TYQUAD
                    416:        case TYQUAD:
                    417: #endif
                    418:            nice_printf (fp, Longfmt, cp->Const.ci);    /* don't cast ci! */
                    419:            break;
                    420:        case TYREAL:
                    421:            nice_printf(fp, "%s", flconst(real_buf, cpd(0)));
                    422:            break;
                    423:        case TYDREAL:
                    424:            nice_printf(fp, "%s", cpd(0));
                    425:            break;
                    426:        case TYCOMPLEX:
                    427:            nice_printf(fp, cm_fmt_string, flconst(real_buf, cpd(0)),
                    428:                        flconst(imag_buf, cpd(1)));
                    429:            break;
                    430:        case TYDCOMPLEX:
                    431:            nice_printf(fp, dcm_fmt_string, cpd(0), cpd(1));
                    432:            break;
                    433:        case TYLOGICAL1:
                    434:        case TYLOGICAL2:
                    435:        case TYLOGICAL:
                    436:            nice_printf (fp, "%s", cp->Const.ci ? "TRUE_" : "FALSE_");
                    437:            break;
                    438:        case TYCHAR: {
                    439:            char *c = cp->Const.ccp, *ce;
                    440: 
                    441:            if (c == NULL) {
                    442:                nice_printf (fp, "\"\"");
                    443:                break;
                    444:            } /* if c == NULL */
                    445: 
                    446:            nice_printf (fp, "\"");
                    447:            ce = c + cp->vleng->constblock.Const.ci;
                    448:            while(c < ce) {
                    449:                k = *(unsigned char *)c++;
                    450:                nice_printf(fp, str_fmt[k], k);
                    451:                }
                    452:            for(k = cp->Const.ccp1.blanks; k > 0; k--)
                    453:                nice_printf(fp, " ");
                    454:            nice_printf (fp, "\"");
                    455:            break;
                    456:        } /* case TYCHAR */
                    457:        default:
                    458:            erri ("out_const:  bad type '%d'", (int) type);
                    459:            break;
                    460:     } /* switch */
                    461: 
                    462: } /* out_const */
                    463: #undef cpd
                    464: 
                    465:  static void
                    466: out_args(fp, ep) FILE *fp; expptr ep;
                    467: {
                    468:        chainp arglist;
                    469: 
                    470:        if(ep->tag != TLIST)
                    471:                badtag("out_args", ep->tag);
                    472:        for(arglist = ep->listblock.listp;;) {
                    473:                expr_out(fp, (expptr)arglist->datap);
                    474:                arglist->datap = 0;
                    475:                if (!(arglist = arglist->nextp))
                    476:                        break;
                    477:                nice_printf(fp, ", ");
                    478:                }
                    479:        }
                    480: 
                    481: 
                    482: /* out_addr -- this routine isn't local because it is called by the
                    483:    system-generated identifier printing routines */
                    484: 
                    485: void out_addr (fp, addrp)
                    486: FILE *fp;
                    487: struct Addrblock *addrp;
                    488: {
                    489:        extern Extsym *extsymtab;
                    490:        int was_array = 0;
                    491:        char *s;
                    492: 
                    493: 
                    494:        if (addrp == NULL)
                    495:                return;
                    496:        if (doin_setbound
                    497:                        && addrp->vstg == STGARG
                    498:                        && addrp->vtype != TYCHAR
                    499:                        && ISICON(addrp->memoffset)
                    500:                        && !addrp->memoffset->constblock.Const.ci)
                    501:                nice_printf(fp, "*");
                    502: 
                    503:        switch (addrp -> uname_tag) {
                    504:            case UNAM_REF:
                    505:                nice_printf(fp, "%s_%s(", addrp->user.name->cvarname,
                    506:                        addrp->cmplx_sub ? "subscr" : "ref");
                    507:                out_args(fp, addrp->memoffset);
                    508:                nice_printf(fp, ")");
                    509:                return;
                    510:            case UNAM_NAME:
                    511:                out_name (fp, addrp -> user.name);
                    512:                break;
                    513:            case UNAM_IDENT:
                    514:                if (*(s = addrp->user.ident) == ' ') {
                    515:                        if (multitype)
                    516:                                nice_printf(fp, "%s",
                    517:                                        xretslot[addrp->vtype]->user.ident);
                    518:                        else
                    519:                                nice_printf(fp, "%s", s+1);
                    520:                        }
                    521:                else {
                    522:                        nice_printf(fp, "%s", s);
                    523:                        }
                    524:                break;
                    525:            case UNAM_CHARP:
                    526:                nice_printf(fp, "%s", addrp->user.Charp);
                    527:                break;
                    528:            case UNAM_EXTERN:
                    529:                extern_out (fp, &extsymtab[addrp -> memno]);
                    530:                break;
                    531:            case UNAM_CONST:
                    532:                switch(addrp->vstg) {
                    533:                        case STGCONST:
                    534:                                out_const(fp, (Constp)addrp);
                    535:                                break;
                    536:                        case STGMEMNO:
                    537:                                output_literal (fp, (int)addrp->memno,
                    538:                                        (Constp)addrp);
                    539:                                break;
                    540:                        default:
                    541:                        Fatal("unexpected vstg in out_addr");
                    542:                        }
                    543:                break;
                    544:            case UNAM_UNKNOWN:
                    545:            default:
                    546:                nice_printf (fp, "Unknown Addrp");
                    547:                break;
                    548:        } /* switch */
                    549: 
                    550: /* It's okay to just throw in the brackets here because they have a
                    551:    precedence level of 15, the highest value.  */
                    552: 
                    553:     if ((addrp->uname_tag == UNAM_NAME && addrp->user.name->vdim
                    554:                        || addrp->ntempelt > 1 || addrp->isarray)
                    555:        && addrp->vtype != TYCHAR) {
                    556:        expptr offset;
                    557: 
                    558:        was_array = 1;
                    559: 
                    560:        offset = addrp -> memoffset;
                    561:        addrp->memoffset = 0;
                    562:        if (ONEOF(addrp->vstg, M(STGCOMMON)|M(STGEQUIV))
                    563:                && addrp -> uname_tag == UNAM_NAME
                    564:                && !addrp->skip_offset)
                    565:            offset = mkexpr (OPMINUS, offset, mkintcon (
                    566:                    addrp -> user.name -> voffset));
                    567: 
                    568:        nice_printf (fp, "[");
                    569: 
                    570:        offset = mkexpr (OPSLASH, offset,
                    571:                ICON (typesize[addrp -> vtype] * (addrp -> Field ? 2 : 1)));
                    572:        expr_out (fp, offset);
                    573:        nice_printf (fp, "]");
                    574:        }
                    575: 
                    576: /* Check for structure field reference */
                    577: 
                    578:     if (addrp -> Field && addrp -> uname_tag != UNAM_CONST &&
                    579:            addrp -> uname_tag != UNAM_UNKNOWN) {
                    580:        if (oneof_stg((addrp -> uname_tag == UNAM_NAME ? addrp -> user.name :
                    581:                (Namep) NULL), addrp -> vstg, M(STGARG)|M(STGEQUIV))
                    582:                && !was_array && (addrp->vclass != CLPROC || !multitype))
                    583:            nice_printf (fp, "->%s", addrp -> Field);
                    584:        else
                    585:            nice_printf (fp, ".%s", addrp -> Field);
                    586:     } /* if */
                    587: 
                    588: /* Check for character subscripting */
                    589: 
                    590:     if (addrp->vtype == TYCHAR &&
                    591:            (addrp->vclass != CLPROC || addrp->uname_tag == UNAM_NAME
                    592:                        && addrp->user.name->vprocclass == PTHISPROC) &&
                    593:            addrp -> memoffset &&
                    594:            (addrp -> uname_tag != UNAM_NAME ||
                    595:             addrp -> user.name -> vtype == TYCHAR) &&
                    596:            (!ISICON (addrp -> memoffset) ||
                    597:             (addrp -> memoffset -> constblock.Const.ci))) {
                    598: 
                    599:        int use_paren = 0;
                    600:        expptr e = addrp -> memoffset;
                    601: 
                    602:        if (!e)
                    603:                return;
                    604:        addrp->memoffset = 0;
                    605: 
                    606:        if (ONEOF(addrp->vstg, M(STGCOMMON)|M(STGEQUIV))
                    607:         && addrp -> uname_tag == UNAM_NAME) {
                    608:            e = mkexpr (OPMINUS, e, mkintcon (addrp -> user.name -> voffset));
                    609: 
                    610: /* mkexpr will simplify it to zero if possible */
                    611:            if (e->tag == TCONST && e->constblock.Const.ci == 0)
                    612:                return;
                    613:        } /* if addrp -> vstg == STGCOMMON */
                    614: 
                    615: /* In the worst case, parentheses might be needed OUTSIDE the expression,
                    616:    too.  But since I think this subscripting can only appear as a
                    617:    parameter in a procedure call, I don't think outside parens will ever
                    618:    be needed.  INSIDE parens are handled below */
                    619: 
                    620:        nice_printf (fp, " + ");
                    621:        if (e -> tag == TEXPR) {
                    622:            int arg_prec = op_precedence (e -> exprblock.opcode);
                    623:            int prec = op_precedence (OPPLUS);
                    624:            use_paren = arg_prec && (arg_prec < prec || (arg_prec == prec &&
                    625:                    is_left_assoc (OPPLUS)));
                    626:        } /* if e -> tag == TEXPR */
                    627:        if (use_paren) nice_printf (fp, "(");
                    628:        expr_out (fp, e);
                    629:        if (use_paren) nice_printf (fp, ")");
                    630:     } /* if */
                    631: } /* out_addr */
                    632: 
                    633: 
                    634: static void output_literal (fp, memno, cp)
                    635:  FILE *fp;
                    636:  int memno;
                    637:  Constp cp;
                    638: {
                    639:     struct Literal *litp, *lastlit;
                    640:     extern char *lit_name ();
                    641: 
                    642:     lastlit = litpool + nliterals;
                    643: 
                    644:     for (litp = litpool; litp < lastlit; litp++) {
                    645:        if (litp -> litnum == memno)
                    646:            break;
                    647:     } /* for litp */
                    648: 
                    649:     if (litp >= lastlit)
                    650:        out_const (fp, cp);
                    651:     else {
                    652:        nice_printf (fp, "%s", lit_name (litp));
                    653:        litp->lituse++;
                    654:        }
                    655: } /* output_literal */
                    656: 
                    657: 
                    658: static void output_prim (fp, primp)
                    659: FILE *fp;
                    660: struct Primblock *primp;
                    661: {
                    662:     if (primp == NULL)
                    663:        return;
                    664: 
                    665:     out_name (fp, primp -> namep);
                    666:     if (primp -> argsp)
                    667:        output_arg_list (fp, primp -> argsp);
                    668: 
                    669:     if (primp -> fcharp != (expptr) NULL || primp -> lcharp != (expptr) NULL)
                    670:        nice_printf (fp, "Sorry, no substrings yet");
                    671: }
                    672: 
                    673: 
                    674: 
                    675: static void output_arg_list (fp, listp)
                    676: FILE *fp;
                    677: struct Listblock *listp;
                    678: {
                    679:     chainp arg_list;
                    680: 
                    681:     if (listp == (struct Listblock *) NULL || listp -> listp == (chainp) NULL)
                    682:        return;
                    683: 
                    684:     nice_printf (fp, "(");
                    685: 
                    686:     for (arg_list = listp -> listp; arg_list; arg_list = arg_list -> nextp) {
                    687:        expr_out (fp, (expptr) arg_list -> datap);
                    688:        if (arg_list -> nextp != (chainp) NULL)
                    689: 
                    690: /* Might want to add a hook in here to accomodate the style setting which
                    691:    wants spaces after commas */
                    692: 
                    693:            nice_printf (fp, ",");
                    694:     } /* for arg_list */
                    695: 
                    696:     nice_printf (fp, ")");
                    697: } /* output_arg_list */
                    698: 
                    699: 
                    700: 
                    701: static void output_unary (fp, e)
                    702: FILE *fp;
                    703: struct Exprblock *e;
                    704: {
                    705:     if (e == NULL)
                    706:        return;
                    707: 
                    708:     switch (e -> opcode) {
                    709:         case OPNEG:
                    710:                if (e->vtype == TYREAL && forcedouble) {
                    711:                        e->opcode = OPNEG_KLUDGE;
                    712:                        output_binary(fp,e);
                    713:                        e->opcode = OPNEG;
                    714:                        break;
                    715:                        }
                    716:        case OPNEG1:
                    717:        case OPNOT:
                    718:        case OPABS:
                    719:        case OPBITNOT:
                    720:        case OPWHATSIN:
                    721:        case OPPREINC:
                    722:        case OPPREDEC:
                    723:        case OPADDR:
                    724:        case OPIDENTITY:
                    725:        case OPCHARCAST:
                    726:        case OPDABS:
                    727:            output_binary (fp, e);
                    728:            break;
                    729:        case OPCALL:
                    730:        case OPCCALL:
                    731:            nice_printf (fp, "Sorry, no OPCALL yet");
                    732:            break;
                    733:        default:
                    734:            erri ("output_unary: bad opcode", (int) e -> opcode);
                    735:            break;
                    736:     } /* switch */
                    737: } /* output_unary */
                    738: 
                    739: 
                    740:  static char *
                    741: findconst(m)
                    742:  register long m;
                    743: {
                    744:        register struct Literal *litp, *litpe;
                    745: 
                    746:        litp = litpool;
                    747:        for(litpe = litp + nliterals; litp < litpe; litp++)
                    748:                if (litp->litnum ==  m)
                    749:                        return litp->cds[0];
                    750:        Fatal("findconst failure!");
                    751:        return 0;
                    752:        }
                    753: 
                    754:  static int
                    755: opconv_fudge(fp,e)
                    756:  FILE *fp;
                    757:  struct Exprblock *e;
                    758: {
                    759:        /* special handling for ichar and character*1 */
                    760:        register expptr lp;
                    761:        register union Expression *Offset;
                    762:        register char *cp;
                    763:        int lt;
                    764:        char buf[8];
                    765:        unsigned int k;
                    766:        Namep np;
                    767: 
                    768:        if (!(lp = e->leftp))   /* possible with erroneous Fortran */
                    769:                return 1;
                    770:        lt = lp->headblock.vtype;
                    771:        if (lt == TYCHAR) {
                    772:                switch(lp->tag) {
                    773:                        case TNAME:
                    774:                                nice_printf(fp, "*");
                    775:                                out_name(fp, (Namep)lp);
                    776:                                return 1;
                    777:                        case TCONST:
                    778:  tconst:
                    779:                                cp = lp->constblock.Const.ccp;
                    780:  tconst1:
                    781:                                k = *(unsigned char *)cp;
                    782:                                sprintf(buf, chr_fmt[k], k);
                    783:                                nice_printf(fp, "'%s'", buf);
                    784:                                return 1;
                    785:                        case TADDR:
                    786:                                switch(lp->addrblock.vstg) {
                    787:                                    case STGMEMNO:
                    788:                                        if (halign && e->vtype != TYCHAR) {
                    789:                                                nice_printf(fp, "*(%s *)",
                    790:                                                        c_type_decl(e->vtype));
                    791:                                                expr_out(fp, lp);
                    792:                                                return 1;
                    793:                                                }
                    794:                                        cp = findconst(lp->addrblock.memno);
                    795:                                        goto tconst1;
                    796:                                    case STGCONST:
                    797:                                        goto tconst;
                    798:                                    }
                    799:                                lp->addrblock.vtype = tyint;
                    800:                                Offset = lp->addrblock.memoffset;
                    801:                                switch(lp->addrblock.uname_tag) {
                    802:                                  case UNAM_REF:
                    803:                                        nice_printf(fp, "*");
                    804:                                        return 0;
                    805:                                  case UNAM_NAME:
                    806:                                        np = lp->addrblock.user.name;
                    807:                                        if (ONEOF(np->vstg,
                    808:                                            M(STGCOMMON)|M(STGEQUIV)))
                    809:                                                Offset = mkexpr(OPMINUS, Offset,
                    810:                                                        ICON(np->voffset));
                    811:                                        }
                    812:                                lp->addrblock.memoffset = Offset ?
                    813:                                        mkexpr(OPSTAR, Offset,
                    814:                                                ICON(typesize[tyint]))
                    815:                                        : ICON(0);
                    816:                                lp->addrblock.isarray = 1;
                    817:                                /* STGCOMMON or STGEQUIV would cause */
                    818:                                /* voffset to be added in a second time */
                    819:                                lp->addrblock.vstg = STGUNKNOWN;
                    820:                                break;
                    821:                        default:
                    822:                                badtag("opconv_fudge", lp->tag);
                    823:                        }
                    824:                }
                    825:        if (lt != e->vtype)
                    826:                nice_printf(fp, "(%s) ",
                    827:                        c_type_decl(e->vtype, 0));
                    828:        return 0;
                    829:        }
                    830: 
                    831: 
                    832: static void output_binary (fp, e)
                    833: FILE *fp;
                    834: struct Exprblock *e;
                    835: {
                    836:     char *format;
                    837:     extern table_entry opcode_table[];
                    838:     int prec;
                    839: 
                    840:     if (e == NULL || e -> tag != TEXPR)
                    841:        return;
                    842: 
                    843: /* Instead of writing a huge switch, I've incorporated the output format
                    844:    into a table.  Things like "%l" and "%r" stand for the left and
                    845:    right subexpressions.  This should allow both prefix and infix
                    846:    functions to be specified (e.g. "(%l * %r", "z_div (%l, %r").  Of
                    847:    course, I should REALLY think out the ramifications of writing out
                    848:    straight text, as opposed to some intermediate format, which could
                    849:    figure out and optimize on the the number of required blanks (we don't
                    850:    want "x - (-y)" to become "x --y", for example).  Special cases (such as
                    851:    incomplete implementations) could still be implemented as part of the
                    852:    switch, they will just have some dummy value instead of the string
                    853:    pattern.  Another difficulty is the fact that the complex functions
                    854:    will differ from the integer and real ones */
                    855: 
                    856: /* Handle a special case.  We don't want to output "x + - 4", or "y - - 3"
                    857: */
                    858:     if ((e -> opcode == OPPLUS || e -> opcode == OPMINUS) &&
                    859:            e -> rightp && e -> rightp -> tag == TCONST &&
                    860:            isnegative_const (&(e -> rightp -> constblock)) &&
                    861:            is_negatable (&(e -> rightp -> constblock))) {
                    862: 
                    863:        e -> opcode = (e -> opcode == OPPLUS) ? OPMINUS : OPPLUS;
                    864:        negate_const (&(e -> rightp -> constblock));
                    865:     } /* if e -> opcode == PLUS or MINUS */
                    866: 
                    867:     prec = op_precedence (e -> opcode);
                    868:     format = op_format (e -> opcode);
                    869: 
                    870:     if (format != SPECIAL_FMT) {
                    871:        while (*format) {
                    872:            if (*format == '%') {
                    873:                int arg_prec, use_paren = 0;
                    874:                expptr lp, rp;
                    875: 
                    876:                switch (*(format + 1)) {
                    877:                    case 'l':
                    878:                        lp = e->leftp;
                    879:                        if (lp && lp->tag == TEXPR) {
                    880:                            arg_prec = op_precedence(lp->exprblock.opcode);
                    881: 
                    882:                            use_paren = arg_prec &&
                    883:                                (arg_prec < prec || (arg_prec == prec &&
                    884:                                    is_right_assoc (prec)));
                    885:                        } /* if e -> leftp */
                    886:                        if (e->opcode == OPCONV && opconv_fudge(fp,e))
                    887:                                break;
                    888:                        if (use_paren)
                    889:                            nice_printf (fp, "(");
                    890:                        expr_out(fp, lp);
                    891:                        if (use_paren)
                    892:                            nice_printf (fp, ")");
                    893:                        break;
                    894:                    case 'r':
                    895:                        rp = e->rightp;
                    896:                        if (rp && rp->tag == TEXPR) {
                    897:                            arg_prec = op_precedence(rp->exprblock.opcode);
                    898: 
                    899:                            use_paren = arg_prec &&
                    900:                                (arg_prec < prec || (arg_prec == prec &&
                    901:                                    is_left_assoc (prec)));
                    902:                            use_paren = use_paren ||
                    903:                                (rp->exprblock.opcode == OPNEG
                    904:                                && prec >= op_precedence(OPMINUS));
                    905:                        } /* if e -> rightp */
                    906:                        if (use_paren)
                    907:                            nice_printf (fp, "(");
                    908:                        expr_out(fp, rp);
                    909:                        if (use_paren)
                    910:                            nice_printf (fp, ")");
                    911:                        break;
                    912:                    case '\0':
                    913:                    case '%':
                    914:                        nice_printf (fp, "%%");
                    915:                        break;
                    916:                    default:
                    917:                        erri ("output_binary: format err: '%%%c' illegal",
                    918:                                (int) *(format + 1));
                    919:                        break;
                    920:                } /* switch */
                    921:                format += 2;
                    922:            } else
                    923:                nice_printf (fp, "%c", *format++);
                    924:        } /* while *format */
                    925:     } else {
                    926: 
                    927: /* Handle Special cases of formatting */
                    928: 
                    929:        switch (e -> opcode) {
                    930:                case OPCCALL:
                    931:                case OPCALL:
                    932:                        out_call (fp, (int) e -> opcode, e -> vtype,
                    933:                                        e -> vleng, e -> leftp, e -> rightp);
                    934:                        break;
                    935: 
                    936:                case OPCOMMA_ARG:
                    937:                        doin_setbound = 1;
                    938:                        nice_printf(fp, "(");
                    939:                        expr_out(fp, e->leftp);
                    940:                        nice_printf(fp, ", &");
                    941:                        doin_setbound = 0;
                    942:                        expr_out(fp, e->rightp);
                    943:                        nice_printf(fp, ")");
                    944:                        break;
                    945: 
                    946:                case OPADDR:
                    947:                default:
                    948:                        nice_printf (fp, "Sorry, can't format OPCODE '%d'",
                    949:                                e -> opcode);
                    950:                        break;
                    951:                }
                    952: 
                    953:     } /* else */
                    954: } /* output_binary */
                    955: 
                    956: 
                    957: out_call (outfile, op, ftype, len, name, args)
                    958: FILE *outfile;
                    959: int op, ftype;
                    960: expptr len, name, args;
                    961: {
                    962:     chainp arglist;            /* Pointer to any actual arguments */
                    963:     chainp cp;                 /* Iterator over argument lists */
                    964:     Addrp ret_val = (Addrp) NULL;
                    965:                                /* Function return value buffer, if any is
                    966:                                   required */
                    967:     int byvalue;               /* True iff we're calling a C library
                    968:                                   routine */
                    969:     int done_once;             /* Used for writing commas to   outfile   */
                    970:     int narg, t;
                    971:     register expptr q;
                    972:     long L;
                    973:     Argtypes *at;
                    974:     Atype *A, *Ac;
                    975:     Namep np;
                    976:     extern int forcereal;
                    977: 
                    978: /* Don't use addresses if we're calling a C function */
                    979: 
                    980:     byvalue = op == OPCCALL;
                    981: 
                    982:     if (args)
                    983:        arglist = args -> listblock.listp;
                    984:     else
                    985:        arglist = CHNULL;
                    986: 
                    987: /* If this is a CHARACTER function, the first argument is the result */
                    988: 
                    989:     if (ftype == TYCHAR)
                    990:        if (ISICON (len)) {
                    991:            ret_val = (Addrp) (arglist -> datap);
                    992:            arglist = arglist -> nextp;
                    993:        } else {
                    994:            err ("adjustable character function");
                    995:            return;
                    996:        } /* else */
                    997: 
                    998: /* If this is a COMPLEX function, the first argument is the result */
                    999: 
                   1000:     else if (ISCOMPLEX (ftype)) {
                   1001:        ret_val = (Addrp) (arglist -> datap);
                   1002:        arglist = arglist -> nextp;
                   1003:     } /* if ISCOMPLEX */
                   1004: 
                   1005: /* Now we can actually start to write out the function invocation */
                   1006: 
                   1007:     if (ftype == TYREAL && forcereal)
                   1008:        nice_printf(outfile, "(real)");
                   1009:     if (name -> tag == TEXPR && name -> exprblock.opcode == OPWHATSIN) {
                   1010:        nice_printf (outfile, "(");
                   1011:        np = (Namep)name->exprblock.leftp; /*expr_out will free name */
                   1012:        expr_out (outfile, name);
                   1013:        nice_printf (outfile, ")");
                   1014:        }
                   1015:     else {
                   1016:        np = (Namep)name;
                   1017:        expr_out(outfile, name);
                   1018:        }
                   1019: 
                   1020:     /* prepare to cast procedure parameters -- set A if we know how */
                   1021: 
                   1022:     A = Ac = 0;
                   1023:     if (np->tag == TNAME && (at = np->arginfo)) {
                   1024:        if (at->nargs > 0)
                   1025:                A = at->atypes;
                   1026:        if (Ansi && (at->defined || at->nargs > 0))
                   1027:                Ac = at->atypes;
                   1028:        }
                   1029: 
                   1030:     nice_printf(outfile, "(");
                   1031: 
                   1032:     if (ret_val) {
                   1033:        if (ISCOMPLEX (ftype))
                   1034:            nice_printf (outfile, "&");
                   1035:        expr_out (outfile, (expptr) ret_val);
                   1036:        if (Ac)
                   1037:                Ac++;
                   1038: 
                   1039: /* The length of the result of a character function is the second argument */
                   1040: /* It should be in place from putcall(), so we won't touch it explicitly */
                   1041: 
                   1042:     } /* if ret_val */
                   1043:     done_once = ret_val ? TRUE : FALSE;
                   1044: 
                   1045: /* Now run through the named arguments */
                   1046: 
                   1047:     narg = -1;
                   1048:     for (cp = arglist; cp; cp = cp -> nextp, done_once = TRUE) {
                   1049: 
                   1050:        if (done_once)
                   1051:            nice_printf (outfile, ", ");
                   1052:        narg++;
                   1053: 
                   1054:        if (!( q = (expptr)cp->datap) )
                   1055:                continue;
                   1056: 
                   1057:        if (q->tag == TADDR) {
                   1058:                if (q->addrblock.vtype > TYERROR) {
                   1059:                        /* I/O block */
                   1060:                        nice_printf(outfile, "&%s", q->addrblock.user.ident);
                   1061:                        continue;
                   1062:                        }
                   1063:                if (!byvalue && q->addrblock.isarray
                   1064:                && q->addrblock.vtype != TYCHAR
                   1065:                && q->addrblock.memoffset->tag == TCONST) {
                   1066: 
                   1067:                        /* check for 0 offset -- after */
                   1068:                        /* correcting for equivalence. */
                   1069:                        L = q->addrblock.memoffset->constblock.Const.ci;
                   1070:                        if (ONEOF(q->addrblock.vstg, M(STGCOMMON)|M(STGEQUIV))
                   1071:                                        && q->addrblock.uname_tag == UNAM_NAME)
                   1072:                                L -= q->addrblock.user.name->voffset;
                   1073:                        if (L)
                   1074:                                goto skip_deref;
                   1075: 
                   1076:                        if (Ac && narg < at->dnargs
                   1077:                         && q->headblock.vtype != (t = Ac[narg].type)
                   1078:                         && t > TYADDR && t < TYSUBR)
                   1079:                                nice_printf(outfile, "(%s*)", typename[t]);
                   1080: 
                   1081:                        /* &x[0] == x */
                   1082:                        /* This also prevents &sizeof(doublereal)[0] */
                   1083: 
                   1084:                        switch(q->addrblock.uname_tag) {
                   1085:                            case UNAM_NAME:
                   1086:                                out_name(outfile, q->addrblock.user.name);
                   1087:                                continue;
                   1088:                            case UNAM_IDENT:
                   1089:                                nice_printf(outfile, "%s",
                   1090:                                        q->addrblock.user.ident);
                   1091:                                continue;
                   1092:                            case UNAM_CHARP:
                   1093:                                nice_printf(outfile, "%s",
                   1094:                                        q->addrblock.user.Charp);
                   1095:                                continue;
                   1096:                            case UNAM_EXTERN:
                   1097:                                extern_out(outfile,
                   1098:                                        &extsymtab[q->addrblock.memno]);
                   1099:                                continue;
                   1100:                            }
                   1101:                        }
                   1102:                }
                   1103: 
                   1104: /* Skip over the dereferencing operator generated only for the
                   1105:    intermediate file */
                   1106:  skip_deref:
                   1107:        if (q -> tag == TEXPR && q -> exprblock.opcode == OPWHATSIN)
                   1108:            q = q -> exprblock.leftp;
                   1109: 
                   1110:        if (q->headblock.vclass == CLPROC) {
                   1111:            if (Castargs && (q->tag != TNAME
                   1112:                                || q->nameblock.vprocclass != PTHISPROC))
                   1113:                {
                   1114:                if (A && (t = A[narg].type) >= 200)
                   1115:                        t %= 100;
                   1116:                else {
                   1117:                        t = q->headblock.vtype;
                   1118:                        if (q->tag == TNAME && q->nameblock.vimpltype)
                   1119:                                t = TYUNKNOWN;
                   1120:                        }
                   1121:                nice_printf(outfile, "(%s)", usedcasts[t] = casttypes[t]);
                   1122:                }
                   1123:            }
                   1124:        else if (Ac && narg < at->dnargs
                   1125:                && q->headblock.vtype != (t = Ac[narg].type)
                   1126:                && t > TYADDR && t < TYSUBR)
                   1127:                nice_printf(outfile, "(%s*)", typename[t]);
                   1128: 
                   1129:        if ((q -> tag == TADDR || q-> tag == TNAME) &&
                   1130:                (byvalue || q -> headblock.vstg != STGREG)) {
                   1131:            if (q -> headblock.vtype != TYCHAR)
                   1132:              if (byvalue) {
                   1133: 
                   1134:                if (q -> tag == TADDR &&
                   1135:                        q -> addrblock.uname_tag == UNAM_NAME &&
                   1136:                        ! q -> addrblock.user.name -> vdim &&
                   1137:                        oneof_stg(q -> addrblock.user.name, q -> addrblock.vstg,
                   1138:                                        M(STGARG)|M(STGEQUIV)) &&
                   1139:                        ! ISCOMPLEX(q->addrblock.user.name->vtype))
                   1140:                    nice_printf (outfile, "*");
                   1141:                else if (q -> tag == TNAME
                   1142:                        && oneof_stg(&q->nameblock, q -> nameblock.vstg,
                   1143:                                M(STGARG)|M(STGEQUIV))
                   1144:                        && !(q -> nameblock.vdim))
                   1145:                    nice_printf (outfile, "*");
                   1146: 
                   1147:              } else {
                   1148:                expptr memoffset;
                   1149: 
                   1150:                if (q->tag == TADDR &&
                   1151:                        !ONEOF (q -> addrblock.vstg, M(STGEXT)|M(STGLENG))
                   1152:                        && (
                   1153:                        ONEOF(q->addrblock.vstg,
                   1154:                                M(STGCOMMON)|M(STGEQUIV)|M(STGMEMNO))
                   1155:                        || ((memoffset = q->addrblock.memoffset)
                   1156:                                && (!ISICON(memoffset)
                   1157:                                || memoffset->constblock.Const.ci)))
                   1158:                        || ONEOF(q->addrblock.vstg,
                   1159:                                        M(STGINIT)|M(STGAUTO)|M(STGBSS))
                   1160:                                && !q->addrblock.isarray)
                   1161:                    nice_printf (outfile, "&");
                   1162:                else if (q -> tag == TNAME
                   1163:                        && !oneof_stg(&q->nameblock, q -> nameblock.vstg,
                   1164:                                M(STGARG)|M(STGEXT)|M(STGEQUIV)))
                   1165:                    nice_printf (outfile, "&");
                   1166:            } /* else */
                   1167: 
                   1168:            expr_out (outfile, q);
                   1169:        } /* if q -> tag == TADDR || q -> tag == TNAME */
                   1170: 
                   1171: /* Might be a Constant expression, e.g. string length, character constants */
                   1172: 
                   1173:        else if (q -> tag == TCONST) {
                   1174:            if (tyioint == TYLONG)
                   1175:                Longfmt = "%ldL";
                   1176:            out_const(outfile, &q->constblock);
                   1177:            Longfmt = "%ld";
                   1178:            }
                   1179: 
                   1180: /* Must be some other kind of expression, or register var, or constant.
                   1181:    In particular, this is likely to be a temporary variable assignment
                   1182:    which was generated in p1put_call */
                   1183: 
                   1184:        else if (!ISCOMPLEX (q -> headblock.vtype) && !ISCHAR (q)){
                   1185:            int use_paren = q -> tag == TEXPR &&
                   1186:                    op_precedence (q -> exprblock.opcode) <=
                   1187:                    op_precedence (OPCOMMA);
                   1188: 
                   1189:            if (use_paren) nice_printf (outfile, "(");
                   1190:            expr_out (outfile, q);
                   1191:            if (use_paren) nice_printf (outfile, ")");
                   1192:        } /* if !ISCOMPLEX */
                   1193:        else
                   1194:            err ("out_call:  unknown parameter");
                   1195: 
                   1196:     } /* for (cp = arglist */
                   1197: 
                   1198:     if (arglist)
                   1199:        frchain (&arglist);
                   1200: 
                   1201:     nice_printf (outfile, ")");
                   1202: 
                   1203: } /* out_call */
                   1204: 
                   1205: 
                   1206:  char *
                   1207: flconst(buf, x)
                   1208:  char *buf, *x;
                   1209: {
                   1210:        sprintf(buf, fl_fmt_string, x);
                   1211:        return buf;
                   1212:        }
                   1213: 
                   1214:  char *
                   1215: dtos(x)
                   1216:  double x;
                   1217: {
                   1218:        static char buf[64];
                   1219:        sprintf(buf, db_fmt_string, x);
                   1220:        return buf;
                   1221:        }
                   1222: 
                   1223: char tr_tab[Table_size];
                   1224: 
                   1225: /* out_init -- Initialize the data structures used by the routines in
                   1226:    output.c.  These structures include the output format to be used for
                   1227:    Float, Double, Complex, and Double Complex constants. */
                   1228: 
                   1229: void out_init ()
                   1230: {
                   1231:     extern int tab_size;
                   1232:     register char *s;
                   1233: 
                   1234:     s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+-.";
                   1235:     while(*s)
                   1236:        tr_tab[*s++] = 3;
                   1237:     tr_tab['>'] = 1;
                   1238: 
                   1239:        opeqable[OPPLUS] = 1;
                   1240:        opeqable[OPMINUS] = 1;
                   1241:        opeqable[OPSTAR] = 1;
                   1242:        opeqable[OPSLASH] = 1;
                   1243:        opeqable[OPMOD] = 1;
                   1244:        opeqable[OPLSHIFT] = 1;
                   1245:        opeqable[OPBITAND] = 1;
                   1246:        opeqable[OPBITXOR] = 1;
                   1247:        opeqable[OPBITOR ] = 1;
                   1248: 
                   1249: 
                   1250: /* Set the output format for both types of floating point constants */
                   1251: 
                   1252:     if (fl_fmt_string == NULL || *fl_fmt_string == '\0')
                   1253:        fl_fmt_string = Ansi == 1 ? "%sf" : "(float)%s";
                   1254: 
                   1255:     if (db_fmt_string == NULL || *db_fmt_string == '\0')
                   1256:        db_fmt_string = "%.17g";
                   1257: 
                   1258: /* Set the output format for both types of complex constants.  They will
                   1259:    have string parameters rather than float or double so that the decimal
                   1260:    point may be added to the strings generated by the {db,fl}_fmt_string
                   1261:    formats above */
                   1262: 
                   1263:     if (cm_fmt_string == NULL || *cm_fmt_string == '\0') {
                   1264:        cm_fmt_string = "{%s,%s}";
                   1265:     } /* if cm_fmt_string == NULL */
                   1266: 
                   1267:     if (dcm_fmt_string == NULL || *dcm_fmt_string == '\0') {
                   1268:        dcm_fmt_string = "{%s,%s}";
                   1269:     } /* if dcm_fmt_string == NULL */
                   1270: 
                   1271:     tab_size = 4;
                   1272: } /* out_init */
                   1273: 
                   1274: 
                   1275: void extern_out (fp, extsym)
                   1276: FILE *fp;
                   1277: Extsym *extsym;
                   1278: {
                   1279:     if (extsym == (Extsym *) NULL)
                   1280:        return;
                   1281: 
                   1282:     nice_printf (fp, "%s", extsym->cextname);
                   1283: 
                   1284: } /* extern_out */
                   1285: 
                   1286: 
                   1287: 
                   1288: static void output_list (fp, listp)
                   1289: FILE *fp;
                   1290: struct Listblock *listp;
                   1291: {
                   1292:     int did_one = 0;
                   1293:     chainp elts;
                   1294: 
                   1295:     nice_printf (fp, "(");
                   1296:     if (listp)
                   1297:        for (elts = listp -> listp; elts; elts = elts -> nextp) {
                   1298:            if (elts -> datap) {
                   1299:                if (did_one)
                   1300:                    nice_printf (fp, ", ");
                   1301:                expr_out (fp, (expptr) elts -> datap);
                   1302:                did_one = 1;
                   1303:            } /* if elts -> datap */
                   1304:        } /* for elts */
                   1305:     nice_printf (fp, ")");
                   1306: } /* output_list */
                   1307: 
                   1308: 
                   1309: void out_asgoto (outfile, expr)
                   1310: FILE *outfile;
                   1311: expptr expr;
                   1312: {
                   1313:     char *user_label();
                   1314:     chainp value;
                   1315:     Namep namep;
                   1316:     int k;
                   1317: 
                   1318:     if (expr == (expptr) NULL) {
                   1319:        err ("out_asgoto:  NULL variable expr");
                   1320:        return;
                   1321:     } /* if expr */
                   1322: 
                   1323:     nice_printf (outfile, Ansi ? "switch (" : "switch ((int)"); /*)*/
                   1324:     expr_out (outfile, expr);
                   1325:     nice_printf (outfile, ") {\n");
                   1326:     next_tab (outfile);
                   1327: 
                   1328: /* The initial addrp value will be stored as a namep pointer */
                   1329: 
                   1330:     switch(expr->tag) {
                   1331:        case TNAME:
                   1332:                /* local variable */
                   1333:                namep = &expr->nameblock;
                   1334:                break;
                   1335:        case TEXPR:
                   1336:                if (expr->exprblock.opcode == OPWHATSIN
                   1337:                 && expr->exprblock.leftp->tag == TNAME)
                   1338:                        /* argument */
                   1339:                        namep = &expr->exprblock.leftp->nameblock;
                   1340:                else
                   1341:                        goto bad;
                   1342:                break;
                   1343:        case TADDR:
                   1344:                if (expr->addrblock.uname_tag == UNAM_NAME) {
                   1345:                        /* initialized local variable */
                   1346:                        namep = expr->addrblock.user.name;
                   1347:                        break;
                   1348:                        }
                   1349:        default:
                   1350:  bad:
                   1351:                err("out_asgoto:  bad expr");
                   1352:                return;
                   1353:        }
                   1354: 
                   1355:     for(k = 0, value = namep -> varxptr.assigned_values; value;
                   1356:            value = value->nextp, k++) {
                   1357:        nice_printf (outfile, "case %d: goto %s;\n", k,
                   1358:                user_label((long)value->datap));
                   1359:     } /* for value */
                   1360:     prev_tab (outfile);
                   1361: 
                   1362:     nice_printf (outfile, "}\n");
                   1363: } /* out_asgoto */
                   1364: 
                   1365: void out_if (outfile, expr)
                   1366: FILE *outfile;
                   1367: expptr expr;
                   1368: {
                   1369:     nice_printf (outfile, "if (");
                   1370:     expr_out (outfile, expr);
                   1371:     nice_printf (outfile, ") {\n");
                   1372:     next_tab (outfile);
                   1373: } /* out_if */
                   1374: 
                   1375:  static void
                   1376: output_rbrace(outfile, s)
                   1377:  FILE *outfile;
                   1378:  char *s;
                   1379: {
                   1380:        extern int last_was_label;
                   1381:        register char *fmt;
                   1382: 
                   1383:        if (last_was_label) {
                   1384:                last_was_label = 0;
                   1385:                fmt = ";%s";
                   1386:                }
                   1387:        else
                   1388:                fmt = "%s";
                   1389:        nice_printf(outfile, fmt, s);
                   1390:        }
                   1391: 
                   1392: void out_else (outfile)
                   1393: FILE *outfile;
                   1394: {
                   1395:     prev_tab (outfile);
                   1396:     output_rbrace(outfile, "} else {\n");
                   1397:     next_tab (outfile);
                   1398: } /* out_else */
                   1399: 
                   1400: void elif_out (outfile, expr)
                   1401: FILE *outfile;
                   1402: expptr expr;
                   1403: {
                   1404:     prev_tab (outfile);
                   1405:     output_rbrace(outfile, "} else ");
                   1406:     out_if (outfile, expr);
                   1407: } /* elif_out */
                   1408: 
                   1409: void endif_out (outfile)
                   1410: FILE *outfile;
                   1411: {
                   1412:     prev_tab (outfile);
                   1413:     output_rbrace(outfile, "}\n");
                   1414: } /* endif_out */
                   1415: 
                   1416: void end_else_out (outfile)
                   1417: FILE *outfile;
                   1418: {
                   1419:     prev_tab (outfile);
                   1420:     output_rbrace(outfile, "}\n");
                   1421: } /* end_else_out */
                   1422: 
                   1423: 
                   1424: 
                   1425: void compgoto_out (outfile, index, labels)
                   1426: FILE *outfile;
                   1427: expptr index, labels;
                   1428: {
                   1429:     char *s1, *s2;
                   1430: 
                   1431:     if (index == ENULL)
                   1432:        err ("compgoto_out:  null index for computed goto");
                   1433:     else if (labels && labels -> tag != TLIST)
                   1434:        erri ("compgoto_out:  expected label list, got tag '%d'",
                   1435:                labels -> tag);
                   1436:     else {
                   1437:        extern char *user_label ();
                   1438:        chainp elts;
                   1439:        int i = 1;
                   1440: 
                   1441:        s2 = /*(*/ ") {\n"; /*}*/
                   1442:        if (Ansi)
                   1443:                s1 = "switch ("; /*)*/
                   1444:        else if (index->tag == TNAME || index->tag == TEXPR
                   1445:                                && index->exprblock.opcode == OPWHATSIN)
                   1446:                s1 = "switch ((int)"; /*)*/
                   1447:        else {
                   1448:                s1 = "switch ((int)(";
                   1449:                s2 = ")) {\n"; /*}*/
                   1450:                }
                   1451:        nice_printf(outfile, s1);
                   1452:        expr_out (outfile, index);
                   1453:        nice_printf (outfile, s2);
                   1454:        next_tab (outfile);
                   1455: 
                   1456:        for (elts = labels -> listblock.listp; elts; elts = elts -> nextp, i++) {
                   1457:            if (elts -> datap) {
                   1458:                if (ISICON(((expptr) (elts -> datap))))
                   1459:                    nice_printf (outfile, "case %d:  goto %s;\n", i,
                   1460:                        user_label(((expptr)(elts->datap))->constblock.Const.ci));
                   1461:                else
                   1462:                    err ("compgoto_out:  bad label in label list");
                   1463:            } /* if (elts -> datap) */
                   1464:        } /* for elts */
                   1465:        prev_tab (outfile);
                   1466:        nice_printf (outfile, /*{*/ "}\n");
                   1467:     } /* else */
                   1468: } /* compgoto_out */
                   1469: 
                   1470: 
                   1471: void out_for (outfile, init, test, inc)
                   1472: FILE *outfile;
                   1473: expptr init, test, inc;
                   1474: {
                   1475:     nice_printf (outfile, "for (");
                   1476:     expr_out (outfile, init);
                   1477:     nice_printf (outfile, "; ");
                   1478:     expr_out (outfile, test);
                   1479:     nice_printf (outfile, "; ");
                   1480:     expr_out (outfile, inc);
                   1481:     nice_printf (outfile, ") {\n");
                   1482:     next_tab (outfile);
                   1483: } /* out_for */
                   1484: 
                   1485: 
                   1486: void out_end_for (outfile)
                   1487: FILE *outfile;
                   1488: {
                   1489:     prev_tab (outfile);
                   1490:     nice_printf (outfile, "}\n");
                   1491: } /* out_end_for */

unix.superglobalmegacorp.com

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