00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
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 
00038 
00039 
00040 
00041 table_entry opcode_table[] = {
00042                                 { 0, 0, NULL },
00043                   { BINARY_OP, 12, "%l + %r" },
00044                  { BINARY_OP, 12, "%l - %r" },
00045                   { BINARY_OP, 13, "%l * %r" },
00046                  { BINARY_OP, 13, "%l / %r" },
00047                  { BINARY_OP,  0, "power (%l, %r)" },
00048                    { UNARY_OP,  14, "-%l" },
00049                     { BINARY_OP,  4, "%l || %r" },
00050                    { BINARY_OP,  5, "%l && %r" },
00051                    { BINARY_OP,  9, "%l == %r" },
00052                  { BINARY_OP,  9, "%l != %r" },
00053                   { UNARY_OP,  14, "! %l" },
00054                { BINARY_OP,  0, "concat (%l, %r)" },
00055                    { BINARY_OP, 10, "%l < %r" },
00056                    { BINARY_OP,  9, "%l == %r" },
00057                    { BINARY_OP, 10, "%l > %r" },
00058                    { BINARY_OP, 10, "%l <= %r" },
00059                    { BINARY_OP,  9, "%l != %r" },
00060                    { BINARY_OP, 10, "%l >= %r" },
00061                  { BINARY_OP, 15, SPECIAL_FMT },
00062                 { BINARY_OP, 15, SPECIAL_FMT },
00063 
00064 
00065 
00066                { BINARY_OP,  2, "%l = %r" },
00067                { BINARY_OP,  2, "%l += %r" },
00068                { BINARY_OP,  2, "%l *= %r" },
00069                  { BINARY_OP, 14, "%l" },
00070                { BINARY_OP, 11, "%l << %r" },
00071                   { BINARY_OP, 13, "%l %% %r" },
00072                 { BINARY_OP,  1, "%l, %r" },
00073 
00074 
00075 
00076                 { BINARY_OP, 3, "%l ? %r" },
00077                 { BINARY_OP, 3, "%l : %r" },
00078                   { UNARY_OP,  0, "abs(%l)" },
00079                   { BINARY_OP,   0, SPECIAL_FMT },
00080                   { BINARY_OP,   0, SPECIAL_FMT },
00081                  { UNARY_OP, 14, "&%l" },
00082 
00083             { BINARY_OP, 15, SPECIAL_FMT },
00084                 { BINARY_OP,  6, "%l | %r" },
00085                { BINARY_OP,  8, "%l & %r" },
00086                { BINARY_OP,  7, "%l ^ %r" },
00087                { UNARY_OP,  14, "~ %l" },
00088                { BINARY_OP, 11, "%l >> %r" },
00089 
00090 
00091 
00092               { UNARY_OP,  14, "*%l" },
00093               { BINARY_OP,  2, "%l -= %r" },
00094               { BINARY_OP,  2, "%l /= %r" },
00095                 { BINARY_OP,  2, "%l %%= %r" },
00096              { BINARY_OP,  2, "%l <<= %r" },
00097              { BINARY_OP,  2, "%l >>= %r" },
00098              { BINARY_OP,  2, "%l &= %r" },
00099              { BINARY_OP,  2, "%l ^= %r" },
00100               { BINARY_OP,  2, "%l |= %r" },
00101                { UNARY_OP,  14, "++%l" },
00102                { UNARY_OP,  14, "--%l" },
00103                   { BINARY_OP, 15, "%l.%r" },
00104                 { BINARY_OP, 15, "%l -> %r"},
00105                  { UNARY_OP,  14, "-%l" },
00106                  { BINARY_OP, 0, "dmin(%l,%r)" },
00107                  { BINARY_OP, 0, "dmax(%l,%r)" },
00108               { BINARY_OP,  2, "%l = &%r" },
00109              { UNARY_OP, 15, "%l" },
00110              { UNARY_OP, 14, "(char *)&%l" },
00111                  { UNARY_OP, 0, "dabs(%l)" },
00112                  { BINARY_OP,   0, "min(%l,%r)" },
00113                  { BINARY_OP,   0, "max(%l,%r)" },
00114               { BINARY_OP,   0, "bit_test(%l,%r)" },
00115                { BINARY_OP,   0, "bit_clear(%l,%r)" },
00116                { BINARY_OP,   0, "bit_set(%l,%r)" },
00117 #ifdef TYQUAD
00118               { BINARY_OP,   0, "qbit_clear(%l,%r)" },
00119               { BINARY_OP,   0, "qbit_set(%l,%r)" },
00120 #endif
00121 
00122 
00123 
00124               { UNARY_OP,  14, "-(doublereal)%l" }
00125 }; 
00126 
00127 #define OPNEG_KLUDGE (sizeof(opcode_table)/sizeof(table_entry) - 1)
00128 
00129 extern int dneg;
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     if (e == (expptr) NULL)
00151         return;
00152 
00153     switch (e -> tag) {
00154         case TNAME:     out_name (fp, (struct Nameblock *) e);
00155                         return;
00156 
00157         case TCONST:    out_const(fp, &e->constblock);
00158                         goto end_out;
00159         case TEXPR:
00160                         break;
00161 
00162         case TADDR:     out_addr (fp, &(e -> addrblock));
00163                         goto end_out;
00164 
00165         case TPRIM:     if (!nerr)
00166                                 warn ("expr_out: got TPRIM");
00167                         output_prim (fp, &(e -> primblock));
00168                         return;
00169 
00170         case TLIST:     output_list (fp, &(e -> listblock));
00171  end_out:               frexpr(e);
00172                         return;
00173 
00174         case TIMPLDO:   err ("expr_out: got TIMPLDO");
00175                         return;
00176 
00177         case TERROR:
00178         default:
00179                         erri ("expr_out: bad tag '%d'", e -> tag);
00180     } 
00181 
00182 
00183 
00184 
00185 
00186     if (e -> exprblock.opcode == OPASSIGN && e -> exprblock.rightp &&
00187         e -> exprblock.rightp -> tag == TEXPR) {
00188         int opcode;
00189 
00190         opcode = e -> exprblock.rightp -> exprblock.opcode;
00191 
00192         if (opeqable[opcode]) {
00193             expptr leftp, rightp;
00194 
00195             if ((leftp = e -> exprblock.leftp) &&
00196                 (rightp = e -> exprblock.rightp -> exprblock.leftp)) {
00197 
00198                 if (same_ident (leftp, rightp)) {
00199                     expptr temp = e -> exprblock.rightp;
00200 
00201                     e -> exprblock.opcode = op_assign(opcode);
00202 
00203                     e -> exprblock.rightp = temp -> exprblock.rightp;
00204                     temp->exprblock.rightp = 0;
00205                     frexpr(temp);
00206                 } 
00207             } 
00208         } 
00209     } 
00210 
00211 
00212 
00213 
00214     {
00215         int opcode = e -> exprblock.opcode;
00216         expptr leftp = e -> exprblock.leftp;
00217         expptr rightp = e -> exprblock.rightp;
00218 
00219         if (leftp && rightp && (leftp -> headblock.vstg == STGARG ||
00220                 ISINT (leftp -> headblock.vtype)) &&
00221                 (opcode == OPPLUSEQ || opcode == OPMINUSEQ) &&
00222                 ISINT (rightp -> headblock.vtype) &&
00223                 ISICON (e -> exprblock.rightp) &&
00224                 (ISONE (e -> exprblock.rightp) ||
00225                 e -> exprblock.rightp -> constblock.Const.ci == -1)) {
00226 
00227 
00228 
00229             if (!ISONE (e -> exprblock.rightp))
00230                 opcode = (opcode == OPPLUSEQ) ? OPMINUSEQ : OPPLUSEQ;
00231 
00232 
00233 
00234             if (opcode == OPPLUSEQ)
00235                 e -> exprblock.opcode = OPPREINC;
00236             else
00237                 e -> exprblock.opcode = OPPREDEC;
00238 
00239 
00240 
00241             frexpr (e -> exprblock.rightp);
00242             e->exprblock.rightp = 0;
00243         } 
00244     } 
00245 
00246 
00247     if (is_unary_op (e -> exprblock.opcode))
00248         output_unary (fp, &(e -> exprblock));
00249     else if (is_binary_op (e -> exprblock.opcode))
00250         output_binary (fp, &(e -> exprblock));
00251     else
00252         erri ("expr_out: bad opcode '%d'", (int) e -> exprblock.opcode);
00253 
00254     free((char *)e);
00255 
00256 } 
00257 
00258 
00259  void
00260 #ifdef KR_headers
00261 out_and_free_statement(outfile, expr)
00262         FILE *outfile;
00263         expptr expr;
00264 #else
00265 out_and_free_statement(FILE *outfile, expptr expr)
00266 #endif
00267 {
00268     if (expr)
00269         expr_out (outfile, expr);
00270 
00271     nice_printf (outfile, ";\n");
00272 } 
00273 
00274 
00275 
00276  int
00277 #ifdef KR_headers
00278 same_ident(left, right)
00279         expptr left;
00280         expptr right;
00281 #else
00282 same_ident(expptr left, expptr right)
00283 #endif
00284 {
00285     if (!left || !right)
00286         return 0;
00287 
00288     if (left -> tag == TNAME && right -> tag == TNAME && left == right)
00289         return 1;
00290 
00291     if (left -> tag == TADDR && right -> tag == TADDR &&
00292             left -> addrblock.uname_tag == right -> addrblock.uname_tag)
00293         switch (left -> addrblock.uname_tag) {
00294             case UNAM_REF:
00295             case UNAM_NAME:
00296 
00297 
00298 
00299                 if (left -> addrblock.user.name -> vdim ||
00300                         right -> addrblock.user.name -> vdim)
00301                     if (left -> addrblock.user.name !=
00302                             right -> addrblock.user.name ||
00303                             !same_expr (left -> addrblock.memoffset,
00304                             right -> addrblock.memoffset))
00305                         return 0;
00306 
00307                 return same_ident ((expptr) (left -> addrblock.user.name),
00308                         (expptr) right -> addrblock.user.name);
00309             case UNAM_IDENT:
00310                 return strcmp(left->addrblock.user.ident,
00311                                 right->addrblock.user.ident) == 0;
00312             case UNAM_CHARP:
00313                 return strcmp(left->addrblock.user.Charp,
00314                                 right->addrblock.user.Charp) == 0;
00315             default:
00316                 return 0;
00317         } 
00318 
00319     if (left->tag == TEXPR && left->exprblock.opcode == OPWHATSIN
00320         && right->tag == TEXPR && right->exprblock.opcode == OPWHATSIN)
00321                 return same_ident(left->exprblock.leftp,
00322                                  right->exprblock.leftp);
00323 
00324     return 0;
00325 } 
00326 
00327  static int
00328 #ifdef KR_headers
00329 samefpconst(c1, c2, n)
00330         register Constp c1;
00331         register Constp c2;
00332         register int n;
00333 #else
00334 samefpconst(register Constp c1, register Constp c2, register int n)
00335 #endif
00336 {
00337         char *s1, *s2;
00338         if (!c1->vstg && !c2->vstg)
00339                 return c1->Const.cd[n] == c2->Const.cd[n];
00340         s1 = c1->vstg ? c1->Const.cds[n] : dtos(c1->Const.cd[n]);
00341         s2 = c2->vstg ? c2->Const.cds[n] : dtos(c2->Const.cd[n]);
00342         return !strcmp(s1, s2);
00343         }
00344 
00345  static int
00346 #ifdef KR_headers
00347 sameconst(c1, c2)
00348         register Constp c1;
00349         register Constp c2;
00350 #else
00351 sameconst(register Constp c1, register Constp c2)
00352 #endif
00353 {
00354         switch(c1->vtype) {
00355                 case TYCOMPLEX:
00356                 case TYDCOMPLEX:
00357                         if (!samefpconst(c1,c2,1))
00358                                 return 0;
00359                 case TYREAL:
00360                 case TYDREAL:
00361                         return samefpconst(c1,c2,0);
00362                 case TYCHAR:
00363                         return c1->Const.ccp1.blanks == c2->Const.ccp1.blanks
00364                             &&     c1->vleng->constblock.Const.ci
00365                                 == c2->vleng->constblock.Const.ci
00366                             && !memcmp(c1->Const.ccp, c2->Const.ccp,
00367                                         (int)c1->vleng->constblock.Const.ci);
00368                 case TYSHORT:
00369                 case TYINT:
00370                 case TYLOGICAL:
00371                         return c1->Const.ci == c2->Const.ci;
00372                 }
00373         err("unexpected type in sameconst");
00374         return 0;
00375         }
00376 
00377 
00378 
00379 
00380 
00381  int
00382 #ifdef KR_headers
00383 same_expr(e1, e2)
00384         expptr e1;
00385         expptr e2;
00386 #else
00387 same_expr(expptr e1, expptr e2)
00388 #endif
00389 {
00390     if (!e1 || !e2)
00391         return !e1 && !e2;
00392 
00393     if (e1 -> tag != e2 -> tag || e1 -> headblock.vtype != e2 -> headblock.vtype)
00394         return 0;
00395 
00396     switch (e1 -> tag) {
00397         case TEXPR:
00398             if (e1 -> exprblock.opcode != e2 -> exprblock.opcode)
00399                 return 0;
00400 
00401             return same_expr (e1 -> exprblock.leftp, e2 -> exprblock.leftp) &&
00402                    same_expr (e1 -> exprblock.rightp, e2 -> exprblock.rightp);
00403         case TNAME:
00404         case TADDR:
00405             return same_ident (e1, e2);
00406         case TCONST:
00407             return sameconst(&e1->constblock, &e2->constblock);
00408         default:
00409             return 0;
00410     } 
00411 } 
00412 
00413 
00414 
00415  void
00416 #ifdef KR_headers
00417 out_name(fp, namep)
00418         FILE *fp;
00419         Namep namep;
00420 #else
00421 out_name(FILE *fp, Namep namep)
00422 #endif
00423 {
00424     extern int usedefsforcommon;
00425     Extsym *comm;
00426 
00427     if (namep == NULL)
00428         return;
00429 
00430 
00431 
00432 
00433     if (namep->vstg == STGCOMMON && !namep->vcommequiv && !usedefsforcommon) {
00434         comm = &extsymtab[namep->vardesc.varno];
00435         extern_out(fp, comm);
00436         nice_printf(fp, "%d.", comm->curno);
00437     } 
00438 
00439     if (namep->vprocclass == PTHISPROC && namep->vtype != TYSUBR)
00440         nice_printf(fp, xretslot[namep->vtype]->user.ident);
00441     else
00442         nice_printf (fp, "%s", namep->cvarname);
00443 } 
00444 
00445 
00446 static char *Longfmt = "%ld";
00447 
00448 #define cpd(n) cp->vstg ? cp->Const.cds[n] : dtos(cp->Const.cd[n])
00449 
00450  void
00451 #ifdef KR_headers
00452 out_const(fp, cp)
00453         FILE *fp;
00454         register Constp cp;
00455 #else
00456 out_const(FILE *fp, register Constp cp)
00457 #endif
00458 {
00459     static char real_buf[50], imag_buf[50];
00460     unsigned int k;
00461     int type = cp->vtype;
00462 
00463     switch (type) {
00464         case TYINT1:
00465         case TYSHORT:
00466             nice_printf (fp, "%ld", cp->Const.ci);      
00467             break;
00468         case TYLONG:
00469 #ifdef TYQUAD
00470         case TYQUAD:
00471 #endif
00472             nice_printf (fp, Longfmt, cp->Const.ci);    
00473             break;
00474         case TYREAL:
00475             nice_printf(fp, "%s", flconst(real_buf, cpd(0)));
00476             break;
00477         case TYDREAL:
00478             nice_printf(fp, "%s", cpd(0));
00479             break;
00480         case TYCOMPLEX:
00481             nice_printf(fp, cm_fmt_string, flconst(real_buf, cpd(0)),
00482                         flconst(imag_buf, cpd(1)));
00483             break;
00484         case TYDCOMPLEX:
00485             nice_printf(fp, dcm_fmt_string, cpd(0), cpd(1));
00486             break;
00487         case TYLOGICAL1:
00488         case TYLOGICAL2:
00489         case TYLOGICAL:
00490             nice_printf (fp, "%s", cp->Const.ci ? "TRUE_" : "FALSE_");
00491             break;
00492         case TYCHAR: {
00493             char *c = cp->Const.ccp, *ce;
00494 
00495             if (c == NULL) {
00496                 nice_printf (fp, "\"\"");
00497                 break;
00498             } 
00499 
00500             nice_printf (fp, "\"");
00501             ce = c + cp->vleng->constblock.Const.ci;
00502             while(c < ce) {
00503                 k = *(unsigned char *)c++;
00504                 nice_printf(fp, str_fmt[k], k);
00505                 }
00506             for(k = cp->Const.ccp1.blanks; k > 0; k--)
00507                 nice_printf(fp, " ");
00508             nice_printf (fp, "\"");
00509             break;
00510         } 
00511         default:
00512             erri ("out_const:  bad type '%d'", (int) type);
00513             break;
00514     } 
00515 
00516 } 
00517 #undef cpd
00518 
00519  static void
00520 #ifdef KR_headers
00521 out_args(fp, ep)
00522         FILE *fp;
00523         expptr ep;
00524 #else
00525 out_args(FILE *fp, expptr ep)
00526 #endif
00527 {
00528         chainp arglist;
00529 
00530         if(ep->tag != TLIST)
00531                 badtag("out_args", ep->tag);
00532         for(arglist = ep->listblock.listp;;) {
00533                 expr_out(fp, (expptr)arglist->datap);
00534                 arglist->datap = 0;
00535                 if (!(arglist = arglist->nextp))
00536                         break;
00537                 nice_printf(fp, ", ");
00538                 }
00539         }
00540 
00541 
00542 
00543 
00544 
00545  void
00546 #ifdef KR_headers
00547 out_addr(fp, addrp)
00548         FILE *fp;
00549         struct Addrblock *addrp;
00550 #else
00551 out_addr(FILE *fp, struct Addrblock *addrp)
00552 #endif
00553 {
00554         extern Extsym *extsymtab;
00555         int was_array = 0;
00556         char *s;
00557 
00558 
00559         if (addrp == NULL)
00560                 return;
00561         if (doin_setbound
00562                         && addrp->vstg == STGARG
00563                         && addrp->vtype != TYCHAR
00564                         && ISICON(addrp->memoffset)
00565                         && !addrp->memoffset->constblock.Const.ci)
00566                 nice_printf(fp, "*");
00567 
00568         switch (addrp -> uname_tag) {
00569             case UNAM_REF:
00570                 nice_printf(fp, "%s_%s(", addrp->user.name->cvarname,
00571                         addrp->cmplx_sub ? "subscr" : "ref");
00572                 out_args(fp, addrp->memoffset);
00573                 nice_printf(fp, ")");
00574                 return;
00575             case UNAM_NAME:
00576                 out_name (fp, addrp -> user.name);
00577                 break;
00578             case UNAM_IDENT:
00579                 if (*(s = addrp->user.ident) == ' ') {
00580                         if (multitype)
00581                                 nice_printf(fp, "%s",
00582                                         xretslot[addrp->vtype]->user.ident);
00583                         else
00584                                 nice_printf(fp, "%s", s+1);
00585                         }
00586                 else {
00587                         nice_printf(fp, "%s", s);
00588                         }
00589                 break;
00590             case UNAM_CHARP:
00591                 nice_printf(fp, "%s", addrp->user.Charp);
00592                 break;
00593             case UNAM_EXTERN:
00594                 extern_out (fp, &extsymtab[addrp -> memno]);
00595                 break;
00596             case UNAM_CONST:
00597                 switch(addrp->vstg) {
00598                         case STGCONST:
00599                                 out_const(fp, (Constp)addrp);
00600                                 break;
00601                         case STGMEMNO:
00602                                 output_literal (fp, addrp->memno,
00603                                         (Constp)addrp);
00604                                 break;
00605                         default:
00606                         Fatal("unexpected vstg in out_addr");
00607                         }
00608                 break;
00609             case UNAM_UNKNOWN:
00610             default:
00611                 nice_printf (fp, "Unknown Addrp");
00612                 break;
00613         } 
00614 
00615 
00616 
00617 
00618     if ((addrp->uname_tag == UNAM_NAME && addrp->user.name->vdim
00619                         || addrp->ntempelt > 1 || addrp->isarray)
00620         && addrp->vtype != TYCHAR) {
00621         expptr offset;
00622 
00623         was_array = 1;
00624 
00625         offset = addrp -> memoffset;
00626         addrp->memoffset = 0;
00627         if (ONEOF(addrp->vstg, M(STGCOMMON)|M(STGEQUIV))
00628                 && addrp -> uname_tag == UNAM_NAME
00629                 && !addrp->skip_offset)
00630             offset = mkexpr (OPMINUS, offset, mkintcon (
00631                     addrp -> user.name -> voffset));
00632 
00633         nice_printf (fp, "[");
00634 
00635         offset = mkexpr (OPSLASH, offset,
00636                 ICON (typesize[addrp -> vtype] * (addrp -> Field ? 2 : 1)));
00637         expr_out (fp, offset);
00638         nice_printf (fp, "]");
00639         }
00640 
00641 
00642 
00643     if (addrp -> Field && addrp -> uname_tag != UNAM_CONST &&
00644             addrp -> uname_tag != UNAM_UNKNOWN) {
00645         if (oneof_stg((addrp -> uname_tag == UNAM_NAME ? addrp -> user.name :
00646                 (Namep) NULL), addrp -> vstg, M(STGARG)|M(STGEQUIV))
00647                 && !was_array && (addrp->vclass != CLPROC || !multitype))
00648             nice_printf (fp, "->%s", addrp -> Field);
00649         else
00650             nice_printf (fp, ".%s", addrp -> Field);
00651     } 
00652 
00653 
00654 
00655     if (addrp->vtype == TYCHAR &&
00656             (addrp->vclass != CLPROC || addrp->uname_tag == UNAM_NAME
00657                         && addrp->user.name->vprocclass == PTHISPROC) &&
00658             addrp -> memoffset &&
00659             (addrp -> uname_tag != UNAM_NAME ||
00660              addrp -> user.name -> vtype == TYCHAR) &&
00661             (!ISICON (addrp -> memoffset) ||
00662              (addrp -> memoffset -> constblock.Const.ci))) {
00663 
00664         int use_paren = 0;
00665         expptr e = addrp -> memoffset;
00666 
00667         if (!e)
00668                 return;
00669         addrp->memoffset = 0;
00670 
00671         if (ONEOF(addrp->vstg, M(STGCOMMON)|M(STGEQUIV))
00672          && addrp -> uname_tag == UNAM_NAME) {
00673             e = mkexpr (OPMINUS, e, mkintcon (addrp -> user.name -> voffset));
00674 
00675 
00676             if (e->tag == TCONST && e->constblock.Const.ci == 0)
00677                 return;
00678         } 
00679 
00680 
00681 
00682 
00683 
00684 
00685         nice_printf (fp, " + ");
00686         if (e -> tag == TEXPR) {
00687             int arg_prec = op_precedence (e -> exprblock.opcode);
00688             int prec = op_precedence (OPPLUS);
00689             use_paren = arg_prec && (arg_prec < prec || (arg_prec == prec &&
00690                     is_left_assoc (OPPLUS)));
00691         } 
00692         if (use_paren) nice_printf (fp, "(");
00693         expr_out (fp, e);
00694         if (use_paren) nice_printf (fp, ")");
00695     } 
00696 } 
00697 
00698 
00699  static void
00700 #ifdef KR_headers
00701 output_literal(fp, memno, cp)
00702         FILE *fp;
00703         long memno;
00704         Constp cp;
00705 #else
00706 output_literal(FILE *fp, long memno, Constp cp)
00707 #endif
00708 {
00709     struct Literal *litp, *lastlit;
00710 
00711     lastlit = litpool + nliterals;
00712 
00713     for (litp = litpool; litp < lastlit; litp++) {
00714         if (litp -> litnum == memno)
00715             break;
00716     } 
00717 
00718     if (litp >= lastlit)
00719         out_const (fp, cp);
00720     else {
00721         nice_printf (fp, "%s", lit_name (litp));
00722         litp->lituse++;
00723         }
00724 } 
00725 
00726 
00727  static void
00728 #ifdef KR_headers
00729 output_prim(fp, primp)
00730         FILE *fp;
00731         struct Primblock *primp;
00732 #else
00733 output_prim(FILE *fp, struct Primblock *primp)
00734 #endif
00735 {
00736     if (primp == NULL)
00737         return;
00738 
00739     out_name (fp, primp -> namep);
00740     if (primp -> argsp)
00741         output_arg_list (fp, primp -> argsp);
00742 
00743     if (primp -> fcharp != (expptr) NULL || primp -> lcharp != (expptr) NULL)
00744         nice_printf (fp, "Sorry, no substrings yet");
00745 }
00746 
00747 
00748 
00749  static void
00750 #ifdef KR_headers
00751 output_arg_list(fp, listp)
00752         FILE *fp;
00753         struct Listblock *listp;
00754 #else
00755 output_arg_list(FILE *fp, struct Listblock *listp)
00756 #endif
00757 {
00758     chainp arg_list;
00759 
00760     if (listp == (struct Listblock *) NULL || listp -> listp == (chainp) NULL)
00761         return;
00762 
00763     nice_printf (fp, "(");
00764 
00765     for (arg_list = listp -> listp; arg_list; arg_list = arg_list -> nextp) {
00766         expr_out (fp, (expptr) arg_list -> datap);
00767         if (arg_list -> nextp != (chainp) NULL)
00768 
00769 
00770 
00771 
00772             nice_printf (fp, ",");
00773     } 
00774 
00775     nice_printf (fp, ")");
00776 } 
00777 
00778 
00779 
00780  static void
00781 #ifdef KR_headers
00782 output_unary(fp, e)
00783         FILE *fp;
00784         struct Exprblock *e;
00785 #else
00786 output_unary(FILE *fp, struct Exprblock *e)
00787 #endif
00788 {
00789     if (e == NULL)
00790         return;
00791 
00792     switch (e -> opcode) {
00793         case OPNEG:
00794                 if (e->vtype == TYREAL && dneg) {
00795                         e->opcode = OPNEG_KLUDGE;
00796                         output_binary(fp,e);
00797                         e->opcode = OPNEG;
00798                         break;
00799                         }
00800         case OPNEG1:
00801         case OPNOT:
00802         case OPABS:
00803         case OPBITNOT:
00804         case OPWHATSIN:
00805         case OPPREINC:
00806         case OPPREDEC:
00807         case OPADDR:
00808         case OPIDENTITY:
00809         case OPCHARCAST:
00810         case OPDABS:
00811             output_binary (fp, e);
00812             break;
00813         case OPCALL:
00814         case OPCCALL:
00815             nice_printf (fp, "Sorry, no OPCALL yet");
00816             break;
00817         default:
00818             erri ("output_unary: bad opcode", (int) e -> opcode);
00819             break;
00820     } 
00821 } 
00822 
00823 
00824  static char *
00825 #ifdef KR_headers
00826 findconst(m)
00827         register long m;
00828 #else
00829 findconst(register long m)
00830 #endif
00831 {
00832         register struct Literal *litp, *litpe;
00833 
00834         litp = litpool;
00835         for(litpe = litp + nliterals; litp < litpe; litp++)
00836                 if (litp->litnum ==  m)
00837                         return litp->cds[0];
00838         Fatal("findconst failure!");
00839         return 0;
00840         }
00841 
00842  static int
00843 #ifdef KR_headers
00844 opconv_fudge(fp, e)
00845         FILE *fp;
00846         struct Exprblock *e;
00847 #else
00848 opconv_fudge(FILE *fp, struct Exprblock *e)
00849 #endif
00850 {
00851         
00852         register expptr lp;
00853         register union Expression *Offset;
00854         register char *cp;
00855         int lt;
00856         char buf[8], *s;
00857         unsigned int k;
00858         Namep np;
00859         Addrp ap;
00860 
00861         if (!(lp = e->leftp))   
00862                 return 1;
00863         lt = lp->headblock.vtype;
00864         if (lt == TYCHAR) {
00865                 switch(lp->tag) {
00866                         case TNAME:
00867                                 nice_printf(fp, "*(unsigned char *)");
00868                                 out_name(fp, (Namep)lp);
00869                                 return 1;
00870                         case TCONST:
00871  tconst:
00872                                 cp = lp->constblock.Const.ccp;
00873  tconst1:
00874                                 k = *(unsigned char *)cp;
00875                                 if (k < 128) { 
00876                                         sprintf(buf, chr_fmt[k], k);
00877                                         nice_printf(fp, "'%s'", buf);
00878                                         }
00879                                 else
00880                                         nice_printf(fp, "%d", k);
00881                                 return 1;
00882                         case TADDR:
00883                                 switch(lp->addrblock.vstg) {
00884                                     case STGMEMNO:
00885                                         if (halign && e->vtype != TYCHAR) {
00886                                                 nice_printf(fp, "*(%s *)",
00887                                                     c_type_decl(e->vtype,0));
00888                                                 expr_out(fp, lp);
00889                                                 return 1;
00890                                                 }
00891                                         cp = findconst(lp->addrblock.memno);
00892                                         goto tconst1;
00893                                     case STGCONST:
00894                                         goto tconst;
00895                                     }
00896                                 lp->addrblock.vtype = tyint;
00897                                 Offset = lp->addrblock.memoffset;
00898                                 switch(lp->addrblock.uname_tag) {
00899                                   case UNAM_REF:
00900                                         nice_printf(fp, "*(unsigned char *)");
00901                                         return 0;
00902                                   case UNAM_NAME:
00903                                         np = lp->addrblock.user.name;
00904                                         if (ONEOF(np->vstg,
00905                                             M(STGCOMMON)|M(STGEQUIV)))
00906                                                 Offset = mkexpr(OPMINUS, Offset,
00907                                                         ICON(np->voffset));
00908                                         }
00909                                 lp->addrblock.memoffset = Offset ?
00910                                         mkexpr(OPSTAR, Offset,
00911                                                 ICON(typesize[tyint]))
00912                                         : ICON(0);
00913                                 lp->addrblock.isarray = 1;
00914                                 
00915                                 
00916                                 lp->addrblock.vstg = STGUNKNOWN;
00917                                 nice_printf(fp, "*(unsigned char *)&");
00918                                 return 0;
00919                         default:
00920                                 badtag("opconv_fudge", lp->tag);
00921                         }
00922                 }
00923         if (lt != e->vtype) {
00924                 s = c_type_decl(e->vtype, 0);
00925                 if (ISCOMPLEX(lt)) {
00926                         np = (Namep)e->leftp;
00927                         switch(np->tag) {
00928                           case TNAME:
00929                                 nice_printf(fp, "(%s) %s.r", s,
00930                                         np->cvarname);
00931                                 return 1;
00932                           case TADDR:
00933                                 ap = (Addrp)np;
00934                                 switch(ap->uname_tag) {
00935                                   case UNAM_IDENT:
00936                                         nice_printf(fp, "(%s) %s.r", s,
00937                                                 ap->user.ident);
00938                                         return 1;
00939                                   case UNAM_NAME:
00940                                         nice_printf(fp, "(%s) ", s);
00941                                         out_addr(fp, ap);
00942                                         nice_printf(fp, ".r");
00943                                         return 1;
00944                                   }
00945                           default:
00946                                 fatali("Unexpected tag %d in opconv_fudge",
00947                                         np->tag);
00948                           }
00949                         }
00950                 nice_printf(fp, "(%s) ", s);
00951                 }
00952         return 0;
00953         }
00954 
00955 
00956  static void
00957 #ifdef KR_headers
00958 output_binary(fp, e)
00959         FILE *fp;
00960         struct Exprblock *e;
00961 #else
00962 output_binary(FILE *fp, struct Exprblock *e)
00963 #endif
00964 {
00965     char *format;
00966     extern table_entry opcode_table[];
00967     int prec;
00968 
00969     if (e == NULL || e -> tag != TEXPR)
00970         return;
00971 
00972 
00973 
00974 
00975 
00976 
00977 
00978 
00979 
00980 
00981 
00982 
00983 
00984 
00985 
00986 
00987     if ((e -> opcode == OPPLUS || e -> opcode == OPMINUS) &&
00988             e -> rightp && e -> rightp -> tag == TCONST &&
00989             isnegative_const (&(e -> rightp -> constblock)) &&
00990             is_negatable (&(e -> rightp -> constblock))) {
00991 
00992         e -> opcode = (e -> opcode == OPPLUS) ? OPMINUS : OPPLUS;
00993         negate_const (&(e -> rightp -> constblock));
00994     } 
00995 
00996     prec = op_precedence (e -> opcode);
00997     format = op_format (e -> opcode);
00998 
00999     if (format != SPECIAL_FMT) {
01000         while (*format) {
01001             if (*format == '%') {
01002                 int arg_prec, use_paren = 0;
01003                 expptr lp, rp;
01004 
01005                 switch (*(format + 1)) {
01006                     case 'l':
01007                         lp = e->leftp;
01008                         if (lp && lp->tag == TEXPR) {
01009                             arg_prec = op_precedence(lp->exprblock.opcode);
01010 
01011                             use_paren = arg_prec &&
01012                                 (arg_prec < prec || (arg_prec == prec &&
01013                                     is_right_assoc (prec)));
01014                         } 
01015                         if (e->opcode == OPCONV && opconv_fudge(fp,e))
01016                                 break;
01017                         if (use_paren)
01018                             nice_printf (fp, "(");
01019                         expr_out(fp, lp);
01020                         if (use_paren)
01021                             nice_printf (fp, ")");
01022                         break;
01023                     case 'r':
01024                         rp = e->rightp;
01025                         if (rp && rp->tag == TEXPR) {
01026                             arg_prec = op_precedence(rp->exprblock.opcode);
01027 
01028                             use_paren = arg_prec &&
01029                                 (arg_prec < prec || (arg_prec == prec &&
01030                                     is_left_assoc (prec)));
01031                             use_paren = use_paren ||
01032                                 (rp->exprblock.opcode == OPNEG
01033                                 && prec >= op_precedence(OPMINUS));
01034                         } 
01035                         if (use_paren)
01036                             nice_printf (fp, "(");
01037                         expr_out(fp, rp);
01038                         if (use_paren)
01039                             nice_printf (fp, ")");
01040                         break;
01041                     case '\0':
01042                     case '%':
01043                         nice_printf (fp, "%%");
01044                         break;
01045                     default:
01046                         erri ("output_binary: format err: '%%%c' illegal",
01047                                 (int) *(format + 1));
01048                         break;
01049                 } 
01050                 format += 2;
01051             } else
01052                 nice_printf (fp, "%c", *format++);
01053         } 
01054     } else {
01055 
01056 
01057 
01058         switch (e -> opcode) {
01059                 case OPCCALL:
01060                 case OPCALL:
01061                         out_call (fp, (int) e -> opcode, e -> vtype,
01062                                         e -> vleng, e -> leftp, e -> rightp);
01063                         break;
01064 
01065                 case OPCOMMA_ARG:
01066                         doin_setbound = 1;
01067                         nice_printf(fp, "(");
01068                         expr_out(fp, e->leftp);
01069                         nice_printf(fp, ", &");
01070                         doin_setbound = 0;
01071                         expr_out(fp, e->rightp);
01072                         nice_printf(fp, ")");
01073                         break;
01074 
01075                 case OPADDR:
01076                 default:
01077                         nice_printf (fp, "Sorry, can't format OPCODE '%d'",
01078                                 e -> opcode);
01079                         break;
01080                 }
01081 
01082     } 
01083 } 
01084 
01085  void
01086 #ifdef KR_headers
01087 out_call(outfile, op, ftype, len, name, args)
01088         FILE *outfile;
01089         int op;
01090         int ftype;
01091         expptr len;
01092         expptr name;
01093         expptr args;
01094 #else
01095 out_call(FILE *outfile, int op, int ftype, expptr len, expptr name, expptr args)
01096 #endif
01097 {
01098     chainp arglist;             
01099     chainp cp;                  
01100     Addrp ret_val = (Addrp) NULL;
01101                                 
01102 
01103     int byvalue;                
01104 
01105     int done_once;              
01106     int narg, t;
01107     register expptr q;
01108     long L;
01109     Argtypes *at;
01110     Atype *A, *Ac;
01111     Namep np;
01112     extern int forcereal;
01113 
01114 
01115 
01116     byvalue = op == OPCCALL;
01117 
01118     if (args)
01119         arglist = args -> listblock.listp;
01120     else
01121         arglist = CHNULL;
01122 
01123 
01124 
01125     if (ftype == TYCHAR)
01126         if (ISICON (len)) {
01127             ret_val = (Addrp) (arglist -> datap);
01128             arglist = arglist -> nextp;
01129         } else {
01130             err ("adjustable character function");
01131             return;
01132         } 
01133 
01134 
01135 
01136     else if (ISCOMPLEX (ftype)) {
01137         ret_val = (Addrp) (arglist -> datap);
01138         arglist = arglist -> nextp;
01139     } 
01140 
01141     
01142     np = name->tag == TEXPR && name->exprblock.opcode == OPWHATSIN
01143         ? (Namep)name->exprblock.leftp : (Namep)name;
01144 
01145     A = Ac = 0;
01146     if (np->tag == TNAME && (at = np->arginfo)) {
01147         if (at->nargs > 0)
01148                 A = at->atypes;
01149         if (Ansi && (at->defined || at->nargs > 0))
01150                 Ac = at->atypes;
01151         }
01152 
01153 
01154 
01155     if (ftype == TYREAL && forcereal)
01156         nice_printf(outfile, "(real)");
01157     if (name -> tag == TEXPR && name -> exprblock.opcode == OPWHATSIN) {
01158         nice_printf (outfile, "(");
01159         expr_out (outfile, name);
01160         nice_printf (outfile, ")");
01161         }
01162     else
01163         expr_out(outfile, name);
01164 
01165     nice_printf(outfile, "(");
01166 
01167     if (ret_val) {
01168         if (ISCOMPLEX (ftype))
01169             nice_printf (outfile, "&");
01170         expr_out (outfile, (expptr) ret_val);
01171         if (Ac)
01172                 Ac++;
01173 
01174 
01175 
01176 
01177     } 
01178     done_once = ret_val ? TRUE : FALSE;
01179 
01180 
01181 
01182     narg = -1;
01183     for (cp = arglist; cp; cp = cp -> nextp, done_once = TRUE) {
01184 
01185         if (done_once)
01186             nice_printf (outfile, ", ");
01187         narg++;
01188 
01189         if (!( q = (expptr)cp->datap) )
01190                 continue;
01191 
01192         if (q->tag == TADDR) {
01193                 if (q->addrblock.vtype > TYERROR) {
01194                         
01195                         nice_printf(outfile, "&%s", q->addrblock.user.ident);
01196                         continue;
01197                         }
01198                 if (!byvalue && q->addrblock.isarray
01199                 && q->addrblock.vtype != TYCHAR
01200                 && q->addrblock.memoffset->tag == TCONST) {
01201 
01202                         
01203                         
01204                         L = q->addrblock.memoffset->constblock.Const.ci;
01205                         if (ONEOF(q->addrblock.vstg, M(STGCOMMON)|M(STGEQUIV))
01206                                         && q->addrblock.uname_tag == UNAM_NAME)
01207                                 L -= q->addrblock.user.name->voffset;
01208                         if (L)
01209                                 goto skip_deref;
01210 
01211                         if (Ac && narg < at->dnargs
01212                          && q->headblock.vtype != (t = Ac[narg].type)
01213                          && t > TYADDR && t < TYSUBR)
01214                                 nice_printf(outfile, "(%s*)", typename[t]);
01215 
01216                         
01217                         
01218 
01219                         switch(q->addrblock.uname_tag) {
01220                             case UNAM_NAME:
01221                                 out_name(outfile, q->addrblock.user.name);
01222                                 continue;
01223                             case UNAM_IDENT:
01224                                 nice_printf(outfile, "%s",
01225                                         q->addrblock.user.ident);
01226                                 continue;
01227                             case UNAM_CHARP:
01228                                 nice_printf(outfile, "%s",
01229                                         q->addrblock.user.Charp);
01230                                 continue;
01231                             case UNAM_EXTERN:
01232                                 extern_out(outfile,
01233                                         &extsymtab[q->addrblock.memno]);
01234                                 continue;
01235                             }
01236                         }
01237                 }
01238 
01239 
01240 
01241  skip_deref:
01242         if (q -> tag == TEXPR && q -> exprblock.opcode == OPWHATSIN)
01243             q = q -> exprblock.leftp;
01244 
01245         if (q->headblock.vclass == CLPROC) {
01246             if (Castargs && (q->tag != TNAME
01247                                 || q->nameblock.vprocclass != PTHISPROC)
01248                          && (q->tag != TADDR
01249                                 || q->addrblock.uname_tag != UNAM_NAME
01250                                 || q->addrblock.user.name->vprocclass
01251                                                                 != PTHISPROC))
01252                 {
01253                 if (A && (t = A[narg].type) >= 200)
01254                         t %= 100;
01255                 else {
01256                         t = q->headblock.vtype;
01257                         if (q->tag == TNAME && q->nameblock.vimpltype)
01258                                 t = TYUNKNOWN;
01259                         }
01260                 nice_printf(outfile, "(%s)", usedcasts[t] = casttypes[t]);
01261                 }
01262             }
01263         else if (Ac && narg < at->dnargs
01264                 && q->headblock.vtype != (t = Ac[narg].type)
01265                 && t > TYADDR && t < TYSUBR)
01266                 nice_printf(outfile, "(%s*)", typename[t]);
01267 
01268         if ((q -> tag == TADDR || q-> tag == TNAME) &&
01269                 (byvalue || q -> headblock.vstg != STGREG)) {
01270             if (q -> headblock.vtype != TYCHAR)
01271               if (byvalue) {
01272 
01273                 if (q -> tag == TADDR &&
01274                         q -> addrblock.uname_tag == UNAM_NAME &&
01275                         ! q -> addrblock.user.name -> vdim &&
01276                         oneof_stg(q -> addrblock.user.name, q -> addrblock.vstg,
01277                                         M(STGARG)|M(STGEQUIV)) &&
01278                         ! ISCOMPLEX(q->addrblock.user.name->vtype))
01279                     nice_printf (outfile, "*");
01280                 else if (q -> tag == TNAME
01281                         && oneof_stg(&q->nameblock, q -> nameblock.vstg,
01282                                 M(STGARG)|M(STGEQUIV))
01283                         && !(q -> nameblock.vdim))
01284                     nice_printf (outfile, "*");
01285 
01286               } else {
01287                 expptr memoffset;
01288 
01289                 if (q->tag == TADDR &&
01290                         !ONEOF (q -> addrblock.vstg, M(STGEXT)|M(STGLENG))
01291                         && (
01292                         ONEOF(q->addrblock.vstg,
01293                                 M(STGCOMMON)|M(STGEQUIV)|M(STGMEMNO))
01294                         || ((memoffset = q->addrblock.memoffset)
01295                                 && (!ISICON(memoffset)
01296                                 || memoffset->constblock.Const.ci)))
01297                         || ONEOF(q->addrblock.vstg,
01298                                         M(STGINIT)|M(STGAUTO)|M(STGBSS))
01299                                 && !q->addrblock.isarray)
01300                     nice_printf (outfile, "&");
01301                 else if (q -> tag == TNAME
01302                         && !oneof_stg(&q->nameblock, q -> nameblock.vstg,
01303                                 M(STGARG)|M(STGEXT)|M(STGEQUIV)))
01304                     nice_printf (outfile, "&");
01305             } 
01306 
01307             expr_out (outfile, q);
01308         } 
01309 
01310 
01311 
01312         else if (q -> tag == TCONST) {
01313             if (tyioint == TYLONG)
01314                 Longfmt = "%ldL";
01315             out_const(outfile, &q->constblock);
01316             Longfmt = "%ld";
01317             }
01318 
01319 
01320 
01321 
01322 
01323         else if (!ISCOMPLEX (q -> headblock.vtype) && !ISCHAR (q)){
01324             int use_paren = q -> tag == TEXPR &&
01325                     op_precedence (q -> exprblock.opcode) <=
01326                     op_precedence (OPCOMMA);
01327 
01328             if (use_paren) nice_printf (outfile, "(");
01329             expr_out (outfile, q);
01330             if (use_paren) nice_printf (outfile, ")");
01331         } 
01332         else
01333             err ("out_call:  unknown parameter");
01334 
01335     } 
01336 
01337     if (arglist)
01338         frchain (&arglist);
01339 
01340     nice_printf (outfile, ")");
01341 
01342 } 
01343 
01344 
01345  char *
01346 #ifdef KR_headers
01347 flconst(buf, x)
01348         char *buf;
01349         char *x;
01350 #else
01351 flconst(char *buf, char *x)
01352 #endif
01353 {
01354         sprintf(buf, fl_fmt_string, x);
01355         return buf;
01356         }
01357 
01358  char *
01359 #ifdef KR_headers
01360 dtos(x)
01361         double x;
01362 #else
01363 dtos(double x)
01364 #endif
01365 {
01366         static char buf[64];
01367 #ifdef USE_DTOA
01368         g_fmt(buf, x);
01369 #else
01370         sprintf(buf, db_fmt_string, x);
01371 #endif
01372         return strcpy(mem(strlen(buf)+1,0), buf);
01373         }
01374 
01375 char tr_tab[Table_size];
01376 
01377 
01378 
01379 
01380 
01381  void
01382 out_init(Void)
01383 {
01384     extern int tab_size;
01385     register char *s;
01386 
01387     s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_+-.";
01388     while(*s)
01389         tr_tab[*s++] = 3;
01390     tr_tab['>'] = 1;
01391 
01392         opeqable[OPPLUS] = 1;
01393         opeqable[OPMINUS] = 1;
01394         opeqable[OPSTAR] = 1;
01395         opeqable[OPSLASH] = 1;
01396         opeqable[OPMOD] = 1;
01397         opeqable[OPLSHIFT] = 1;
01398         opeqable[OPBITAND] = 1;
01399         opeqable[OPBITXOR] = 1;
01400         opeqable[OPBITOR ] = 1;
01401 
01402 
01403 
01404 
01405     if (fl_fmt_string == NULL || *fl_fmt_string == '\0')
01406         fl_fmt_string = Ansi == 1 ? "%sf" : "(float)%s";
01407 
01408     if (db_fmt_string == NULL || *db_fmt_string == '\0')
01409         db_fmt_string = "%.17g";
01410 
01411 
01412 
01413 
01414 
01415 
01416     if (cm_fmt_string == NULL || *cm_fmt_string == '\0') {
01417         cm_fmt_string = "{%s,%s}";
01418     } 
01419 
01420     if (dcm_fmt_string == NULL || *dcm_fmt_string == '\0') {
01421         dcm_fmt_string = "{%s,%s}";
01422     } 
01423 
01424     tab_size = 4;
01425 } 
01426 
01427 
01428  void
01429 #ifdef KR_headers
01430 extern_out(fp, extsym)
01431         FILE *fp;
01432         Extsym *extsym;
01433 #else
01434 extern_out(FILE *fp, Extsym *extsym)
01435 #endif
01436 {
01437     if (extsym == (Extsym *) NULL)
01438         return;
01439 
01440     nice_printf (fp, "%s", extsym->cextname);
01441 
01442 } 
01443 
01444 
01445 
01446  static void
01447 #ifdef KR_headers
01448 output_list(fp, listp)
01449         FILE *fp;
01450         struct Listblock *listp;
01451 #else
01452 output_list(FILE *fp, struct Listblock *listp)
01453 #endif
01454 {
01455     int did_one = 0;
01456     chainp elts;
01457 
01458     nice_printf (fp, "(");
01459     if (listp)
01460         for (elts = listp -> listp; elts; elts = elts -> nextp) {
01461             if (elts -> datap) {
01462                 if (did_one)
01463                     nice_printf (fp, ", ");
01464                 expr_out (fp, (expptr) elts -> datap);
01465                 did_one = 1;
01466             } 
01467         } 
01468     nice_printf (fp, ")");
01469 } 
01470 
01471 
01472  void
01473 #ifdef KR_headers
01474 out_asgoto(outfile, expr)
01475         FILE *outfile;
01476         expptr expr;
01477 #else
01478 out_asgoto(FILE *outfile, expptr expr)
01479 #endif
01480 {
01481     chainp value;
01482     Namep namep;
01483     int k;
01484 
01485     if (expr == (expptr) NULL) {
01486         err ("out_asgoto:  NULL variable expr");
01487         return;
01488     } 
01489 
01490     nice_printf (outfile, Ansi ? "switch (" : "switch ((int)"); 
01491     expr_out (outfile, expr);
01492     nice_printf (outfile, ") {\n");
01493     next_tab (outfile);
01494 
01495 
01496 
01497     switch(expr->tag) {
01498         case TNAME:
01499                 
01500                 namep = &expr->nameblock;
01501                 break;
01502         case TEXPR:
01503                 if (expr->exprblock.opcode == OPWHATSIN
01504                  && expr->exprblock.leftp->tag == TNAME)
01505                         
01506                         namep = &expr->exprblock.leftp->nameblock;
01507                 else
01508                         goto bad;
01509                 break;
01510         case TADDR:
01511                 if (expr->addrblock.uname_tag == UNAM_NAME) {
01512                         
01513                         namep = expr->addrblock.user.name;
01514                         break;
01515                         }
01516         default:
01517  bad:
01518                 err("out_asgoto:  bad expr");
01519                 return;
01520         }
01521 
01522     for(k = 0, value = namep -> varxptr.assigned_values; value;
01523             value = value->nextp, k++) {
01524         nice_printf (outfile, "case %d: goto %s;\n", k,
01525                 user_label((long)value->datap));
01526     } 
01527     prev_tab (outfile);
01528 
01529     nice_printf (outfile, "}\n");
01530 } 
01531 
01532  void
01533 #ifdef KR_headers
01534 out_if(outfile, expr)
01535         FILE *outfile;
01536         expptr expr;
01537 #else
01538 out_if(FILE *outfile, expptr expr)
01539 #endif
01540 {
01541     nice_printf (outfile, "if (");
01542     expr_out (outfile, expr);
01543     nice_printf (outfile, ") {\n");
01544     next_tab (outfile);
01545 } 
01546 
01547  static void
01548 #ifdef KR_headers
01549 output_rbrace(outfile, s)
01550         FILE *outfile;
01551         char *s;
01552 #else
01553 output_rbrace(FILE *outfile, char *s)
01554 #endif
01555 {
01556         extern int last_was_label;
01557         register char *fmt;
01558 
01559         if (last_was_label) {
01560                 last_was_label = 0;
01561                 fmt = ";%s";
01562                 }
01563         else
01564                 fmt = "%s";
01565         nice_printf(outfile, fmt, s);
01566         }
01567 
01568  void
01569 #ifdef KR_headers
01570 out_else(outfile)
01571         FILE *outfile;
01572 #else
01573 out_else(FILE *outfile)
01574 #endif
01575 {
01576     prev_tab (outfile);
01577     output_rbrace(outfile, "} else {\n");
01578     next_tab (outfile);
01579 } 
01580 
01581  void
01582 #ifdef KR_headers
01583 elif_out(outfile, expr)
01584         FILE *outfile;
01585         expptr expr;
01586 #else
01587 elif_out(FILE *outfile, expptr expr)
01588 #endif
01589 {
01590     prev_tab (outfile);
01591     output_rbrace(outfile, "} else ");
01592     out_if (outfile, expr);
01593 } 
01594 
01595  void
01596 #ifdef KR_headers
01597 endif_out(outfile)
01598         FILE *outfile;
01599 #else
01600 endif_out(FILE *outfile)
01601 #endif
01602 {
01603     prev_tab (outfile);
01604     output_rbrace(outfile, "}\n");
01605 } 
01606 
01607  void
01608 #ifdef KR_headers
01609 end_else_out(outfile)
01610         FILE *outfile;
01611 #else
01612 end_else_out(FILE *outfile)
01613 #endif
01614 {
01615     prev_tab (outfile);
01616     output_rbrace(outfile, "}\n");
01617 } 
01618 
01619 
01620 
01621  void
01622 #ifdef KR_headers
01623 compgoto_out(outfile, index, labels)
01624         FILE *outfile;
01625         expptr index;
01626         expptr labels;
01627 #else
01628 compgoto_out(FILE *outfile, expptr index, expptr labels)
01629 #endif
01630 {
01631     char *s1, *s2;
01632 
01633     if (index == ENULL)
01634         err ("compgoto_out:  null index for computed goto");
01635     else if (labels && labels -> tag != TLIST)
01636         erri ("compgoto_out:  expected label list, got tag '%d'",
01637                 labels -> tag);
01638     else {
01639         chainp elts;
01640         int i = 1;
01641 
01642         s2 =  ") {\n"; 
01643         if (Ansi)
01644                 s1 = "switch ("; 
01645         else if (index->tag == TNAME || index->tag == TEXPR
01646                                 && index->exprblock.opcode == OPWHATSIN)
01647                 s1 = "switch ((int)"; 
01648         else {
01649                 s1 = "switch ((int)(";
01650                 s2 = ")) {\n"; 
01651                 }
01652         nice_printf(outfile, s1);
01653         expr_out (outfile, index);
01654         nice_printf (outfile, s2);
01655         next_tab (outfile);
01656 
01657         for (elts = labels -> listblock.listp; elts; elts = elts -> nextp, i++) {
01658             if (elts -> datap) {
01659                 if (ISICON(((expptr) (elts -> datap))))
01660                     nice_printf (outfile, "case %d:  goto %s;\n", i,
01661                         user_label(((expptr)(elts->datap))->constblock.Const.ci));
01662                 else
01663                     err ("compgoto_out:  bad label in label list");
01664             } 
01665         } 
01666         prev_tab (outfile);
01667         nice_printf (outfile,  "}\n");
01668     } 
01669 } 
01670 
01671 
01672  void
01673 #ifdef KR_headers
01674 out_for(outfile, init, test, inc)
01675         FILE *outfile;
01676         expptr init;
01677         expptr test;
01678         expptr inc;
01679 #else
01680 out_for(FILE *outfile, expptr init, expptr test, expptr inc)
01681 #endif
01682 {
01683     nice_printf (outfile, "for (");
01684     expr_out (outfile, init);
01685     nice_printf (outfile, "; ");
01686     expr_out (outfile, test);
01687     nice_printf (outfile, "; ");
01688     expr_out (outfile, inc);
01689     nice_printf (outfile, ") {\n");
01690     next_tab (outfile);
01691 } 
01692 
01693 
01694  void
01695 #ifdef KR_headers
01696 out_end_for(outfile)
01697         FILE *outfile;
01698 #else
01699 out_end_for(FILE *outfile)
01700 #endif
01701 {
01702     prev_tab (outfile);
01703     nice_printf (outfile, "}\n");
01704 }