output.c

Go to the documentation of this file.
00001 /****************************************************************
00002 Copyright 1990-1996, 2000-2001 by AT&T, Lucent Technologies and Bellcore.
00003 
00004 Permission to use, copy, modify, and distribute this software
00005 and its documentation for any purpose and without fee is hereby
00006 granted, provided that the above copyright notice appear in all
00007 copies and that both that the copyright notice and this
00008 permission notice and warranty disclaimer appear in supporting
00009 documentation, and that the names of AT&T, Bell Laboratories,
00010 Lucent or Bellcore or any of their entities not be used in
00011 advertising or publicity pertaining to distribution of the
00012 software without specific, written prior permission.
00013 
00014 AT&T, Lucent and Bellcore disclaim all warranties with regard to
00015 this software, including all implied warranties of
00016 merchantability and fitness.  In no event shall AT&T, Lucent or
00017 Bellcore be liable for any special, indirect or consequential
00018 damages or any damages whatsoever resulting from loss of use,
00019 data or profits, whether in an action of contract, negligence or
00020 other tortious action, arising out of or in connection with the
00021 use or performance of this software.
00022 ****************************************************************/
00023 
00024 #include "defs.h"
00025 #include "names.h"
00026 #include "output.h"
00027 
00028 #ifndef TRUE
00029 #define TRUE 1
00030 #endif
00031 #ifndef FALSE
00032 #define FALSE 0
00033 #endif
00034 
00035 char _assoc_table[] = { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0 };
00036 
00037 /* Opcode table -- This array is indexed by the OP_____ macros defined in
00038    defines.h; these macros are expected to be adjacent integers, so that
00039    this table is as small as possible. */
00040 
00041 table_entry opcode_table[] = {
00042                                 { 0, 0, NULL },
00043         /* OPPLUS 1 */          { BINARY_OP, 12, "%l + %r" },
00044         /* OPMINUS 2 */         { BINARY_OP, 12, "%l - %r" },
00045         /* OPSTAR 3 */          { BINARY_OP, 13, "%l * %r" },
00046         /* OPSLASH 4 */         { BINARY_OP, 13, "%l / %r" },
00047         /* OPPOWER 5 */         { BINARY_OP,  0, "power (%l, %r)" },
00048         /* OPNEG 6 */           { UNARY_OP,  14, "-%l" },
00049         /* OPOR 7 */            { BINARY_OP,  4, "%l || %r" },
00050         /* OPAND 8 */           { BINARY_OP,  5, "%l && %r" },
00051         /* OPEQV 9 */           { BINARY_OP,  9, "%l == %r" },
00052         /* OPNEQV 10 */         { BINARY_OP,  9, "%l != %r" },
00053         /* OPNOT 11 */          { UNARY_OP,  14, "! %l" },
00054         /* OPCONCAT 12 */       { BINARY_OP,  0, "concat (%l, %r)" },
00055         /* OPLT 13 */           { BINARY_OP, 10, "%l < %r" },
00056         /* OPEQ 14 */           { BINARY_OP,  9, "%l == %r" },
00057         /* OPGT 15 */           { BINARY_OP, 10, "%l > %r" },
00058         /* OPLE 16 */           { BINARY_OP, 10, "%l <= %r" },
00059         /* OPNE 17 */           { BINARY_OP,  9, "%l != %r" },
00060         /* OPGE 18 */           { BINARY_OP, 10, "%l >= %r" },
00061         /* OPCALL 19 */         { BINARY_OP, 15, SPECIAL_FMT },
00062         /* OPCCALL 20 */        { BINARY_OP, 15, SPECIAL_FMT },
00063 
00064 /* Left hand side of an assignment cannot have outermost parens */
00065 
00066         /* OPASSIGN 21 */       { BINARY_OP,  2, "%l = %r" },
00067         /* OPPLUSEQ 22 */       { BINARY_OP,  2, "%l += %r" },
00068         /* OPSTAREQ 23 */       { BINARY_OP,  2, "%l *= %r" },
00069         /* OPCONV 24 */         { BINARY_OP, 14, "%l" },
00070         /* OPLSHIFT 25 */       { BINARY_OP, 11, "%l << %r" },
00071         /* OPMOD 26 */          { BINARY_OP, 13, "%l %% %r" },
00072         /* OPCOMMA 27 */        { BINARY_OP,  1, "%l, %r" },
00073 
00074 /* Don't want to nest the colon operator in parens */
00075 
00076         /* OPQUEST 28 */        { BINARY_OP, 3, "%l ? %r" },
00077         /* OPCOLON 29 */        { BINARY_OP, 3, "%l : %r" },
00078         /* OPABS 30 */          { UNARY_OP,  0, "abs(%l)" },
00079         /* OPMIN 31 */          { BINARY_OP,   0, SPECIAL_FMT },
00080         /* OPMAX 32 */          { BINARY_OP,   0, SPECIAL_FMT },
00081         /* OPADDR 33 */         { UNARY_OP, 14, "&%l" },
00082 
00083         /* OPCOMMA_ARG 34 */    { BINARY_OP, 15, SPECIAL_FMT },
00084         /* OPBITOR 35 */        { BINARY_OP,  6, "%l | %r" },
00085         /* OPBITAND 36 */       { BINARY_OP,  8, "%l & %r" },
00086         /* OPBITXOR 37 */       { BINARY_OP,  7, "%l ^ %r" },
00087         /* OPBITNOT 38 */       { UNARY_OP,  14, "~ %l" },
00088         /* OPRSHIFT 39 */       { BINARY_OP, 11, "%l >> %r" },
00089 
00090 /* This isn't quite right -- it doesn't handle arrays, for instance */
00091 
00092         /* OPWHATSIN 40 */      { UNARY_OP,  14, "*%l" },
00093         /* OPMINUSEQ 41 */      { BINARY_OP,  2, "%l -= %r" },
00094         /* OPSLASHEQ 42 */      { BINARY_OP,  2, "%l /= %r" },
00095         /* OPMODEQ 43 */        { BINARY_OP,  2, "%l %%= %r" },
00096         /* OPLSHIFTEQ 44 */     { BINARY_OP,  2, "%l <<= %r" },
00097         /* OPRSHIFTEQ 45 */     { BINARY_OP,  2, "%l >>= %r" },
00098         /* OPBITANDEQ 46 */     { BINARY_OP,  2, "%l &= %r" },
00099         /* OPBITXOREQ 47 */     { BINARY_OP,  2, "%l ^= %r" },
00100         /* OPBITOREQ 48 */      { BINARY_OP,  2, "%l |= %r" },
00101         /* OPPREINC 49 */       { UNARY_OP,  14, "++%l" },
00102         /* OPPREDEC 50 */       { UNARY_OP,  14, "--%l" },
00103         /* OPDOT 51 */          { BINARY_OP, 15, "%l.%r" },
00104         /* OPARROW 52 */        { BINARY_OP, 15, "%l -> %r"},
00105         /* OPNEG1 53 */         { UNARY_OP,  14, "-%l" },
00106         /* OPDMIN 54 */         { BINARY_OP, 0, "dmin(%l,%r)" },
00107         /* OPDMAX 55 */         { BINARY_OP, 0, "dmax(%l,%r)" },
00108         /* OPASSIGNI 56 */      { BINARY_OP,  2, "%l = &%r" },
00109         /* OPIDENTITY 57 */     { UNARY_OP, 15, "%l" },
00110         /* OPCHARCAST 58 */     { UNARY_OP, 14, "(char *)&%l" },
00111         /* OPDABS 59 */         { UNARY_OP, 0, "dabs(%l)" },
00112         /* OPMIN2 60 */         { BINARY_OP,   0, "min(%l,%r)" },
00113         /* OPMAX2 61 */         { BINARY_OP,   0, "max(%l,%r)" },
00114         /* OPBITTEST 62 */      { BINARY_OP,   0, "bit_test(%l,%r)" },
00115         /* OPBITCLR 63 */       { BINARY_OP,   0, "bit_clear(%l,%r)" },
00116         /* OPBITSET 64 */       { BINARY_OP,   0, "bit_set(%l,%r)" },
00117 #ifdef TYQUAD
00118         /* OPQBITCLR 65 */      { BINARY_OP,   0, "qbit_clear(%l,%r)" },
00119         /* OPQBITSET 66 */      { BINARY_OP,   0, "qbit_set(%l,%r)" },
00120 #endif
00121 
00122 /* kludge to imitate (under forcedouble) f77's bizarre treatement of OPNEG... */
00123 
00124         /* OPNEG KLUDGE */      { UNARY_OP,  14, "-(doublereal)%l" }
00125 }; /* opcode_table */
00126 
00127 #define OPNEG_KLUDGE (sizeof(opcode_table)/sizeof(table_entry) - 1)
00128 
00129 extern int dneg, trapuv;
00130 static char opeqable[sizeof(opcode_table)/sizeof(table_entry)];
00131 
00132 
00133 static void output_arg_list Argdcl((FILEP, struct Listblock*));
00134 static void output_binary Argdcl((FILEP, Exprp));
00135 static void output_list Argdcl((FILEP, struct Listblock*));
00136 static void output_literal Argdcl((FILEP, long, Constp));
00137 static void output_prim Argdcl((FILEP, struct Primblock*));
00138 static void output_unary Argdcl((FILEP, Exprp));
00139 
00140 
00141  void
00142 #ifdef KR_headers
00143 expr_out(fp, e)
00144         FILE *fp;
00145         expptr e;
00146 #else
00147 expr_out(FILE *fp, expptr e)
00148 #endif
00149 {
00150         Namep var;
00151         expptr leftp, rightp;
00152         int opcode;
00153 
00154     if (e == (expptr) NULL)
00155         return;
00156 
00157     switch (e -> tag) {
00158         case TNAME:     out_name (fp, (struct Nameblock *) e);
00159                         return;
00160 
00161         case TCONST:    out_const(fp, &e->constblock);
00162                         goto end_out;
00163         case TEXPR:
00164                         break;
00165 
00166         case TADDR:     out_addr (fp, &(e -> addrblock));
00167                         goto end_out;
00168 
00169         case TPRIM:     if (!nerr)
00170                                 warn ("expr_out: got TPRIM");
00171                         output_prim (fp, &(e -> primblock));
00172                         return;
00173 
00174         case TLIST:     output_list (fp, &(e -> listblock));
00175  end_out:               frexpr(e);
00176                         return;
00177 
00178         case TIMPLDO:   err ("expr_out: got TIMPLDO");
00179                         return;
00180 
00181         case TERROR:
00182         default:
00183                         erri ("expr_out: bad tag '%d'", e -> tag);
00184     } /* switch */
00185 
00186 /* Now we know that the tag is TEXPR */
00187 
00188 /* Optimize on simple expressions, such as "a = a + b" ==> "a += b" */
00189 
00190     if (e -> exprblock.opcode == OPASSIGN && e -> exprblock.rightp)
00191       switch(e->exprblock.rightp->tag) {
00192         case TEXPR:
00193         opcode = e -> exprblock.rightp -> exprblock.opcode;
00194 
00195         if (opeqable[opcode]) {
00196             if ((leftp = e -> exprblock.leftp) &&
00197                 (rightp = e -> exprblock.rightp -> exprblock.leftp)) {
00198 
00199                 if (same_ident (leftp, rightp)) {
00200                     expptr temp = e -> exprblock.rightp;
00201 
00202                     e -> exprblock.opcode = op_assign(opcode);
00203 
00204                     e -> exprblock.rightp = temp -> exprblock.rightp;
00205                     temp->exprblock.rightp = 0;
00206                     frexpr(temp);
00207                 } /* if same_ident (leftp, rightp) */
00208             } /* if leftp && rightp */
00209         } /* if opcode == OPPLUS || */
00210         break;
00211 
00212         case TNAME:
00213           if (trapuv) {
00214                 var = &e->exprblock.rightp->nameblock;
00215                 if (ISREAL(var->vtype)
00216                  && var->vclass == CLVAR
00217                  && ONEOF(var->vstg, M(STGAUTO)|M(STGBSS))
00218                  && !var->vsave) {
00219                         expr_out(fp, e -> exprblock.leftp);
00220                         nice_printf(fp, " = _0 + ");
00221                         expr_out(fp, e->exprblock.rightp);
00222                         goto done;
00223                         }
00224                 }
00225       } /* if e -> exprblock.opcode == OPASSIGN */
00226 
00227 
00228 /* Optimize on increment or decrement by 1 */
00229 
00230     {
00231         opcode = e -> exprblock.opcode;
00232         leftp = e -> exprblock.leftp;
00233         rightp = e -> exprblock.rightp;
00234 
00235         if (leftp && rightp && (leftp -> headblock.vstg == STGARG ||
00236                 ISINT (leftp -> headblock.vtype)) &&
00237                 (opcode == OPPLUSEQ || opcode == OPMINUSEQ) &&
00238                 ISINT (rightp -> headblock.vtype) &&
00239                 ISICON (e -> exprblock.rightp) &&
00240                 (ISONE (e -> exprblock.rightp) ||
00241                 e -> exprblock.rightp -> constblock.Const.ci == -1)) {
00242 
00243 /* Allow for the '-1' constant value */
00244 
00245             if (!ISONE (e -> exprblock.rightp))
00246                 opcode = (opcode == OPPLUSEQ) ? OPMINUSEQ : OPPLUSEQ;
00247 
00248 /* replace the existing opcode */
00249 
00250             if (opcode == OPPLUSEQ)
00251                 e -> exprblock.opcode = OPPREINC;
00252             else
00253                 e -> exprblock.opcode = OPPREDEC;
00254 
00255 /* Free up storage used by the right hand side */
00256 
00257             frexpr (e -> exprblock.rightp);
00258             e->exprblock.rightp = 0;
00259         } /* if opcode == OPPLUS */
00260     } /* block */
00261 
00262 
00263     if (is_unary_op (e -> exprblock.opcode))
00264         output_unary (fp, &(e -> exprblock));
00265     else if (is_binary_op (e -> exprblock.opcode))
00266         output_binary (fp, &(e -> exprblock));
00267     else
00268         erri ("expr_out: bad opcode '%d'", (int) e -> exprblock.opcode);
00269 
00270  done:
00271     free((char *)e);
00272 
00273 } /* expr_out */
00274 
00275 
00276  void
00277 #ifdef KR_headers
00278 out_and_free_statement(outfile, expr)
00279         FILE *outfile;
00280         expptr expr;
00281 #else
00282 out_and_free_statement(FILE *outfile, expptr expr)
00283 #endif
00284 {
00285     if (expr)
00286         expr_out (outfile, expr);
00287 
00288     nice_printf (outfile, ";\n");
00289 } /* out_and_free_statement */
00290 
00291 
00292 
00293  int
00294 #ifdef KR_headers
00295 same_ident(left, right)
00296         expptr left;
00297         expptr right;
00298 #else
00299 same_ident(expptr left, expptr right)
00300 #endif
00301 {
00302     if (!left || !right)
00303         return 0;
00304 
00305     if (left -> tag == TNAME && right -> tag == TNAME && left == right)
00306         return 1;
00307 
00308     if (left -> tag == TADDR && right -> tag == TADDR &&
00309             left -> addrblock.uname_tag == right -> addrblock.uname_tag)
00310         switch (left -> addrblock.uname_tag) {
00311             case UNAM_REF:
00312             case UNAM_NAME:
00313 
00314 /* Check for array subscripts */
00315 
00316                 if (left -> addrblock.user.name -> vdim ||
00317                         right -> addrblock.user.name -> vdim)
00318                     if (left -> addrblock.user.name !=
00319                             right -> addrblock.user.name ||
00320                             !same_expr (left -> addrblock.memoffset,
00321                             right -> addrblock.memoffset))
00322                         return 0;
00323 
00324                 return same_ident ((expptr) (left -> addrblock.user.name),
00325                         (expptr) right -> addrblock.user.name);
00326             case UNAM_IDENT:
00327                 return strcmp(left->addrblock.user.ident,
00328                                 right->addrblock.user.ident) == 0;
00329             case UNAM_CHARP:
00330                 return strcmp(left->addrblock.user.Charp,
00331                                 right->addrblock.user.Charp) == 0;
00332             default:
00333                 return 0;
00334         } /* switch */
00335 
00336     if (left->tag == TEXPR && left->exprblock.opcode == OPWHATSIN
00337         && right->tag == TEXPR && right->exprblock.opcode == OPWHATSIN)
00338                 return same_ident(left->exprblock.leftp,
00339                                  right->exprblock.leftp);
00340 
00341     return 0;
00342 } /* same_ident */
00343 
00344  static int
00345 #ifdef KR_headers
00346 samefpconst(c1, c2, n)
00347         register Constp c1;
00348         register Constp c2;
00349         register int n;
00350 #else
00351 samefpconst(register Constp c1, register Constp c2, register int n)
00352 #endif
00353 {
00354         char *s1, *s2;
00355         if (!c1->vstg && !c2->vstg)
00356                 return c1->Const.cd[n] == c2->Const.cd[n];
00357         s1 = c1->vstg ? c1->Const.cds[n] : dtos(c1->Const.cd[n]);
00358         s2 = c2->vstg ? c2->Const.cds[n] : dtos(c2->Const.cd[n]);
00359         return !strcmp(s1, s2);
00360         }
00361 
00362  static int
00363 #ifdef KR_headers
00364 sameconst(c1, c2)
00365         register Constp c1;
00366         register Constp c2;
00367 #else
00368 sameconst(register Constp c1, register Constp c2)
00369 #endif
00370 {
00371         switch(c1->vtype) {
00372                 case TYCOMPLEX:
00373                 case TYDCOMPLEX:
00374                         if (!samefpconst(c1,c2,1))
00375                                 return 0;
00376                 case TYREAL:
00377                 case TYDREAL:
00378                         return samefpconst(c1,c2,0);
00379                 case TYCHAR:
00380                         return c1->Const.ccp1.blanks == c2->Const.ccp1.blanks
00381                             &&     c1->vleng->constblock.Const.ci
00382                                 == c2->vleng->constblock.Const.ci
00383                             && !memcmp(c1->Const.ccp, c2->Const.ccp,
00384                                         (int)c1->vleng->constblock.Const.ci);
00385                 case TYSHORT:
00386                 case TYINT:
00387                 case TYLOGICAL:
00388                         return c1->Const.ci == c2->Const.ci;
00389                 }
00390         err("unexpected type in sameconst");
00391         return 0;
00392         }
00393 
00394 /* same_expr -- Returns true only if   e1 and e2   match.  This is
00395    somewhat pessimistic, but can afford to be because it's just used to
00396    optimize on the assignment operators (+=, -=, etc). */
00397 
00398  int
00399 #ifdef KR_headers
00400 same_expr(e1, e2)
00401         expptr e1;
00402         expptr e2;
00403 #else
00404 same_expr(expptr e1, expptr e2)
00405 #endif
00406 {
00407     if (!e1 || !e2)
00408         return !e1 && !e2;
00409 
00410     if (e1 -> tag != e2 -> tag || e1 -> headblock.vtype != e2 -> headblock.vtype)
00411         return 0;
00412 
00413     switch (e1 -> tag) {
00414         case TEXPR:
00415             if (e1 -> exprblock.opcode != e2 -> exprblock.opcode)
00416                 return 0;
00417 
00418             return same_expr (e1 -> exprblock.leftp, e2 -> exprblock.leftp) &&
00419                    same_expr (e1 -> exprblock.rightp, e2 -> exprblock.rightp);
00420         case TNAME:
00421         case TADDR:
00422             return same_ident (e1, e2);
00423         case TCONST:
00424             return sameconst(&e1->constblock, &e2->constblock);
00425         default:
00426             return 0;
00427     } /* switch */
00428 } /* same_expr */
00429 
00430 
00431 
00432  void
00433 #ifdef KR_headers
00434 out_name(fp, namep)
00435         FILE *fp;
00436         Namep namep;
00437 #else
00438 out_name(FILE *fp, Namep namep)
00439 #endif
00440 {
00441     extern int usedefsforcommon;
00442     Extsym *comm;
00443 
00444     if (namep == NULL)
00445         return;
00446 
00447 /* DON'T want to use oneof_stg() here; need to find the right common name
00448    */
00449 
00450     if (namep->vstg == STGCOMMON && !namep->vcommequiv && !usedefsforcommon) {
00451         comm = &extsymtab[namep->vardesc.varno];
00452         extern_out(fp, comm);
00453         nice_printf(fp, "%d.", comm->curno);
00454     } /* if namep -> vstg == STGCOMMON */
00455 
00456     if (namep->vprocclass == PTHISPROC && namep->vtype != TYSUBR)
00457         nice_printf(fp, xretslot[namep->vtype]->user.ident);
00458     else
00459         nice_printf (fp, "%s", namep->cvarname);
00460 } /* out_name */
00461 
00462 
00463 #define cpd(n) cp->vstg ? cp->Const.cds[n] : dtos(cp->Const.cd[n])
00464 
00465  void
00466 #ifdef KR_headers
00467 out_const(fp, cp)
00468         FILE *fp;
00469         register Constp cp;
00470 #else
00471 out_const(FILE *fp, register Constp cp)
00472 #endif
00473 {
00474     static char real_buf[50], imag_buf[50];
00475     ftnint j;
00476     unsigned int k;
00477     int type = cp->vtype;
00478 
00479     switch (type) {
00480         case TYINT1:
00481         case TYSHORT:
00482             nice_printf (fp, "%ld", cp->Const.ci);      /* don't cast ci! */
00483             break;
00484         case TYLONG:
00485 #ifdef TYQUAD0
00486         case TYQUAD:
00487 #endif
00488             nice_printf (fp, "%ld", cp->Const.ci);      /* don't cast ci! */
00489             break;
00490 #ifndef NO_LONG_LONG
00491         case TYQUAD:
00492                 if (cp->Const.cd[1] == 123.456)
00493                         nice_printf (fp, "%s", cp->Const.cds[0]);
00494                 else
00495                         nice_printf (fp, "%lld", cp->Const.cq);
00496                 break;
00497 #endif
00498         case TYREAL:
00499             nice_printf(fp, "%s", flconst(real_buf, cpd(0)));
00500             break;
00501         case TYDREAL:
00502             nice_printf(fp, "%s", cpd(0));
00503             break;
00504         case TYCOMPLEX:
00505             nice_printf(fp, cm_fmt_string, flconst(real_buf, cpd(0)),
00506                         flconst(imag_buf, cpd(1)));
00507             break;
00508         case TYDCOMPLEX:
00509             nice_printf(fp, dcm_fmt_string, cpd(0), cpd(1));
00510             break;
00511         case TYLOGICAL1:
00512         case TYLOGICAL2:
00513         case TYLOGICAL:
00514             nice_printf (fp, "%s", cp->Const.ci ? "TRUE_" : "FALSE_");
00515             break;
00516         case TYCHAR: {
00517             char *c = cp->Const.ccp, *ce;
00518 
00519             if (c == NULL) {
00520                 nice_printf (fp, "\"\"");
00521                 break;
00522             } /* if c == NULL */
00523 
00524             nice_printf (fp, "\"");
00525             ce = c + cp->vleng->constblock.Const.ci;
00526             while(c < ce) {
00527                 k = *(unsigned char *)c++;
00528                 nice_printf(fp, str_fmt[k]);
00529                 }
00530             for(j = cp->Const.ccp1.blanks; j > 0; j--)
00531                 nice_printf(fp, " ");
00532             nice_printf (fp, "\"");
00533             break;
00534         } /* case TYCHAR */
00535         default:
00536             erri ("out_const:  bad type '%d'", (int) type);
00537             break;
00538     } /* switch */
00539 
00540 } /* out_const */
00541 #undef cpd
00542 
00543  static void
00544 #ifdef KR_headers
00545 out_args(fp, ep)
00546         FILE *fp;
00547         expptr ep;
00548 #else
00549 out_args(FILE *fp, expptr ep)
00550 #endif
00551 {
00552         chainp arglist;
00553 
00554         if(ep->tag != TLIST)
00555                 badtag("out_args", ep->tag);
00556         for(arglist = ep->listblock.listp;;) {
00557                 expr_out(fp, (expptr)arglist->datap);
00558                 arglist->datap = 0;
00559                 if (!(arglist = arglist->nextp))
00560                         break;
00561                 nice_printf(fp, ", ");
00562                 }
00563         }
00564 
00565 
00566 /* out_addr -- this routine isn't local because it is called by the
00567    system-generated identifier printing routines */
00568 
00569  void
00570 #ifdef KR_headers
00571 out_addr(fp, addrp)
00572         FILE *fp;
00573         struct Addrblock *addrp;
00574 #else
00575 out_addr(FILE *fp, struct Addrblock *addrp)
00576 #endif
00577 {
00578         extern Extsym *extsymtab;
00579         int was_array = 0;
00580         char *s;
00581 
00582 
00583         if (addrp == NULL)
00584                 return;
00585         if (doin_setbound
00586                         && addrp->vstg == STGARG
00587                         && addrp->vtype != TYCHAR
00588                         && ISICON(addrp->memoffset)
00589                         && !addrp->memoffset->constblock.Const.ci)
00590                 nice_printf(fp, "*");
00591 
00592         switch (addrp -> uname_tag) {
00593             case UNAM_REF:
00594                 nice_printf(fp, "%s_%s(", addrp->user.name->cvarname,
00595                         addrp->cmplx_sub ? "subscr" : "ref");
00596                 out_args(fp, addrp->memoffset);
00597                 nice_printf(fp, ")");
00598                 return;
00599             case UNAM_NAME:
00600                 out_name (fp, addrp -> user.name);
00601                 break;
00602             case UNAM_IDENT:
00603                 if (*(s = addrp->user.ident) == ' ') {
00604                         if (multitype)
00605                                 nice_printf(fp, "%s",
00606                                         xretslot[addrp->vtype]->user.ident);
00607                         else
00608                                 nice_printf(fp, "%s", s+1);
00609                         }
00610                 else {
00611                         nice_printf(fp, "%s", s);
00612                         }
00613                 break;
00614             case UNAM_CHARP:
00615                 nice_printf(fp, "%s", addrp->user.Charp);
00616                 break;
00617             case UNAM_EXTERN:
00618                 extern_out (fp, &extsymtab[addrp -> memno]);
00619                 break;
00620             case UNAM_CONST:
00621                 switch(addrp->vstg) {
00622                         case STGCONST:
00623                                 out_const(fp, (Constp)addrp);
00624                                 break;
00625                         case STGMEMNO:
00626                                 output_literal (fp, addrp->memno,
00627                                         (Constp)addrp);
00628                                 break;
00629                         default:
00630                         Fatal("unexpected vstg in out_addr");
00631                         }
00632                 break;
00633             case UNAM_UNKNOWN:
00634             default:
00635                 nice_printf (fp, "Unknown Addrp");
00636                 break;
00637         } /* switch */
00638 
00639 /* It's okay to just throw in the brackets here because they have a
00640    precedence level of 15, the highest value.  */
00641 
00642     if ((addrp->uname_tag == UNAM_NAME && addrp->user.name->vdim
00643                         || addrp->ntempelt > 1 || addrp->isarray)
00644         && addrp->vtype != TYCHAR) {
00645         expptr offset;
00646 
00647         was_array = 1;
00648 
00649         offset = addrp -> memoffset;
00650         addrp->memoffset = 0;
00651         if (ONEOF(addrp->vstg, M(STGCOMMON)|M(STGEQUIV))
00652                 && addrp -> uname_tag == UNAM_NAME
00653                 && !addrp->skip_offset)
00654             offset = mkexpr (OPMINUS, offset, mkintcon (
00655                     addrp -> user.name -> voffset));
00656 
00657         nice_printf (fp, "[");
00658 
00659         offset = mkexpr (OPSLASH, offset,
00660                 ICON (typesize[addrp -> vtype] * (addrp -> Field ? 2 : 1)));
00661         expr_out (fp, offset);
00662         nice_printf (fp, "]");
00663         }
00664 
00665 /* Check for structure field reference */
00666 
00667     if (addrp -> Field && addrp -> uname_tag != UNAM_CONST &&
00668             addrp -> uname_tag != UNAM_UNKNOWN) {
00669         if (oneof_stg((addrp -> uname_tag == UNAM_NAME ? addrp -> user.name :
00670                 (Namep) NULL), addrp -> vstg, M(STGARG)|M(STGEQUIV))
00671                 && !was_array && (addrp->vclass != CLPROC || !multitype))
00672             nice_printf (fp, "->%s", addrp -> Field);
00673         else
00674             nice_printf (fp, ".%s", addrp -> Field);
00675     } /* if */
00676 
00677 /* Check for character subscripting */
00678 
00679     if (addrp->vtype == TYCHAR &&
00680             (addrp->vclass != CLPROC || addrp->uname_tag == UNAM_NAME
00681                         && addrp->user.name->vprocclass == PTHISPROC) &&
00682             addrp -> memoffset &&
00683             (addrp -> uname_tag != UNAM_NAME ||
00684              addrp -> user.name -> vtype == TYCHAR) &&
00685             (!ISICON (addrp -> memoffset) ||
00686              (addrp -> memoffset -> constblock.Const.ci))) {
00687 
00688         int use_paren = 0;
00689         expptr e = addrp -> memoffset;
00690 
00691         if (!e)
00692                 return;
00693         addrp->memoffset = 0;
00694 
00695         if (ONEOF(addrp->vstg, M(STGCOMMON)|M(STGEQUIV))
00696          && addrp -> uname_tag == UNAM_NAME) {
00697             e = mkexpr (OPMINUS, e, mkintcon (addrp -> user.name -> voffset));
00698 
00699 /* mkexpr will simplify it to zero if possible */
00700             if (e->tag == TCONST && e->constblock.Const.ci == 0)
00701                 return;
00702         } /* if addrp -> vstg == STGCOMMON */
00703 
00704 /* In the worst case, parentheses might be needed OUTSIDE the expression,
00705    too.  But since I think this subscripting can only appear as a
00706    parameter in a procedure call, I don't think outside parens will ever
00707    be needed.  INSIDE parens are handled below */
00708 
00709         nice_printf (fp, " + ");
00710         if (e -> tag == TEXPR) {
00711             int arg_prec = op_precedence (e -> exprblock.opcode);
00712             int prec = op_precedence (OPPLUS);
00713             use_paren = arg_prec && (arg_prec < prec || (arg_prec == prec &&
00714                     is_left_assoc (OPPLUS)));
00715         } /* if e -> tag == TEXPR */
00716         if (use_paren) nice_printf (fp, "(");
00717         expr_out (fp, e);
00718         if (use_paren) nice_printf (fp, ")");
00719     } /* if */
00720 } /* out_addr */
00721 
00722 
00723  static void
00724 #ifdef KR_headers
00725 output_literal(fp, memno, cp)
00726         FILE *fp;
00727         long memno;
00728         Constp cp;
00729 #else
00730 output_literal(FILE *fp, long memno, Constp cp)
00731 #endif
00732 {
00733     struct Literal *litp, *lastlit;
00734 
00735     lastlit = litpool + nliterals;
00736 
00737     for (litp = litpool; litp < lastlit; litp++) {
00738         if (litp -> litnum == memno)
00739             break;
00740     } /* for litp */
00741 
00742     if (litp >= lastlit)
00743         out_const (fp, cp);
00744     else {
00745         nice_printf (fp, "%s", lit_name (litp));
00746         litp->lituse++;
00747         }
00748 } /* output_literal */
00749 
00750 
00751  static void
00752 #ifdef KR_headers
00753 output_prim(fp, primp)
00754         FILE *fp;
00755         struct Primblock *primp;
00756 #else
00757 output_prim(FILE *fp, struct Primblock *primp)
00758 #endif
00759 {
00760     if (primp == NULL)
00761         return;
00762 
00763     out_name (fp, primp -> namep);
00764     if (primp -> argsp)
00765         output_arg_list (fp, primp -> argsp);
00766 
00767     if (primp -> fcharp != (expptr) NULL || primp -> lcharp != (expptr) NULL)
00768         nice_printf (fp, "Sorry, no substrings yet");
00769 }
00770 
00771 
00772 
00773  static void
00774 #ifdef KR_headers
00775 output_arg_list(fp, listp)
00776         FILE *fp;
00777         struct Listblock *listp;
00778 #else
00779 output_arg_list(FILE *fp, struct Listblock *listp)
00780 #endif
00781 {
00782     chainp arg_list;
00783 
00784     if (listp == (struct Listblock *) NULL || listp -> listp == (chainp) NULL)
00785         return;
00786 
00787     nice_printf (fp, "(");
00788 
00789     for (arg_list = listp -> listp; arg_list; arg_list = arg_list -> nextp) {
00790         expr_out (fp, (expptr) arg_list -> datap);
00791         if (arg_list -> nextp != (chainp) NULL)
00792 
00793 /* Might want to add a hook in here to accomodate the style setting which
00794    wants spaces after commas */
00795 
00796             nice_printf (fp, ",");
00797     } /* for arg_list */
00798 
00799     nice_printf (fp, ")");
00800 } /* output_arg_list */
00801 
00802 
00803 
00804  static void
00805 #ifdef KR_headers
00806 output_unary(fp, e)
00807         FILE *fp;
00808         struct Exprblock *e;
00809 #else
00810 output_unary(FILE *fp, struct Exprblock *e)
00811 #endif
00812 {
00813     if (e == NULL)
00814         return;
00815 
00816     switch (e -> opcode) {
00817         case OPNEG:
00818                 if (e->vtype == TYREAL && dneg) {
00819                         e->opcode = OPNEG_KLUDGE;
00820                         output_binary(fp,e);
00821                         e->opcode = OPNEG;
00822                         break;
00823                         }
00824         case OPNEG1:
00825         case OPNOT:
00826         case OPABS:
00827         case OPBITNOT:
00828         case OPWHATSIN:
00829         case OPPREINC:
00830         case OPPREDEC:
00831         case OPADDR:
00832         case OPIDENTITY:
00833         case OPCHARCAST:
00834         case OPDABS:
00835             output_binary (fp, e);
00836             break;
00837         case OPCALL:
00838         case OPCCALL:
00839             nice_printf (fp, "Sorry, no OPCALL yet");
00840             break;
00841         default:
00842             erri ("output_unary: bad opcode", (int) e -> opcode);
00843             break;
00844     } /* switch */
00845 } /* output_unary */
00846 
00847 
00848  static char *
00849 #ifdef KR_headers
00850 findconst(m)
00851         register long m;
00852 #else
00853 findconst(register long m)
00854 #endif
00855 {
00856         register struct Literal *litp, *litpe;
00857 
00858         litp = litpool;
00859         for(litpe = litp + nliterals; litp < litpe; litp++)
00860                 if (litp->litnum ==  m)
00861                         return litp->cds[0];
00862         Fatal("findconst failure!");
00863         return 0;
00864         }
00865 
00866  static int
00867 #ifdef KR_headers
00868 opconv_fudge(fp, e)
00869         FILE *fp;
00870         struct Exprblock *e;
00871 #else
00872 opconv_fudge(FILE *fp, struct Exprblock *e)
00873 #endif
00874 {
00875         /* special handling for conversions, ichar and character*1 */
00876         register expptr lp;
00877         register union Expression *Offset;
00878         register char *cp;
00879         int lt;
00880         char buf[8], *s;
00881         unsigned int k;
00882         Namep np;
00883         Addrp ap;
00884 
00885         if (!(lp = e->leftp))   /* possible with erroneous Fortran */
00886                 return 1;
00887         lt = lp->headblock.vtype;
00888         if (lt == TYCHAR) {
00889                 switch(lp->tag) {
00890                         case TNAME:
00891                                 nice_printf(fp, "*(unsigned char *)");
00892                                 out_name(fp, (Namep)lp);
00893                                 return 1;
00894                         case TCONST:
00895  tconst:
00896                                 cp = lp->constblock.Const.ccp;
00897  tconst1:
00898                                 k = *(unsigned char *)cp;
00899                                 if (k < 128) { /* ASCII character */
00900                                         sprintf(buf, chr_fmt[k], k);
00901                                         nice_printf(fp, "'%s'", buf);
00902                                         }
00903                                 else
00904                                         nice_printf(fp, "%d", k);
00905                                 return 1;
00906                         case TADDR:
00907                                 switch(lp->addrblock.vstg) {
00908                                     case STGMEMNO:
00909                                         if (halign && e->vtype != TYCHAR) {
00910                                                 nice_printf(fp, "*(%s *)",
00911                                                     c_type_decl(e->vtype,0));
00912                                                 expr_out(fp, lp);
00913                                                 return 1;
00914                                                 }
00915                                         cp = findconst(lp->addrblock.memno);
00916                                         goto tconst1;
00917                                     case STGCONST:
00918                                         goto tconst;
00919                                     }
00920                                 lp->addrblock.vtype = tyint;
00921                                 Offset = lp->addrblock.memoffset;
00922                                 switch(lp->addrblock.uname_tag) {
00923                                   case UNAM_REF:
00924                                         nice_printf(fp, "*(unsigned char *)");
00925                                         return 0;
00926                                   case UNAM_NAME:
00927                                         np = lp->addrblock.user.name;
00928                                         if (ONEOF(np->vstg,
00929                                             M(STGCOMMON)|M(STGEQUIV)))
00930                                                 Offset = mkexpr(OPMINUS, Offset,
00931                                                         ICON(np->voffset));
00932                                         }
00933                                 lp->addrblock.memoffset = Offset ?
00934                                         mkexpr(OPSTAR, Offset,
00935                                                 ICON(typesize[tyint]))
00936                                         : ICON(0);
00937                                 lp->addrblock.isarray = 1;
00938                                 /* STGCOMMON or STGEQUIV would cause */
00939                                 /* voffset to be added in a second time */
00940                                 lp->addrblock.vstg = STGUNKNOWN;
00941                                 nice_printf(fp, "*(unsigned char *)&");
00942                                 return 0;
00943                         default:
00944                                 badtag("opconv_fudge", lp->tag);
00945                         }
00946                 }
00947         if (lt != e->vtype) {
00948                 s = c_type_decl(e->vtype, 0);
00949                 if (ISCOMPLEX(lt)) {
00950  tryagain:
00951                         np = (Namep)e->leftp;
00952                         switch(np->tag) {
00953                           case TNAME:
00954                                 nice_printf(fp, "(%s) %s%sr", s,
00955                                         np->cvarname,
00956                                         np->vstg == STGARG ? "->" : ".");
00957                                 return 1;
00958                           case TADDR:
00959                                 ap = (Addrp)np;
00960                                 switch(ap->uname_tag) {
00961                                   case UNAM_IDENT:
00962                                         nice_printf(fp, "(%s) %s.r", s,
00963                                                 ap->user.ident);
00964                                         return 1;
00965                                   case UNAM_NAME:
00966                                         nice_printf(fp, "(%s) ", s);
00967                                         out_addr(fp, ap);
00968                                         nice_printf(fp, ".r");
00969                                         return 1;
00970                                   case UNAM_REF:
00971                                         nice_printf(fp, "(%s) %s_%s(",
00972                                          s, ap->user.name->cvarname,
00973                                          ap->cmplx_sub ? "subscr" : "ref");
00974                                         out_args(fp, ap->memoffset);
00975                                         nice_printf(fp, ").r");
00976                                         return 1;
00977                                   default:
00978                                         fatali(
00979                                          "Bad uname_tag %d in opconv_fudge",
00980                                                 ap->uname_tag);
00981                                   }
00982                           case TEXPR:
00983                                 e = (Exprp)np;
00984                                 if (e->opcode == OPWHATSIN)
00985                                         goto tryagain;
00986                           default:
00987                                 fatali("Unexpected tag %d in opconv_fudge",
00988                                         np->tag);
00989                           }
00990                         }
00991                 nice_printf(fp, "(%s) ", s);
00992                 }
00993         return 0;
00994         }
00995 
00996 
00997  static void
00998 #ifdef KR_headers
00999 output_binary(fp, e)
01000         FILE *fp;
01001         struct Exprblock *e;
01002 #else
01003 output_binary(FILE *fp, struct Exprblock *e)
01004 #endif
01005 {
01006     char *format;
01007     int prec;
01008 
01009     if (e == NULL || e -> tag != TEXPR)
01010         return;
01011 
01012 /* Instead of writing a huge switch, I've incorporated the output format
01013    into a table.  Things like "%l" and "%r" stand for the left and
01014    right subexpressions.  This should allow both prefix and infix
01015    functions to be specified (e.g. "(%l * %r", "z_div (%l, %r").  Of
01016    course, I should REALLY think out the ramifications of writing out
01017    straight text, as opposed to some intermediate format, which could
01018    figure out and optimize on the the number of required blanks (we don't
01019    want "x - (-y)" to become "x --y", for example).  Special cases (such as
01020    incomplete implementations) could still be implemented as part of the
01021    switch, they will just have some dummy value instead of the string
01022    pattern.  Another difficulty is the fact that the complex functions
01023    will differ from the integer and real ones */
01024 
01025 /* Handle a special case.  We don't want to output "x + - 4", or "y - - 3"
01026 */
01027     if ((e -> opcode == OPPLUS || e -> opcode == OPMINUS) &&
01028             e -> rightp && e -> rightp -> tag == TCONST &&
01029             isnegative_const (&(e -> rightp -> constblock)) &&
01030             is_negatable (&(e -> rightp -> constblock))) {
01031 
01032         e -> opcode = (e -> opcode == OPPLUS) ? OPMINUS : OPPLUS;
01033         negate_const (&(e -> rightp -> constblock));
01034     } /* if e -> opcode == PLUS or MINUS */
01035 
01036     prec = op_precedence (e -> opcode);
01037     format = op_format (e -> opcode);
01038 
01039     if (format != SPECIAL_FMT) {
01040         while (*format) {
01041             if (*format == '%') {
01042                 int arg_prec, use_paren = 0;
01043                 expptr lp, rp;
01044 
01045                 switch (*(format + 1)) {
01046                     case 'l':
01047                         lp = e->leftp;
01048                         if (lp && lp->tag == TEXPR) {
01049                             arg_prec = op_precedence(lp->exprblock.opcode);
01050 
01051                             use_paren = arg_prec &&
01052                                 (arg_prec < prec || (arg_prec == prec &&
01053                                     is_right_assoc (prec)));
01054                         } /* if e -> leftp */
01055                         if (e->opcode == OPCONV && opconv_fudge(fp,e))
01056                                 break;
01057                         if (use_paren)
01058                             nice_printf (fp, "(");
01059                         expr_out(fp, lp);
01060                         if (use_paren)
01061                             nice_printf (fp, ")");
01062                         break;
01063                     case 'r':
01064                         rp = e->rightp;
01065                         if (rp && rp->tag == TEXPR) {
01066                             arg_prec = op_precedence(rp->exprblock.opcode);
01067 
01068                             use_paren = arg_prec &&
01069                                 (arg_prec < prec || (arg_prec == prec &&
01070                                     is_left_assoc (prec)));
01071                             use_paren = use_paren ||
01072                                 (rp->exprblock.opcode == OPNEG
01073                                 && prec >= op_precedence(OPMINUS));
01074                         } /* if e -> rightp */
01075                         if (use_paren)
01076                             nice_printf (fp, "(");
01077                         expr_out(fp, rp);
01078                         if (use_paren)
01079                             nice_printf (fp, ")");
01080                         break;
01081                     case '\0':
01082                     case '%':
01083                         nice_printf (fp, "%%");
01084                         break;
01085                     default:
01086                         erri ("output_binary: format err: '%%%c' illegal",
01087                                 (int) *(format + 1));
01088                         break;
01089                 } /* switch */
01090                 format += 2;
01091             } else
01092                 nice_printf (fp, "%c", *format++);
01093         } /* while *format */
01094     } else {
01095 
01096 /* Handle Special cases of formatting */
01097 
01098         switch (e -> opcode) {
01099                 case OPCCALL:
01100                 case OPCALL:
01101                         out_call (fp, (int) e -> opcode, e -> vtype,
01102                                         e -> vleng, e -> leftp, e -> rightp);
01103                         break;
01104 
01105                 case OPCOMMA_ARG:
01106                         doin_setbound = 1;
01107                         nice_printf(fp, "(");
01108                         expr_out(fp, e->leftp);
01109                         nice_printf(fp, ", &");
01110                         doin_setbound = 0;
01111                         expr_out(fp, e->rightp);
01112                         nice_printf(fp, ")");
01113                         break;
01114 
01115                 case OPADDR:
01116                 default:
01117                         nice_printf (fp, "Sorry, can't format OPCODE '%d'",
01118                                 e -> opcode);
01119                         break;
01120                 }
01121 
01122     } /* else */
01123 } /* output_binary */
01124 
01125  void
01126 #ifdef KR_headers
01127 out_call(outfile, op, ftype, len, name, args)
01128         FILE *outfile;
01129         int op;
01130         int ftype;
01131         expptr len;
01132         expptr name;
01133         expptr args;
01134 #else
01135 out_call(FILE *outfile, int op, int ftype, expptr len, expptr name, expptr args)
01136 #endif
01137 {
01138     chainp arglist;             /* Pointer to any actual arguments */
01139     chainp cp;                  /* Iterator over argument lists */
01140     Addrp ret_val = (Addrp) NULL;
01141                                 /* Function return value buffer, if any is
01142                                    required */
01143     int byvalue;                /* True iff we're calling a C library
01144                                    routine */
01145     int done_once;              /* Used for writing commas to   outfile   */
01146     int narg, t;
01147     register expptr q;
01148     long L;
01149     Argtypes *at;
01150     Atype *A, *Ac;
01151     Namep np;
01152     extern int forcereal;
01153 
01154 /* Don't use addresses if we're calling a C function */
01155 
01156     byvalue = op == OPCCALL;
01157 
01158     if (args)
01159         arglist = args -> listblock.listp;
01160     else
01161         arglist = CHNULL;
01162 
01163 /* If this is a CHARACTER function, the first argument is the result */
01164 
01165     if (ftype == TYCHAR)
01166         if (ISICON (len)) {
01167             ret_val = (Addrp) (arglist -> datap);
01168             arglist = arglist -> nextp;
01169         } else {
01170             err ("adjustable character function");
01171             return;
01172         } /* else */
01173 
01174 /* If this is a COMPLEX function, the first argument is the result */
01175 
01176     else if (ISCOMPLEX (ftype)) {
01177         ret_val = (Addrp) (arglist -> datap);
01178         arglist = arglist -> nextp;
01179     } /* if ISCOMPLEX */
01180 
01181     /* prepare to cast procedure parameters -- set A if we know how */
01182     np = name->tag == TEXPR && name->exprblock.opcode == OPWHATSIN
01183         ? (Namep)name->exprblock.leftp : (Namep)name;
01184 
01185     A = Ac = 0;
01186     if (np->tag == TNAME && (at = np->arginfo)) {
01187         if (at->nargs > 0)
01188                 A = at->atypes;
01189         if (Ansi && (at->defined || at->nargs > 0))
01190                 Ac = at->atypes;
01191         }
01192 
01193 /* Now we can actually start to write out the function invocation */
01194 
01195     if (ftype == TYREAL && forcereal)
01196         nice_printf(outfile, "(real)");
01197     if (name -> tag == TEXPR && name -> exprblock.opcode == OPWHATSIN) {
01198         nice_printf (outfile, "(");
01199         expr_out (outfile, name);
01200         nice_printf (outfile, ")");
01201         }
01202     else
01203         expr_out(outfile, name);
01204 
01205     nice_printf(outfile, "(");
01206 
01207     if (ret_val) {
01208         if (ISCOMPLEX (ftype))
01209             nice_printf (outfile, "&");
01210         expr_out (outfile, (expptr) ret_val);
01211         if (Ac)
01212                 Ac++;
01213 
01214 /* The length of the result of a character function is the second argument */
01215 /* It should be in place from putcall(), so we won't touch it explicitly */
01216 
01217     } /* if ret_val */
01218     done_once = ret_val ? TRUE : FALSE;
01219 
01220 /* Now run through the named arguments */
01221 
01222     narg = -1;
01223     for (cp = arglist; cp; cp = cp -> nextp, done_once = TRUE) {
01224 
01225         if (done_once)
01226             nice_printf (outfile, ", ");
01227         narg++;
01228 
01229         if (!( q = (expptr)cp->datap) )
01230                 continue;
01231 
01232         if (q->tag == TADDR) {
01233                 if (q->addrblock.vtype > TYERROR) {
01234                         /* I/O block */
01235                         nice_printf(outfile, "&%s", q->addrblock.user.ident);
01236                         continue;
01237                         }
01238                 if (!byvalue && q->addrblock.isarray
01239                 && q->addrblock.vtype != TYCHAR
01240                 && q->addrblock.memoffset->tag == TCONST) {
01241 
01242                         /* check for 0 offset -- after */
01243                         /* correcting for equivalence. */
01244                         L = q->addrblock.memoffset->constblock.Const.ci;
01245                         if (ONEOF(q->addrblock.vstg, M(STGCOMMON)|M(STGEQUIV))
01246                                         && q->addrblock.uname_tag == UNAM_NAME)
01247                                 L -= q->addrblock.user.name->voffset;
01248                         if (L)
01249                                 goto skip_deref;
01250 
01251                         if (Ac && narg < at->dnargs
01252                          && q->headblock.vtype != (t = Ac[narg].type)
01253                          && t > TYADDR && t < TYSUBR)
01254                                 nice_printf(outfile, "(%s*)", Typename[t]);
01255 
01256                         /* &x[0] == x */
01257                         /* This also prevents &sizeof(doublereal)[0] */
01258 
01259                         switch(q->addrblock.uname_tag) {
01260                             case UNAM_NAME:
01261                                 out_name(outfile, q->addrblock.user.name);
01262                                 continue;
01263                             case UNAM_IDENT:
01264                                 nice_printf(outfile, "%s",
01265                                         q->addrblock.user.ident);
01266                                 continue;
01267                             case UNAM_CHARP:
01268                                 nice_printf(outfile, "%s",
01269                                         q->addrblock.user.Charp);
01270                                 continue;
01271                             case UNAM_EXTERN:
01272                                 extern_out(outfile,
01273                                         &extsymtab[q->addrblock.memno]);
01274                                 continue;
01275                             }
01276                         }
01277                 }
01278 
01279 /* Skip over the dereferencing operator generated only for the
01280    intermediate file */
01281  skip_deref:
01282         if (q -> tag == TEXPR && q -> exprblock.opcode == OPWHATSIN)
01283             q = q -> exprblock.leftp;
01284 
01285         if (q->headblock.vclass == CLPROC) {
01286             if (Castargs && (q->tag != TNAME
01287                                 || q->nameblock.vprocclass != PTHISPROC)
01288                          && (q->tag != TADDR
01289                                 || q->addrblock.uname_tag != UNAM_NAME
01290                                 || q->addrblock.user.name->vprocclass
01291                                                                 != PTHISPROC))
01292                 {
01293                 if (A && (t = A[narg].type) >= 200)
01294                         t %= 100;
01295                 else {
01296                         t = q->headblock.vtype;
01297                         if (q->tag == TNAME && q->nameblock.vimpltype)
01298                                 t = TYUNKNOWN;
01299                         }
01300                 nice_printf(outfile, "(%s)", usedcasts[t] = casttypes[t]);
01301                 }
01302             }
01303         else if (Ac && narg < at->dnargs
01304                 && q->headblock.vtype != (t = Ac[narg].type)
01305                 && t > TYADDR && t < TYSUBR)
01306                 nice_printf(outfile, "(%s*)", Typename[t]);
01307 
01308         if ((q -> tag == TADDR || q-> tag == TNAME) &&
01309                 (byvalue || q -> headblock.vstg != STGREG)) {
01310             if (q -> headblock.vtype != TYCHAR)
01311               if (byvalue) {
01312 
01313                 if (q -> tag == TADDR &&
01314                         q -> addrblock.uname_tag == UNAM_NAME &&
01315                         ! q -> addrblock.user.name -> vdim &&
01316                         oneof_stg(q -> addrblock.user.name, q -> addrblock.vstg,
01317                                         M(STGARG)|M(STGEQUIV)) &&
01318                         ! ISCOMPLEX(q->addrblock.user.name->vtype))
01319                     nice_printf (outfile, "*");
01320                 else if (q -> tag == TNAME
01321                         && oneof_stg(&q->nameblock, q -> nameblock.vstg,
01322                                 M(STGARG)|M(STGEQUIV))
01323                         && !(q -> nameblock.vdim))
01324                     nice_printf (outfile, "*");
01325 
01326               } else {
01327                 expptr memoffset;
01328 
01329                 if (q->tag == TADDR && (
01330                         !ONEOF (q -> addrblock.vstg, M(STGEXT)|M(STGLENG))
01331                         && (ONEOF(q->addrblock.vstg,
01332                                 M(STGCOMMON)|M(STGEQUIV)|M(STGMEMNO))
01333                             || ((memoffset = q->addrblock.memoffset)
01334                                 && (!ISICON(memoffset)
01335                                 || memoffset->constblock.Const.ci)))
01336                         || ONEOF(q->addrblock.vstg,
01337                                         M(STGINIT)|M(STGAUTO)|M(STGBSS))
01338                                 && !q->addrblock.isarray))
01339                     nice_printf (outfile, "&");
01340                 else if (q -> tag == TNAME
01341                         && !oneof_stg(&q->nameblock, q -> nameblock.vstg,
01342                                 M(STGARG)|M(STGEXT)|M(STGEQUIV)))
01343                     nice_printf (outfile, "&");
01344             } /* else */
01345 
01346             expr_out (outfile, q);
01347         } /* if q -> tag == TADDR || q -> tag == TNAME */
01348 
01349 /* Might be a Constant expression, e.g. string length, character constants */
01350 
01351         else if (q -> tag == TCONST) {
01352                 if (q->constblock.vtype == TYLONG)
01353                         nice_printf(outfile, "(ftnlen)%ld",
01354                                 q->constblock.Const.ci);
01355                 else
01356                         out_const(outfile, &q->constblock);
01357             }
01358 
01359 /* Must be some other kind of expression, or register var, or constant.
01360    In particular, this is likely to be a temporary variable assignment
01361    which was generated in p1put_call */
01362 
01363         else if (!ISCOMPLEX (q -> headblock.vtype) && !ISCHAR (q)){
01364             int use_paren = q -> tag == TEXPR &&
01365                     op_precedence (q -> exprblock.opcode) <=
01366                     op_precedence (OPCOMMA);
01367             if (q->headblock.vtype == TYREAL) {
01368                 if (forcereal) {
01369                         nice_printf(outfile, "(real)");
01370                         use_paren = 1;
01371                         }
01372                 }
01373             else if (!Ansi && ISINT(q->headblock.vtype)) {
01374                 nice_printf(outfile, "(ftnlen)");
01375                 use_paren = 1;
01376                 }
01377             if (use_paren) nice_printf (outfile, "(");
01378             expr_out (outfile, q);
01379             if (use_paren) nice_printf (outfile, ")");
01380         } /* if !ISCOMPLEX */
01381         else
01382             err ("out_call:  unknown parameter");
01383 
01384     } /* for (cp = arglist */
01385 
01386     if (arglist)
01387         frchain (&arglist);
01388 
01389     nice_printf (outfile, ")");
01390 
01391 } /* out_call */
01392 
01393 
01394  char *
01395 #ifdef KR_headers
01396 flconst(buf, x)
01397         char *buf;
01398         char *x;
01399 #else
01400 flconst(char *buf, char *x)
01401 #endif
01402 {
01403         sprintf(buf, fl_fmt_string, x);
01404         return buf;
01405         }
01406 
01407  char *
01408 #ifdef KR_headers
01409 dtos(x)
01410         double x;
01411 #else
01412 dtos(double x)
01413 #endif
01414 {
01415         static char buf[64];
01416 #ifdef USE_DTOA
01417         g_fmt(buf, x);
01418 #else
01419         sprintf(buf, db_fmt_string, x);
01420 #endif
01421         return strcpy(mem(strlen(buf)+1,0), buf);
01422         }
01423 
01424 char tr_tab[Table_size];
01425 
01426 /* out_init -- Initialize the data structures used by the routines in
01427    output.c.  These structures include the output format to be used for
01428    Float, Double, Complex, and Double Complex constants. */
01429 
01430  void
01431 out_init(Void)
01432 {
01433     extern int tab_size;
01434     register char *s;
01435 
01436     s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+-.";
01437     while(*s)
01438         tr_tab[*s++] = 3;
01439     tr_tab['>'] = 1;
01440 
01441         opeqable[OPPLUS] = 1;
01442         opeqable[OPMINUS] = 1;
01443         opeqable[OPSTAR] = 1;
01444         opeqable[OPSLASH] = 1;
01445         opeqable[OPMOD] = 1;
01446         opeqable[OPLSHIFT] = 1;
01447         opeqable[OPBITAND] = 1;
01448         opeqable[OPBITXOR] = 1;
01449         opeqable[OPBITOR ] = 1;
01450 
01451 
01452 /* Set the output format for both types of floating point constants */
01453 
01454     if (fl_fmt_string == NULL || *fl_fmt_string == '\0')
01455         fl_fmt_string = (char*)(Ansi == 1 ? "%sf" : "(float)%s");
01456 
01457     if (db_fmt_string == NULL || *db_fmt_string == '\0')
01458         db_fmt_string = "%.17g";
01459 
01460 /* Set the output format for both types of complex constants.  They will
01461    have string parameters rather than float or double so that the decimal
01462    point may be added to the strings generated by the {db,fl}_fmt_string
01463    formats above */
01464 
01465     if (cm_fmt_string == NULL || *cm_fmt_string == '\0') {
01466         cm_fmt_string = "{%s,%s}";
01467     } /* if cm_fmt_string == NULL */
01468 
01469     if (dcm_fmt_string == NULL || *dcm_fmt_string == '\0') {
01470         dcm_fmt_string = "{%s,%s}";
01471     } /* if dcm_fmt_string == NULL */
01472 
01473     tab_size = 4;
01474 } /* out_init */
01475 
01476 
01477  void
01478 #ifdef KR_headers
01479 extern_out(fp, extsym)
01480         FILE *fp;
01481         Extsym *extsym;
01482 #else
01483 extern_out(FILE *fp, Extsym *extsym)
01484 #endif
01485 {
01486     if (extsym == (Extsym *) NULL)
01487         return;
01488 
01489     nice_printf (fp, "%s", extsym->cextname);
01490 
01491 } /* extern_out */
01492 
01493 
01494 
01495  static void
01496 #ifdef KR_headers
01497 output_list(fp, listp)
01498         FILE *fp;
01499         struct Listblock *listp;
01500 #else
01501 output_list(FILE *fp, struct Listblock *listp)
01502 #endif
01503 {
01504     int did_one = 0;
01505     chainp elts;
01506 
01507     nice_printf (fp, "(");
01508     if (listp)
01509         for (elts = listp -> listp; elts; elts = elts -> nextp) {
01510             if (elts -> datap) {
01511                 if (did_one)
01512                     nice_printf (fp, ", ");
01513                 expr_out (fp, (expptr) elts -> datap);
01514                 did_one = 1;
01515             } /* if elts -> datap */
01516         } /* for elts */
01517     nice_printf (fp, ")");
01518 } /* output_list */
01519 
01520 
01521  void
01522 #ifdef KR_headers
01523 out_asgoto(outfile, expr)
01524         FILE *outfile;
01525         expptr expr;
01526 #else
01527 out_asgoto(FILE *outfile, expptr expr)
01528 #endif
01529 {
01530     chainp value;
01531     Namep namep;
01532     int k;
01533 
01534     if (expr == (expptr) NULL) {
01535         err ("out_asgoto:  NULL variable expr");
01536         return;
01537     } /* if expr */
01538 
01539     nice_printf (outfile, Ansi ? "switch (" : "switch ((int)"); /*)*/
01540     expr_out (outfile, expr);
01541     nice_printf (outfile, ") {\n");
01542     next_tab (outfile);
01543 
01544 /* The initial addrp value will be stored as a namep pointer */
01545 
01546     switch(expr->tag) {
01547         case TNAME:
01548                 /* local variable */
01549                 namep = &expr->nameblock;
01550                 break;
01551         case TEXPR:
01552                 if (expr->exprblock.opcode == OPWHATSIN
01553                  && expr->exprblock.leftp->tag == TNAME)
01554                         /* argument */
01555                         namep = &expr->exprblock.leftp->nameblock;
01556                 else
01557                         goto bad;
01558                 break;
01559         case TADDR:
01560                 if (expr->addrblock.uname_tag == UNAM_NAME) {
01561                         /* initialized local variable */
01562                         namep = expr->addrblock.user.name;
01563                         break;
01564                         }
01565         default:
01566  bad:
01567                 err("out_asgoto:  bad expr");
01568                 return;
01569         }
01570 
01571     for(k = 0, value = namep -> varxptr.assigned_values; value;
01572             value = value->nextp, k++) {
01573         nice_printf (outfile, "case %d: goto %s;\n", k,
01574                 user_label((long)value->datap));
01575     } /* for value */
01576     prev_tab (outfile);
01577 
01578     nice_printf (outfile, "}\n");
01579 } /* out_asgoto */
01580 
01581  void
01582 #ifdef KR_headers
01583 out_if(outfile, expr)
01584         FILE *outfile;
01585         expptr expr;
01586 #else
01587 out_if(FILE *outfile, expptr expr)
01588 #endif
01589 {
01590     nice_printf (outfile, "if (");
01591     expr_out (outfile, expr);
01592     nice_printf (outfile, ") {\n");
01593     next_tab (outfile);
01594 } /* out_if */
01595 
01596  static void
01597 #ifdef KR_headers
01598 output_rbrace(outfile, s)
01599         FILE *outfile;
01600         char *s;
01601 #else
01602 output_rbrace(FILE *outfile, char *s)
01603 #endif
01604 {
01605         extern int last_was_label;
01606         register char *fmt;
01607 
01608         if (last_was_label) {
01609                 last_was_label = 0;
01610                 fmt = ";%s";
01611                 }
01612         else
01613                 fmt = "%s";
01614         nice_printf(outfile, fmt, s);
01615         }
01616 
01617  void
01618 #ifdef KR_headers
01619 out_else(outfile)
01620         FILE *outfile;
01621 #else
01622 out_else(FILE *outfile)
01623 #endif
01624 {
01625     prev_tab (outfile);
01626     output_rbrace(outfile, "} else {\n");
01627     next_tab (outfile);
01628 } /* out_else */
01629 
01630  void
01631 #ifdef KR_headers
01632 elif_out(outfile, expr)
01633         FILE *outfile;
01634         expptr expr;
01635 #else
01636 elif_out(FILE *outfile, expptr expr)
01637 #endif
01638 {
01639     prev_tab (outfile);
01640     output_rbrace(outfile, "} else ");
01641     out_if (outfile, expr);
01642 } /* elif_out */
01643 
01644  void
01645 #ifdef KR_headers
01646 endif_out(outfile)
01647         FILE *outfile;
01648 #else
01649 endif_out(FILE *outfile)
01650 #endif
01651 {
01652     prev_tab (outfile);
01653     output_rbrace(outfile, "}\n");
01654 } /* endif_out */
01655 
01656  void
01657 #ifdef KR_headers
01658 end_else_out(outfile)
01659         FILE *outfile;
01660 #else
01661 end_else_out(FILE *outfile)
01662 #endif
01663 {
01664     prev_tab (outfile);
01665     output_rbrace(outfile, "}\n");
01666 } /* end_else_out */
01667 
01668 
01669 
01670  void
01671 #ifdef KR_headers
01672 compgoto_out(outfile, index, labels)
01673         FILE *outfile;
01674         expptr index;
01675         expptr labels;
01676 #else
01677 compgoto_out(FILE *outfile, expptr index, expptr labels)
01678 #endif
01679 {
01680     char *s1, *s2;
01681 
01682     if (index == ENULL)
01683         err ("compgoto_out:  null index for computed goto");
01684     else if (labels && labels -> tag != TLIST)
01685         erri ("compgoto_out:  expected label list, got tag '%d'",
01686                 labels -> tag);
01687     else {
01688         chainp elts;
01689         int i = 1;
01690 
01691         s2 = /*(*/ ") {\n"; /*}*/
01692         if (Ansi)
01693                 s1 = "switch ("; /*)*/
01694         else if (index->tag == TNAME || index->tag == TEXPR
01695                                 && index->exprblock.opcode == OPWHATSIN)
01696                 s1 = "switch ((int)"; /*)*/
01697         else {
01698                 s1 = "switch ((int)(";
01699                 s2 = ")) {\n"; /*}*/
01700                 }
01701         nice_printf(outfile, s1);
01702         expr_out (outfile, index);
01703         nice_printf (outfile, s2);
01704         next_tab (outfile);
01705 
01706         for (elts = labels -> listblock.listp; elts; elts = elts -> nextp, i++) {
01707             if (elts -> datap) {
01708                 if (ISICON(((expptr) (elts -> datap))))
01709                     nice_printf (outfile, "case %d:  goto %s;\n", i,
01710                         user_label(((expptr)(elts->datap))->constblock.Const.ci));
01711                 else
01712                     err ("compgoto_out:  bad label in label list");
01713             } /* if (elts -> datap) */
01714         } /* for elts */
01715         prev_tab (outfile);
01716         nice_printf (outfile, /*{*/ "}\n");
01717     } /* else */
01718 } /* compgoto_out */
01719 
01720 
01721  void
01722 #ifdef KR_headers
01723 out_for(outfile, init, test, inc)
01724         FILE *outfile;
01725         expptr init;
01726         expptr test;
01727         expptr inc;
01728 #else
01729 out_for(FILE *outfile, expptr init, expptr test, expptr inc)
01730 #endif
01731 {
01732     nice_printf (outfile, "for (");
01733     expr_out (outfile, init);
01734     nice_printf (outfile, "; ");
01735     expr_out (outfile, test);
01736     nice_printf (outfile, "; ");
01737     expr_out (outfile, inc);
01738     nice_printf (outfile, ") {\n");
01739     next_tab (outfile);
01740 } /* out_for */
01741 
01742 
01743  void
01744 #ifdef KR_headers
01745 out_end_for(outfile)
01746         FILE *outfile;
01747 #else
01748 out_end_for(FILE *outfile)
01749 #endif
01750 {
01751     prev_tab (outfile);
01752     nice_printf (outfile, "}\n");
01753 } /* out_end_for */

Generated on Sun Mar 4 15:03:44 2007 for Scilab [trunk] by  doxygen 1.5.1