Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wn2f_io.cxx
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 /* ====================================================================
00037  * ====================================================================
00038  *
00039  *
00040  * Revision history:
00041  *  5-June-95 - Original Version
00042  *
00043  * Description:
00044  *
00045  *   Translate an OPC_IO subtree into the appropriate Fortran constructs.
00046  *   Recursive translation of WN nodes should only use WN2F_Translate(),
00047  *   with exception of IO_ITEMS which are handled locally!
00048  *
00049  *   The Fortran I/O statements have the following syntax:
00050  *
00051  *      <statement_keyword> <control_list> <I/O list>
00052  *
00053  *   where
00054  *
00055  *      <statement_keyword> ::= <IOS enumeration as defined in wio.h>
00056  *      <control_list>      ::= <IOU, IOF, and IOC items from wio.h>
00057  *      <I/O list>          ::= <IOL items from wio.h>
00058  *
00059  * ====================================================================
00060  * ====================================================================
00061  */
00062 
00063 
00064 #include "whirl2f_common.h"
00065 #include "wio.h"
00066 #include "wutil.h"
00067 #include "PUinfo.h"          /* In be/whirl2c directory */
00068 #include "wn2f.h"
00069 #include "st2f.h"
00070 #include "ty2f.h"
00071 #include "tcon2f.h"
00072 #include "wn2f_io.h"
00073 #include "wn2f_load_store.h"
00074 
00075 
00076 /* A rather special IOC item to replace an IOF_LABEL item.  This
00077  * value is only valid when WN2F_CONTEXT_origfmt_ioctrl is TRUE!
00078  */
00079 static UINT32       Origfmt_Ioctrl_Label;
00080 static TOKEN_BUFFER Format_Stmts = NULL;
00081 static TOKEN_BUFFER Ios_Prefix_Tokens = NULL;
00082 
00083 typedef void (*IO_STMT_HANDLER)(TOKEN_BUFFER, WN *, WN2F_CONTEXT);
00084 static IO_STMT_HANDLER Ios_Handler[IOSTATEMENT_LAST+1];
00085 
00086 
00087 #define WN_IOITEM(x) (IOITEM) WN_io_item(x)
00088 #define WN_IOSTMT(x) (IOSTATEMENT) WN_io_statement(x)
00089 
00090 /* several craylib/dope items represent a no-op by a zero inconst...*/
00091 
00092 #define IS_IO_NULL_OPR(wn) ((WN_operator(wn) == OPR_INTCONST) && (WN_const_val(wn) == 0))
00093 
00094 /*------------------------- Io Utility Routines -----------------------*/
00095 /*---------------------------------------------------------------------*/
00096 
00097 static void 
00098 WN2F_Append_IO_CtrlList(TOKEN_BUFFER tokens, 
00099                         WN          *ios,
00100                         INT          from_kid,
00101                         INT          to_kid,
00102                         BOOL         use_keyword,
00103                         WN2F_CONTEXT context)
00104 {
00105    /* Emit an IO control list (IOU, IOF, and IOC with explicit
00106     * keywords.
00107     */
00108    BOOL         emitted, emitted2;
00109    INT          ios_kid;
00110    TOKEN_BUFFER item_buffer;
00111    
00112    Append_Token_Special(tokens, '(');
00113 
00114    /* Should we use keyword notation? */
00115    if (use_keyword)
00116       set_WN2F_CONTEXT_keyword_ioctrl(context);
00117    
00118    emitted = FALSE; /* No item before the next one, as of yet */
00119    for (ios_kid = from_kid; ios_kid <= to_kid; ios_kid++)
00120    {
00121       item_buffer = New_Token_Buffer();
00122       emitted2 = WN2F_io_item(item_buffer, WN_kid(ios, ios_kid), context);
00123       if (emitted2)
00124       {
00125          if (emitted)
00126             Append_Token_Special(tokens, ','); /* an item emitted earlier */
00127          emitted = TRUE;
00128       }
00129       Append_And_Reclaim_Token_List(tokens, &item_buffer);
00130    }
00131    reset_WN2F_CONTEXT_origfmt_ioctrl(context);
00132 
00133    Append_Token_Special(tokens, ')');
00134 } /* WN2F_Append_IO_CtrlList */
00135 
00136 
00137 static void 
00138 WN2F_Append_IO_List(TOKEN_BUFFER tokens, 
00139                     WN          *ios,
00140                     INT          from_kid,
00141                     WN2F_CONTEXT context)
00142 {
00143    /* Emit an IOL list, starting at the given kid index and
00144     * continuing to the last kid.
00145     */
00146    BOOL emitted;
00147    INT  ios_kid;
00148    
00149    for (ios_kid = from_kid; ios_kid < WN_kid_count(ios); ios_kid++)
00150    {
00151       emitted = WN2F_io_item(tokens, WN_kid(ios, ios_kid), context);
00152       if (emitted && (ios_kid+1 < WN_kid_count(ios)))
00153          Append_Token_Special(tokens, ',');
00154    }
00155 } /* WN2F_Append_IO_List */
00156 
00157 
00158 /*---------------------- IO Item Handler-routines ---------------------*/
00159 /*---------------------------------------------------------------------*/
00160 
00161 #define WN2F_IS_IOU(item) \
00162    (WN_IOITEM(item) >= IOU_NONE && WN_IOITEM(item) <= IOU_INTERNAL)
00163 #define WN2F_IS_IOF(item) \
00164    ((WN_IOITEM(item) >= IOF_NONE && WN_IOITEM(item) <= IOF_CR_FMTSRC_DOPE))
00165 #define WN2F_IS_IOC(item) \
00166    (WN_IOITEM(item) >= IOC_ACCESS && WN_IOITEM(item) <= IOC_ERRFLAG)
00167 #define WN2F_IS_IOL(item) \
00168    ((WN_IOITEM(item) >= IOL_ARRAY && WN_IOITEM(item) <= IOL_VAR) || \
00169     (WN_IOITEM(item) == IOL_DOPE))
00170 
00171 
00172 static void
00173 WN2F_emit_ctrl(TOKEN_BUFFER tokens, const char *p , WN2F_CONTEXT context)
00174 {
00175   if (WN2F_CONTEXT_keyword_ioctrl(context))
00176   {
00177     Append_Token_String(tokens,p);
00178     Append_Token_Special(tokens, '=');
00179   }
00180 }
00181 
00182 static BOOL
00183 WN2F_io_unit(TOKEN_BUFFER tokens, 
00184              WN          *item, 
00185              WN2F_CONTEXT context)
00186 {
00187    
00188    BOOL emitted = TRUE; /*  if a unit specifier was emitted */
00189    const char * p = "UNIT";
00190    const BOOL issue_asterisk = WN2F_CONTEXT_issue_ioc_asterisk(context);
00191 
00192    /* Any arguments assumed to be by reference unless otherwise noted */
00193    set_WN2F_CONTEXT_deref_addr(context);
00194 
00195    switch (WN_io_item(item))
00196    {
00197    case IOU_NONE: 
00198 
00199      if (WN2F_CONTEXT_cray_io(context) && 
00200              issue_asterisk)
00201      {
00202        WN2F_emit_ctrl(tokens,p,context);
00203        Append_Token_Special(tokens, '*');
00204      } else
00205        emitted = FALSE;  /* eg: inquire by file */
00206 
00207       break;
00208       
00209    case IOU_DEFAULT: /* asterisk or double astrisk */
00210 
00211       if (issue_asterisk){
00212            WN2F_emit_ctrl(tokens,p,context);
00213            if (WN_const_val(WN_kid0(item)) == 0)
00214              Append_Token_String(tokens, "**");
00215            else
00216              Append_Token_Special(tokens, '*');
00217         }
00218        else
00219            emitted =FALSE;
00220 
00221       break;
00222 
00223    case IOU_EXTERNAL:    /* unit number */
00224    case IOU_DOPE:
00225    case IOU_INTERNAL:    /* substring or array reference */
00226       WN2F_emit_ctrl(tokens,p,context);
00227       WN2F_translate(tokens, WN_kid0(item), context);
00228       break;
00229 
00230    default:
00231       ASSERT_DBG_WARN(FALSE, 
00232                       (DIAG_W2F_UNEXPECTED_IOU,
00233                        IOITEM_name(WN_IOITEM(item)), "WN2F_io_unit"));
00234       WN2F_emit_ctrl(tokens,p,context);
00235       Append_Token_String(tokens, IOITEM_name(WN_IOITEM(item)));
00236       break;
00237    } /*switch*/
00238 
00239    return emitted;
00240 } /* WN2F_io_unit */
00241 
00242 
00243 static BOOL
00244 WN2F_io_format(TOKEN_BUFFER tokens, 
00245                WN          *item, 
00246                WN2F_CONTEXT context)
00247 {
00248    /* Return TRUE if a format or name-list specifier was emitted */ 
00249 
00250    BOOL emitted = TRUE;
00251    const char *p = "fmt";
00252 
00253    /* Any arguments assumed to be by reference unless otherwise noted */
00254    set_WN2F_CONTEXT_deref_addr(context);
00255 
00256    switch (WN_io_item(item))
00257    {
00258    case IOF_NONE:
00259       if (WN2F_CONTEXT_cray_io(context) && 
00260           WN2F_CONTEXT_fmt_io(context))
00261       {
00262         WN2F_emit_ctrl(tokens,p,context);
00263         Append_Token_Special(tokens, '*');
00264       }
00265       else
00266         emitted = FALSE;
00267       break;
00268 
00269    case IOF_ASSIGNED_VAR:
00270 
00271       /* The front-end should never generate these, since they are converted
00272        * into IOF_CHAR_EXPR items.  Should we for any reason start regenerating
00273        * these, this is the place where it should occur.
00274        */
00275       ASSERT_DBG_WARN(FALSE, 
00276                       (DIAG_W2F_UNEXPECTED_IOF,
00277                        IOITEM_name(WN_IOITEM(item)), "WN2F_io_format"));
00278       Append_Token_String(tokens, IOITEM_name(WN_IOITEM(item)));
00279 #if 0
00280       WN2F_translate(tokens, WN_kid0(item), context);      
00281 #endif
00282       break;
00283 
00284    case IOF_LABEL:
00285       /* a FORMAT label or character-string expression */
00286 
00287       WN2F_emit_ctrl(tokens,p,context);
00288       if (WN2F_CONTEXT_origfmt_ioctrl(context))
00289          Append_Token_String(tokens, 
00290                              Number_as_String(Origfmt_Ioctrl_Label, "%lld"));
00291       else
00292          WN2F_translate(tokens, WN_kid0(item), context);
00293       break;
00294 
00295    case IOF_CHAR_EXPR:
00296       /* a character-substring expression */
00297 
00298       WN2F_emit_ctrl(tokens,p,context);
00299       WN2F_String_Argument(tokens,
00300                            WN_kid0(item), /* base */
00301                            WN_kid1(item), /* length */
00302                            context);
00303       break;
00304 
00305    case IOF_LIST_DIRECTED:
00306       WN2F_emit_ctrl(tokens,p,context);
00307       Append_Token_Special(tokens, '*');
00308       break;
00309 
00310    case IOF_NAMELIST_DIRECTED:
00311       WN2F_emit_ctrl(tokens,"NML",context);
00312       WN2F_translate(tokens, WN_kid(item,WN_kid_count(item)-1), context);
00313       Clear_BE_ST_w2fc_referenced(WN_st(WN_kid(item,WN_kid_count(item)-1)));
00314 /* don't dump out Namelist name and corresponding type
00315  * in *.w2f.f file.When call WN2F_translate,the namelist name(st entry) will
00316  * be set "referenced".Clear the flag.--------fzhao
00317  */
00318       break;
00319 
00320    case IOF_UNFORMATTED:
00321       emitted = FALSE;
00322       break;
00323 
00324    case IOF_CR_PARSFMT:
00325       emitted = FALSE;
00326       break;
00327        
00328    case IOF_CR_FMTSRC:
00329    case IOF_CR_FMTSRC_DOPE:
00330       {
00331         WN * kid0 = WN_kid0(item);
00332         if (IS_IO_NULL_OPR(kid0))
00333           emitted = FALSE;
00334         else
00335           WN2F_translate(tokens, kid0, context);
00336         break;
00337       }
00338    default:
00339       ASSERT_DBG_WARN(FALSE, 
00340                       (DIAG_W2F_UNEXPECTED_IOF,
00341                        IOITEM_name(WN_IOITEM(item)), "WN2F_io_format"));
00342       Append_Token_String(tokens, IOITEM_name(WN_IOITEM(item)));
00343       break;
00344    } /*switch*/
00345 
00346    return emitted;
00347 } /* WN2F_io_format */
00348 
00349 static BOOL
00350 WN2F_io_control(TOKEN_BUFFER tokens, 
00351                 WN          *item, 
00352                 WN2F_CONTEXT context)
00353 {
00354    /* Return TRUE if a control specifier was emitted.
00355     */
00356    BOOL         emitted = TRUE;
00357    const IOITEM item_kind = WN_IOITEM(item);
00358    
00359    switch (item_kind)
00360    {
00361    case IOC_KEY:
00362       /* TODO: associate this with IOC_KEY */
00363       ASSERT_WARN(FALSE, (DIAG_UNIMPLEMENTED, 
00364                           Concat2_Strings("IOC", IOITEM_name(item_kind))));
00365       Append_Token_String(tokens, IOITEM_name(item_kind));
00366       Append_Token_Special(tokens, '=');
00367       Append_Token_String(tokens, "<???>");
00368       break;
00369       
00370    case IOC_KEY_START:
00371    case IOC_KEY_END:
00372    case IOC_KEY_CHARACTER:
00373    case IOC_KEY_INTEGER: 
00374    case IOC_NML: /* TODO: remove from IOC enumeration! It is redundant */
00375       ASSERT_WARN(FALSE, (DIAG_UNIMPLEMENTED, 
00376                           Concat2_Strings("IOC", IOITEM_name(item_kind))));
00377       Append_Token_String(tokens, IOITEM_name(item_kind));
00378       break;
00379       
00380    case IOC_EXIST:
00381    case IOC_NAMED:
00382    case IOC_OPENED:
00383       /* LOGICAL argument */
00384       ASSERT_FATAL(WN_kid_count(item) >= 1,
00385                    (DIAG_W2F_UNEXPECTED_NUM_KIDS, 
00386                     WN_kid_count(item), 1, "WN2F_io_control"));
00387       Append_Token_String(tokens, IOITEM_name(item_kind));
00388       Append_Token_Special(tokens, '=');
00389       set_WN2F_CONTEXT_has_logical_arg(context);
00390       if (TY_kind(WN_Tree_Type(WN_kid0(item))) != KIND_SCALAR)
00391          set_WN2F_CONTEXT_deref_addr(context);
00392       WN2F_translate(tokens, WN_kid0(item), context);
00393       reset_WN2F_CONTEXT_has_logical_arg(context);
00394       break;
00395       
00396    case IOC_READONLY:
00397    case IOC_SHARED:
00398    case IOC_U:
00399       Append_Token_String(tokens, IOITEM_name(item_kind));
00400       /* No argument */
00401       break;
00402 
00403    case IOC_VARFMT:
00404       emitted = FALSE;
00405       break;
00406 
00407    case IOC_VARFMT_ORIGFMT:
00408       /* We assume a label-number already has been assigned for
00409        * this FORMAT statement into Origfmt_Ioctrl_Label.  See
00410        * also IOF_LABEL.  Expect the string argument to be an
00411        * LDA of a string-constant (ST of class CONST).  Note that
00412        * a string-constant always is '\0' terminated.
00413        */
00414       ASSERT_DBG_WARN((WN_opc_operator(WN_kid0(item)) == OPR_LDA &&
00415                        ST_class(WN_st(WN_kid0(item))) == CLASS_CONST),
00416                       (DIAG_W2F_UNEXPECTED_IOC,
00417                        IOITEM_name(WN_IOITEM(item)), "WN2F_io_control"));
00418 
00419       if (Format_Stmts == NULL)
00420          Format_Stmts = New_Token_Buffer();
00421 
00422       reset_WN2F_CONTEXT_no_newline(context);
00423       WN2F_Stmt_Newline(
00424          Format_Stmts, 
00425          Number_as_String(Origfmt_Ioctrl_Label, "%lld"), 
00426          WN_linenum(item), context);
00427 
00428       Append_Token_String(Format_Stmts, "FORMAT");
00429       Append_Token_String(Format_Stmts, 
00430                           Targ_String_Address(STC_val(WN_st(WN_kid0(item)))));
00431       emitted = FALSE; /* Only emitted into Format_Stmts */
00432       break;
00433 
00434    case IOC_ERR:
00435    case IOC_EOR:
00436    case IOC_END:
00437       Append_Token_String(tokens, IOITEM_name(item_kind));
00438       Append_Token_Special(tokens, '=');
00439       ASSERT_DBG_WARN((WN_opc_operator(WN_kid0(item)) == OPR_GOTO),
00440                       (DIAG_W2F_UNEXPECTED_OPC,WN_opc_operator(item),"ERR/END/EOR="));
00441       Append_Token_String(tokens, 
00442                           WHIRL2F_number_as_name(WN_label_number(WN_kid0(item))));
00443       break;
00444 
00445    case IOC_CR_FLFLAG:
00446    case IOC_CR_EDFLAG:
00447    case IOC_ERRFLAG:
00448    case IOC_CR_EEEFLAG:
00449      emitted = FALSE;
00450      break;
00451 
00452    default:
00453       /* The usual case; an arbitrary non-logic expression argument,
00454        * which is usually an integral value, an array, or a character
00455        * string.
00456        */
00457       Append_Token_String(tokens, IOITEM_name(item_kind));
00458       Append_Token_Special(tokens, '=');
00459       if (TY_kind(WN_Tree_Type(WN_kid0(item))) != KIND_SCALAR)
00460          set_WN2F_CONTEXT_deref_addr(context);
00461 
00462       /* if kid count > 1, then it's a character object */
00463 
00464       if (WN_kid_count(item) == 1)
00465         WN2F_translate(tokens, WN_kid0(item), context);
00466       else
00467         WN2F_String_Argument(tokens,WN_kid0(item),WN_kid1(item),context);
00468       break;
00469    }
00470    
00471    return emitted;
00472 } /* WN2F_io_control */
00473 
00474 
00475 
00476 extern WN2F_STATUS
00477    WN2F_implied_do(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context);
00478 
00479 static BOOL
00480 WN2F_io_list(TOKEN_BUFFER tokens, 
00481              WN          *item, 
00482              WN2F_CONTEXT context)
00483 {
00484    const IOITEM item_kind = WN_IOITEM(item);
00485 
00486    switch (item_kind)
00487    {
00488    case IOL_VAR:
00489    case IOL_ARRAY:
00490    case IOL_CHAR_ARRAY:
00491    case IOL_RECORD:
00492       if (WN_opc_operator(WN_kid0(item)) == OPR_LDID       &&
00493           ST_sclass(WN_st(WN_kid0(item))) == SCLASS_FORMAL &&
00494           TY_Is_Pointer(WN_ty(WN_kid0(item)))              &&
00495           TY_Is_Pointer(TY_pointed(WN_ty(WN_kid0(item)))))
00496       {
00497          /* Work around a f77 bug
00498           */
00499          WN_set_ty(WN_kid0(item), TY_pointed(WN_ty(WN_kid0(item))));
00500       }
00501       set_WN2F_CONTEXT_deref_addr(context); /* Assume pass-by-reference */
00502       WN2F_translate(tokens, WN_kid0(item), context);
00503       break;
00504 
00505    case IOL_CHAR: 
00506      { 
00507        WN * len = WN_kid1(item);
00508        if (WN2F_CONTEXT_cray_io(context))   /* typecode is kid1 */
00509         len = WN_kid2(item);
00510 
00511        WN2F_String_Argument(tokens,
00512                             WN_kid0(item), /* base */
00513                             len,           /* length */
00514                             context);
00515      }
00516      break;
00517 
00518    case IOL_EXPR:
00519       reset_WN2F_CONTEXT_deref_addr(context); /* Assume pass-by-value */
00520       WN2F_translate(tokens, WN_kid0(item), context);
00521       break;
00522       
00523    case IOL_IMPLIED_DO:
00524    case IOL_IMPLIED_DO_1TRIP:
00525       reset_WN2F_CONTEXT_deref_addr(context); /* Handled specially */
00526       WN2F_implied_do(tokens, item, context); /* Defined in WN2F_stmt.c */
00527       break;
00528         
00529    case IOL_LOGICAL:
00530       set_WN2F_CONTEXT_has_logical_arg(context);
00531       reset_WN2F_CONTEXT_deref_addr(context); /* Assume pass-by-value */
00532       WN2F_translate(tokens, WN_kid0(item), context);
00533       break;
00534 
00535    case IOL_DOPE:
00536       {
00537         INT32 kids = WN_kid_count(item);
00538 
00539         /* base address */ 
00540 
00541         set_WN2F_CONTEXT_deref_addr(context); 
00542         WN2F_translate(tokens, WN_kid0(item), context);
00543 #if 0 //August 
00544         if (kids > 2)  /* implied do? */
00545         {
00546           Append_Token_Special(tokens, '(');
00547 
00548           /* Generate the subscript list - part may be in dope address, */
00549           /* set up several stmts ago. may just get INTCONST(0) here    */
00550         
00551           INT32 i = 2 ;
00552           while (i < kids)
00553           {
00554             WN2F_translate(tokens, WN_kid(item,i), context);
00555               
00556             if (i++ < kids-1)
00557               Append_Token_Special(tokens, ',');
00558           }
00559           Append_Token_Special(tokens, ')');
00560         }
00561 #endif
00562       }
00563       break ;
00564 
00565    default:
00566       ASSERT_DBG_WARN(FALSE, 
00567                       (DIAG_W2F_UNEXPECTED_IOL,
00568                        IOITEM_name(WN_IOITEM(item)), "WN2F_io_list"));
00569       Append_Token_String(tokens, IOITEM_name(WN_IOITEM(item)));
00570       break;
00571    } /* switch */
00572    
00573    return TRUE;
00574 } /* WN2F_io_list */
00575 
00576 
00577 /*---------- IO Statement Handler-routines and Dispatch-array ---------*/
00578 /*---------------------------------------------------------------------*/
00579 
00580 static void 
00581 WN2F_ios_backspace(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00582 {
00583    /* The kids should be an IOU, followed a sequence of IOCs.  Always
00584     * use the explicit UNIT keyword, unless there is exactly one kid an
00585     * it is an IOU.
00586     */
00587    ASSERT_WARN(WN_IOSTMT(wn) == IOS_BACKSPACE || WN_IOSTMT(wn) == IOS_CR_BACKSPACE, 
00588                (DIAG_W2F_UNEXPECTED_IOS, 
00589                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_backspace"));
00590    
00591    Append_Token_String(tokens, "BACKSPACE");
00592    if (WN_kid_count(wn) == 1 && WN2F_IS_IOU(WN_kid0(wn)))
00593       (void)WN2F_io_item(tokens, WN_kid0(wn), context);
00594    else
00595       WN2F_Append_IO_CtrlList(tokens,
00596                               wn,                 /* ios */
00597                               0,                  /* from kid*/
00598                               WN_kid_count(wn)-1, /* to kid*/
00599                               TRUE,               /* use keyword control */
00600                               context);
00601 
00602 } /* WN2F_ios_backspace */
00603 
00604 
00605 static void 
00606 WN2F_ios_close(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00607 {
00608    /* The kids should be an IOU, followed a sequence of IOCs.  Always
00609     * use the explicit UNIT keyword.
00610     */
00611    ASSERT_WARN(WN_IOSTMT(wn) == IOS_CLOSE || WN_IOSTMT(wn) == IOS_CR_CLOSE, 
00612                (DIAG_W2F_UNEXPECTED_IOS, 
00613                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_close"));
00614 
00615    Append_Token_String(tokens, "CLOSE");
00616    WN2F_Append_IO_CtrlList(tokens,
00617                            wn,                 /* ios */
00618                            0,                  /* from kid*/
00619                            WN_kid_count(wn)-1, /* to kid*/
00620                            TRUE,               /* use keyword control */
00621                            context);
00622 } /* WN2F_ios_close */
00623 
00624 
00625 static void 
00626 WN2F_ios_definefile(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00627 {
00628    /* The kids should be an IOU, followed a sequence of IOCs.  Always
00629     * use the explicit UNIT keyword.
00630     */
00631    ASSERT_FATAL(WN_io_statement(wn) == IOS_DEFINEFILE   &&
00632                 WN_kid_count(wn) == 5                   &&
00633                 WN_io_item(WN_kid(wn, 1)) == IOC_MAXREC &&
00634                 WN_io_item(WN_kid(wn, 2)) == IOC_RECL   &&
00635                 WN_io_item(WN_kid(wn, 3)) == IOC_U      &&
00636                 WN_io_item(WN_kid(wn, 4)) == IOC_ASSOCIATEVARIABLE,
00637                 (DIAG_W2F_UNEXPECTED_IOS, 
00638                  IOSTATEMENT_name(WN_IOSTMT(wn)), 
00639                  "WN2F_ios_definefile"));
00640 
00641    Append_Token_String(tokens, "DEFINE FILE");
00642 
00643    reset_WN2F_CONTEXT_keyword_ioctrl(context);
00644    WN2F_io_unit(tokens, WN_kid(wn, 0), context);
00645    Append_Token_Special(tokens, '(');
00646 
00647    if (TY_kind(WN_Tree_Type(WN_kid0(WN_kid(wn, 1)))) != KIND_SCALAR)
00648       set_WN2F_CONTEXT_deref_addr(context);
00649    WN2F_translate(tokens, WN_kid0(WN_kid(wn, 1)), context);
00650    reset_WN2F_CONTEXT_deref_addr(context);
00651    Append_Token_Special(tokens, ',');
00652 
00653    if (TY_kind(WN_Tree_Type(WN_kid0(WN_kid(wn, 2)))) != KIND_SCALAR)
00654       set_WN2F_CONTEXT_deref_addr(context);
00655    WN2F_translate(tokens, WN_kid0(WN_kid(wn, 2)), context);
00656    reset_WN2F_CONTEXT_deref_addr(context);
00657    Append_Token_Special(tokens, ',');
00658 
00659    Append_Token_String(tokens, "U");
00660    Append_Token_Special(tokens, ',');
00661 
00662    if (TY_kind(WN_Tree_Type(WN_kid0(WN_kid(wn, 4)))) != KIND_SCALAR)
00663       set_WN2F_CONTEXT_deref_addr(context);
00664    WN2F_translate(tokens, WN_kid0(WN_kid(wn, 4)), context);
00665    Append_Token_Special(tokens, ')');
00666    
00667 } /* WN2F_ios_definefile */
00668 
00669 
00670 static void 
00671 WN2F_ios_delete(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00672 {
00673    /* The kids should be an IOU, followed a sequence of IOCs.  Always
00674     * use the explicit UNIT keyword.
00675     */
00676    ASSERT_WARN(WN_IOSTMT(wn) == IOS_DELETE, 
00677                (DIAG_W2F_UNEXPECTED_IOS, 
00678                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_delete"));
00679    
00680    Append_Token_String(tokens, "DELETE");
00681    WN2F_Append_IO_CtrlList(tokens,
00682                            wn,                 /* ios */
00683                            0,                  /* from kid*/
00684                            WN_kid_count(wn)-1, /* to kid*/
00685                            TRUE,               /* use keyword control */
00686                            context);
00687 } /* WN2F_ios_delete */
00688 
00689 
00690 static void 
00691 WN2F_ios_endfile(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00692 {
00693    /* The kids should be an IOU, followed a sequence of IOCs.  Always
00694     * use the explicit UNIT keyword, unless there is exactly one kid an
00695     * it is an IOU.
00696     */
00697    ASSERT_WARN(WN_IOSTMT(wn) == IOS_ENDFILE || WN_IOSTMT(wn) == IOS_CR_ENDFILE, 
00698                (DIAG_W2F_UNEXPECTED_IOS, 
00699                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_endfile"));
00700    
00701    Append_Token_String(tokens, "ENDFILE");
00702    if (WN_kid_count(wn) == 1 && WN2F_IS_IOU(WN_kid0(wn)))
00703       (void)WN2F_io_item(tokens, WN_kid0(wn), context);
00704    else
00705       WN2F_Append_IO_CtrlList(tokens,
00706                               wn,                 /* ios */
00707                               0,                  /* from kid*/
00708                               WN_kid_count(wn)-1, /* to kid*/
00709                               TRUE,               /* use keyword control */
00710                               context);
00711 
00712 } /* WN2F_ios_endfile */
00713 
00714 
00715 static void 
00716 WN2F_ios_find(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00717 {
00718    /* The kids should be an IOU, followed a sequence of IOCs.  Always
00719     * use the explicit UNIT keyword.
00720     */
00721    ASSERT_WARN(WN_IOSTMT(wn) == IOS_FIND, 
00722                (DIAG_W2F_UNEXPECTED_IOS, 
00723                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_find"));
00724 
00725    Append_Token_String(tokens, "FIND");
00726    WN2F_Append_IO_CtrlList(tokens,
00727                            wn,                 /* ios */
00728                            0,                  /* from kid*/
00729                            WN_kid_count(wn)-1, /* to kid*/
00730                            TRUE,               /* use keyword control */
00731                            context);
00732 } /* WN2F_ios_find */
00733 
00734 
00735 static void 
00736 WN2F_ios_inquire(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00737 {
00738    /* The kids should be an optional IOU, followed a sequence of IOCs.
00739     * Always use the explicit UNIT keyword when the IOU is present.
00740     */
00741    ASSERT_WARN(WN_IOSTMT(wn) == IOS_INQUIRE || WN_IOSTMT(wn) == IOS_CR_INQUIRE,
00742                (DIAG_W2F_UNEXPECTED_IOS, 
00743                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_inquire"));
00744 
00745    Append_Token_String(tokens, "INQUIRE");
00746    WN2F_Append_IO_CtrlList(tokens,
00747                            wn,                 /* ios */
00748                            0,                  /* from kid*/
00749                            WN_kid_count(wn)-1, /* to kid*/
00750                            TRUE,               /* use keyword control */
00751                            context);
00752 } /* WN2F_ios_inquire */
00753 
00754 static void
00755 WN2F_ios_inqlength(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00756 {
00757    INT  ios_kid;
00758    BOOL emitted = FALSE;
00759    ASSERT_WARN(WN_IOSTMT(wn) == IOS_INQLENGTH,
00760                   (DIAG_W2F_UNEXPECTED_IOS,
00761                    IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_inqlength"));
00762 
00763    Append_Token_String(tokens, "INQUIRE");
00764    Append_Token_Special(tokens,'(');
00765    for (ios_kid=0; ios_kid<=WN_kid_count(wn)-1; ios_kid++)
00766      {
00767         WN *item = WN_kid(wn, ios_kid); 
00768         if (WN2F_IS_IOC(item) && WN_IOITEM(item)==IOC_INQLENGTH_VAR){
00769               Append_Token_String(tokens,"IOLENGTH =");
00770               WN2F_translate(tokens, WN_kid0(item), context);
00771               Append_Token_Special(tokens,')');
00772            }
00773 
00774          if (WN2F_IS_IOL(item)) {
00775              TOKEN_BUFFER item_buffer = New_Token_Buffer();
00776              if (WN2F_io_list(item_buffer, item, context)){
00777                 if (emitted )
00778                        Append_Token_Special(tokens, ',');
00779                  else 
00780                        emitted = TRUE;
00781                 Append_And_Reclaim_Token_List(tokens, &item_buffer);
00782               }
00783           }
00784       }
00785      reset_WN2F_CONTEXT_origfmt_ioctrl(context);
00786 
00787 } /*WN2F_ios_inqlength*/
00788 
00789 static void 
00790 WN2F_ios_namelist(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00791 {
00792    ASSERT_WARN(WN_IOSTMT(wn) == IOS_NAMELIST, 
00793                (DIAG_W2F_UNEXPECTED_IOS, 
00794                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_namelist"));
00795 
00796    Append_Token_String(tokens, "NAMELIST");
00797    Append_Token_Special(tokens, '/');
00798    (void)WN2F_io_item(tokens, WN_kid1(wn), context);
00799    Append_Token_Special(tokens, '/');
00800 
00801    if (WN_kid_count(wn) > 2)
00802       WN2F_Append_IO_List(tokens, wn, 2, context);
00803 
00804 } /* WN2F_ios_namelist */
00805 
00806 
00807 static void 
00808 WN2F_ios_open(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00809 {
00810    /* The kids should be an IOU, followed a sequence of IOCs.  Always
00811     * use the explicit UNIT keyword.
00812     */
00813    ASSERT_WARN(WN_IOSTMT(wn) == IOS_OPEN || WN_IOSTMT(wn) == IOS_CR_OPEN, 
00814                (DIAG_W2F_UNEXPECTED_IOS, 
00815                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_open"));
00816 
00817    Append_Token_String(tokens, "OPEN");
00818    WN2F_Append_IO_CtrlList(tokens,
00819                            wn,                 /* ios */
00820                            0,                  /* from kid*/
00821                            WN_kid_count(wn)-1, /* to kid*/
00822                            TRUE,               /* use keyword control */
00823                            context);
00824 } /* WN2F_ios_open */
00825 
00826 
00827 static void 
00828 WN2F_ios_rewind(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00829 {
00830    /* The kids should be an IOU, followed a sequence of IOCs.  Always
00831     * use the explicit UNIT keyword, unless there is exactly one kid
00832     * and it is an IOU.
00833     */
00834    ASSERT_WARN(WN_IOSTMT(wn) == IOS_REWIND || WN_IOSTMT(wn) == IOS_CR_REWIND, 
00835                (DIAG_W2F_UNEXPECTED_IOS, 
00836                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_rewind"));
00837    
00838    Append_Token_String(tokens, "REWIND");
00839    if (WN_kid_count(wn) == 1 && WN2F_IS_IOU(WN_kid0(wn)))
00840       (void)WN2F_io_item(tokens, WN_kid0(wn), context);
00841    else
00842       WN2F_Append_IO_CtrlList(tokens,
00843                               wn,                 /* ios */
00844                               0,                  /* from kid*/
00845                               WN_kid_count(wn)-1, /* to kid*/
00846                               TRUE,               /* use keyword control */
00847                               context);
00848 } /* WN2F_ios_rewind */
00849 
00850 
00851 static void 
00852 WN2F_ios_unlock(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00853 {
00854    /* The kids should be an IOU, followed a sequence of IOCs.  Always
00855     * use the explicit UNIT keyword, unless there is exactly one kid an
00856     * it is an IOU.
00857     */
00858    ASSERT_WARN(WN_IOSTMT(wn) == IOS_UNLOCK, 
00859                (DIAG_W2F_UNEXPECTED_IOS, 
00860                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_unlock"));
00861    
00862    Append_Token_String(tokens, "UNLOCK");
00863    if (WN_kid_count(wn) == 1 && WN2F_IS_IOU(WN_kid0(wn)))
00864       (void)WN2F_io_item(tokens, WN_kid0(wn), context);
00865    else
00866       WN2F_Append_IO_CtrlList(tokens,
00867                               wn,                 /* ios */
00868                               0,                  /* from kid*/
00869                               WN_kid_count(wn)-1, /* to kid*/
00870                               TRUE,               /* use keyword control */
00871                               context);
00872 
00873 } /* WN2F_ios_unlock */
00874 
00875 
00876 static void 
00877 WN2F_ios_accept(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00878 {
00879    /* The kids should be an IOF, followed a sequence of IOLs.
00880     */
00881    ASSERT_WARN(WN_IOSTMT(wn) == IOS_ACCEPT, 
00882                (DIAG_W2F_UNEXPECTED_IOS, 
00883                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_accept"));
00884    
00885    Append_Token_String(tokens, "ACCEPT");
00886    (void)WN2F_io_item(tokens, WN_kid0(wn), context);
00887    if (WN_kid_count(wn) > 1)
00888    {
00889       Append_Token_Special(tokens, ',');
00890       WN2F_Append_IO_List(tokens, wn, 1, context);
00891    }
00892 } /* WN2F_ios_accept */
00893 
00894 
00895 static void
00896 WN2F_ios_decode(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00897 {
00898    /* The kids should be an IOU, followed by an IOF, followed by a
00899     * sequence of IOCs and a sequence of IOLs.  Use keywords only
00900     * when the IOC list is non-empty.  Note that the IOU contains
00901     * both the integer expression (c) and the scalar or array 
00902     * reference (a) in "ENCODE (c, f, a [,IOSTAT=ios][,ERR=s]) iolist".
00903     */
00904    INT  iol_kid;
00905    
00906    ASSERT_WARN(WN_IOSTMT(wn) == IOS_DECODE, 
00907                (DIAG_W2F_UNEXPECTED_IOS, 
00908                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_decode"));
00909    
00910    /* This is needed for the translation of the number of characters and
00911     * the buffer we decode characters from.
00912     */
00913    set_WN2F_CONTEXT_deref_addr(context);
00914 
00915    Append_Token_String(tokens, "DECODE");
00916    Append_Token_Special(tokens, '(');
00917 
00918    /* Translate the number of characters */
00919    ASSERT_WARN(WN_IOITEM(WN_kid0(wn)) == IOU_INTERNAL &&
00920                WN_kid_count(WN_kid0(wn)) >= 2,
00921                (DIAG_W2F_UNEXPECTED_IOU, 
00922                 IOITEM_name(WN_IOITEM(WN_kid0(wn))), "WN2F_ios_decode"));
00923    WN2F_translate(tokens, WN_kid1(WN_kid0(wn)), context);
00924 
00925    /* Translate the format */
00926    Append_Token_Special(tokens, ',');
00927    (void)WN2F_io_item(tokens, WN_kid1(wn), context);
00928 
00929    /* Translate the buffer we decode from */
00930    Append_Token_Special(tokens, ',');
00931    WN2F_translate(tokens, WN_kid0(WN_kid0(wn)), context);
00932 
00933    /* Translate the EOSTAT and the ERR items */
00934    iol_kid = 2;
00935    if (WN_kid_count(wn) > 2 && WN2F_IS_IOC(WN_kid(wn, 2)))
00936    {
00937       iol_kid = 3;
00938       Append_Token_Special(tokens, ',');
00939       (void)WN2F_io_item(tokens, WN_kid(wn, 2), context);
00940    }
00941    if (WN_kid_count(wn) > 3 && WN2F_IS_IOC(WN_kid(wn, 3)))
00942    {
00943       iol_kid = 4;
00944       Append_Token_Special(tokens, ',');
00945       (void)WN2F_io_item(tokens, WN_kid(wn, 3), context);
00946    }
00947    Append_Token_Special(tokens, ')');
00948       
00949    /* Get the io_list */
00950    if (WN_kid_count(wn) > iol_kid)
00951       WN2F_Append_IO_List(tokens, wn, iol_kid, context);
00952 
00953 } /* WN2F_ios_decode */
00954 
00955 
00956 static void 
00957 WN2F_ios_encode(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
00958 {
00959    /* The kids should be an IOU, followed by an IOF, followed by a
00960     * sequence of IOCs and a sequence of IOLs.  Use keywords only
00961     * when the IOC list is non-empty.  Note that the IOU contains
00962     * both the integer expression (c) and the scalar or array 
00963     * reference (a) in "ENCODE (c, f, a [,IOSTAT=ios][,ERR=s]) iolist".
00964     */
00965    INT  iol_kid;
00966    
00967    ASSERT_WARN(WN_IOSTMT(wn) == IOS_ENCODE, 
00968                (DIAG_W2F_UNEXPECTED_IOS, 
00969                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_ENcode"));
00970    
00971    /* This is needed for the translation of the number of characters and
00972     * the buffer we encode characters from.
00973     */
00974    set_WN2F_CONTEXT_deref_addr(context);
00975 
00976    Append_Token_String(tokens, "ENCODE");
00977    Append_Token_Special(tokens, '(');
00978 
00979    /* Translate the number of characters */
00980    ASSERT_WARN(WN_IOITEM(WN_kid0(wn)) == IOU_INTERNAL &&
00981                WN_kid_count(WN_kid0(wn)) >= 2,
00982                (DIAG_W2F_UNEXPECTED_IOU, 
00983                 IOITEM_name(WN_IOITEM(WN_kid0(wn))), "WN2F_ios_encode"));
00984    WN2F_translate(tokens, WN_kid1(WN_kid0(wn)), context);
00985 
00986    /* Translate the format */
00987    Append_Token_Special(tokens, ',');
00988    (void)WN2F_io_item(tokens, WN_kid1(wn), context);
00989 
00990    /* Translate the buffer we encode from */
00991    Append_Token_Special(tokens, ',');
00992    WN2F_translate(tokens, WN_kid0(WN_kid0(wn)), context);
00993 
00994    /* Translate the EOSTAT and the ERR items */
00995    iol_kid = 2;
00996    if (WN_kid_count(wn) > 2 && WN2F_IS_IOC(WN_kid(wn, 2)))
00997    {
00998       iol_kid = 3;
00999       Append_Token_Special(tokens, ',');
01000       (void)WN2F_io_item(tokens, WN_kid(wn, 2), context);
01001    }
01002    if (WN_kid_count(wn) > 3 && WN2F_IS_IOC(WN_kid(wn, 3)))
01003    {
01004       iol_kid = 4;
01005       Append_Token_Special(tokens, ',');
01006       (void)WN2F_io_item(tokens, WN_kid(wn, 3), context);
01007    }
01008    Append_Token_Special(tokens, ')');
01009       
01010    /* Get the io_list */
01011    if (WN_kid_count(wn) > iol_kid)
01012       WN2F_Append_IO_List(tokens, wn, iol_kid, context);
01013 
01014 } /* WN2F_ios_encode */
01015 
01016 
01017 static void 
01018 WN2F_ios_print(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01019 {
01020    INT iol_kid;
01021    
01022    /* The kids should be an IOF, followed a sequence of IOLs.
01023     */
01024    ASSERT_WARN(WN_IOSTMT(wn) == IOS_PRINT, 
01025                (DIAG_W2F_UNEXPECTED_IOS, 
01026                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_print"));
01027    
01028    Append_Token_String(tokens, "PRINT");
01029 
01030    set_WN2F_CONTEXT_issue_ioc_asterisk(context);
01031 
01032    /* We do not really expect to have a unit specification for a "PRINT"
01033     * statement, but just in the case one occurs anyway, we skip it here.
01034     */
01035    if (WN2F_IS_IOU(WN_kid0(wn)))
01036       iol_kid = 2; /* kid 1 must be the format */
01037    else
01038       iol_kid = 1; /* Missing unit number */
01039    (void)WN2F_io_item(tokens, WN_kid(wn, iol_kid-1), context);
01040    if (WN_kid_count(wn) > iol_kid)
01041    {
01042       Append_Token_Special(tokens, ',');
01043       WN2F_Append_IO_List(tokens, wn, iol_kid, context);
01044    }
01045 
01046    reset_WN2F_CONTEXT_issue_ioc_asterisk(context);
01047 
01048 } /* WN2F_ios_print */
01049 
01050 
01051 static void 
01052 WN2F_ios_read(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01053 {
01054    /* The kids should be an IOU, followed by an IOF, followed by a
01055     * sequence of IOCs and a sequence of IOLs.  Use keywords only
01056     * when the IOC list is non-empty.  The IOL should be a sequence
01057     * of addresses into which the values read should be put.  In
01058     * the whirl2f output these addresses must be dereferenced.
01059     */
01060    INT  iol_kid;
01061    BOOL use_keyword;
01062    
01063    
01064    Append_Token_String(tokens, "READ");
01065    set_WN2F_CONTEXT_issue_ioc_asterisk(context);
01066 
01067    /* Determine whether or not we have the "READ f [,iolist]" format.
01068     */
01069    if (WN_IOITEM(WN_kid0(wn)) == IOU_DEFAULT           && 
01070        WN2F_IS_IOF(WN_kid1(wn))                         &&
01071        WN_IOITEM(WN_kid1(wn)) != IOF_NAMELIST_DIRECTED &&
01072        (WN_kid_count(wn) == 2 || WN2F_IS_IOL(WN_kid(wn, 2))))
01073    {
01074       (void)WN2F_io_item(tokens, WN_kid0(wn), context);
01075       iol_kid = 2;
01076       if (WN_kid_count(wn) > 2)
01077          Append_Token_Special(tokens, ',');
01078    }
01079    else
01080    {
01081       /* Determine if we should use the "unit=" or "fmt=" keyword notation,
01082        * and which kid is the last control specification item.
01083        */
01084       use_keyword = (WN_kid_count(wn) > 2       &&
01085                      WN2F_IS_IOF(WN_kid(wn, 1)) &&
01086                      WN2F_IS_IOC(WN_kid(wn, 2)));
01087       for (iol_kid = 0; 
01088            (iol_kid < WN_kid_count(wn)) && !WN2F_IS_IOL(WN_kid(wn, iol_kid));
01089            iol_kid++);
01090    
01091       /* Get the IOU, IOF, and IOC items */
01092       WN2F_Append_IO_CtrlList(tokens,
01093                               wn,          /* ios */
01094                               0,           /* from kid*/
01095                               iol_kid-1,   /* to kid*/
01096                               use_keyword, /* use keyword control */
01097                               context);
01098    }
01099       
01100    /* Get the io_list */
01101    if (iol_kid < WN_kid_count(wn))
01102    {
01103       set_WN2F_CONTEXT_deref_io_item(context); /* Assume pass-by-reference */
01104       WN2F_Append_IO_List(tokens, wn, iol_kid, context);
01105    }
01106 
01107     reset_WN2F_CONTEXT_issue_ioc_asterisk(context);
01108 
01109 } /* WN2F_ios_read */
01110 
01111 
01112 static void 
01113 WN2F_ios_rewrite(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01114 {
01115    /* The kids should be an IOU, followed by an IOF, followed by a
01116     * sequence of IOCs and a sequence of IOLs.  Use keywords only
01117     * when the IOC list is non-empty.
01118     */
01119    INT  iol_kid;
01120    BOOL use_keyword;
01121    
01122    ASSERT_WARN(WN_IOSTMT(wn) == IOS_REWRITE, 
01123                (DIAG_W2F_UNEXPECTED_IOS, 
01124                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_rewrite"));
01125 
01126    Append_Token_String(tokens, "REWRITE");
01127    set_WN2F_CONTEXT_issue_ioc_asterisk(context);
01128 
01129    /* Determine if we should use the "unit=" or "fmt=" keyword notation,
01130     * and which kid is the last control specification itemx.
01131     */
01132    use_keyword = (WN_kid_count(wn) > 2 &&
01133                   WN2F_IS_IOF(WN_kid(wn, 1)) &&
01134                   WN2F_IS_IOC(WN_kid(wn, 2)));
01135    for (iol_kid = 0; 
01136         (iol_kid < WN_kid_count(wn)) && !WN2F_IS_IOL(WN_kid(wn, iol_kid));
01137         iol_kid++);
01138    
01139    /* Get the IOU, IOF, and IOC items */
01140    WN2F_Append_IO_CtrlList(tokens,
01141                            wn,          /* ios */
01142                            0,           /* from kid*/
01143                            iol_kid-1,     /* to kid*/
01144                            use_keyword, /* use keyword control */
01145                            context);
01146    
01147    /* Get the io_list */
01148    if (iol_kid < WN_kid_count(wn))
01149       WN2F_Append_IO_List(tokens, wn, iol_kid, context);
01150 
01151    reset_WN2F_CONTEXT_issue_ioc_asterisk(context);
01152 
01153 } /* WN2F_ios_rewrite */
01154 
01155 
01156 static void 
01157 WN2F_ios_type(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01158 {
01159    /* The kids should be an IOF, followed a sequence of IOLs.
01160     */
01161    ASSERT_WARN(WN_IOSTMT(wn) == IOS_TYPE, 
01162                (DIAG_W2F_UNEXPECTED_IOS, 
01163                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_type"));
01164    
01165    Append_Token_String(tokens, "TYPE");
01166    (void)WN2F_io_item(tokens, WN_kid0(wn), context);
01167    if (WN_kid_count(wn) > 1)
01168    {
01169       Append_Token_Special(tokens, ',');
01170       WN2F_Append_IO_List(tokens, wn, 1, context);
01171    }
01172 } /* WN2F_ios_type */
01173 
01174 
01175 static void 
01176 WN2F_ios_write(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01177 {
01178    /* The kids should be an IOU, followed by an IOF, followed by a
01179     * sequence of IOCs and a sequence of IOLs.  Use keywords only
01180     * when the IOC list is non-empty.
01181     */
01182    INT  iol_kid;
01183    BOOL use_keyword;
01184    
01185    Append_Token_String(tokens, "WRITE");
01186 
01187    set_WN2F_CONTEXT_issue_ioc_asterisk(context);
01188 
01189    /* Determine if we should use the "unit=" or "fmt=" keyword notation,
01190     * and which kid is the last control specification item.
01191     */
01192    use_keyword = (WN_kid_count(wn) > 2 &&
01193                   WN2F_IS_IOF(WN_kid(wn, 1)) &&
01194                   WN2F_IS_IOC(WN_kid(wn, 2)));
01195    for (iol_kid = 0; 
01196         (iol_kid < WN_kid_count(wn)) && !WN2F_IS_IOL(WN_kid(wn, iol_kid));
01197         iol_kid++);
01198    
01199    /* Get the IOU, IOF, and IOC items */
01200    WN2F_Append_IO_CtrlList(tokens,
01201                            wn,          /* ios */
01202                            0,           /* from kid */
01203                            iol_kid-1,   /* to kid */
01204                            use_keyword, /* use keyword control */
01205                            context);
01206    
01207    /* Get the io_list */
01208    if (iol_kid < WN_kid_count(wn))
01209       WN2F_Append_IO_List(tokens, wn, iol_kid, context);
01210 
01211    reset_WN2F_CONTEXT_issue_ioc_asterisk(context);
01212 
01213 } /* WN2F_ios_write */
01214 
01215 
01216 /*------------------------- Cray Library routines ---------------------*/
01217 /*---------------------------------------------------------------------*/
01218 
01219 static void 
01220 WN2F_ios_cr(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01221 {
01222    /* Craylibs IO - write/read The kids should be an IOS, with kids of IO_ITEMS */
01223 
01224    INT  iol_kid;
01225    char * p ;
01226 
01227    ASSERT_WARN(WN_IOSTMT(wn) == IOS_CR_FWF || 
01228                WN_IOSTMT(wn) == IOS_CR_FWU || 
01229                WN_IOSTMT(wn) == IOS_CR_FRF || 
01230                WN_IOSTMT(wn) == IOS_CR_FRU,
01231                (DIAG_W2F_UNEXPECTED_IOS, 
01232                 IOSTATEMENT_name(WN_IOSTMT(wn)), "WN2F_ios_cr"));
01233 
01234    set_WN2F_CONTEXT_issue_ioc_asterisk(context);
01235 
01236    /* See if this is the first/last part of a 3-call IO stmt. If so punt */
01237    /* - it just duplicates some detail from the main stmt.               */
01238 
01239    for (iol_kid = 0; iol_kid < WN_kid_count(wn); iol_kid++)
01240    {
01241      WN * item = WN_kid(wn,iol_kid);
01242      if (WN_io_item(item) == IOC_CR_FLFLAG)
01243      {
01244        INT32 i = (WN_const_val(WN_kid0(item)) & 3);
01245        if (i != 0 && i != 3)
01246          return;
01247        else
01248          break;
01249      }
01250    }
01251 
01252    /* decide if read/write formatted/unformatted */
01253 
01254    if (WN_IOSTMT(wn) == IOS_CR_FWF || WN_IOSTMT(wn) == IOS_CR_FRF)
01255      set_WN2F_CONTEXT_fmt_io(context) ;
01256 
01257    if (WN_IOSTMT(wn) == IOS_CR_FRF || WN_IOSTMT(wn) == IOS_CR_FRU)
01258      p = "READ" ;
01259    else 
01260      p = "WRITE";
01261 
01262    Append_Token_String(tokens,p);
01263 
01264 
01265    /* count items in control list */
01266 
01267    for (iol_kid = 0; 
01268         (iol_kid < WN_kid_count(wn)) && !WN2F_IS_IOL(WN_kid(wn, iol_kid));
01269         iol_kid++);
01270    
01271    /* Get the IOU, IOF, and IOC items */
01272 
01273    WN2F_Append_IO_CtrlList(tokens,
01274                            wn,          /* ios */
01275                            0,           /* from kid */
01276                            iol_kid-1,   /* to kid */
01277                            FALSE,       /* use keyword control */
01278                            context);
01279    
01280    /* Get the io_list */
01281 
01282    if (iol_kid < WN_kid_count(wn))
01283       WN2F_Append_IO_List(tokens, wn, iol_kid, context);
01284 
01285    reset_WN2F_CONTEXT_issue_ioc_asterisk(context);
01286 
01287 } /* WN2F_ios_cr */
01288 
01289 /*------------------------- Exported routines -------------------------*/
01290 /*---------------------------------------------------------------------*/
01291 
01292 void WN2F_Io_initialize(void)
01293 {
01294    Ios_Handler[IOS_BACKSPACE] = &WN2F_ios_backspace;
01295    Ios_Handler[IOS_CLOSE] = &WN2F_ios_close;
01296    Ios_Handler[IOS_DEFINEFILE] = &WN2F_ios_definefile;
01297    Ios_Handler[IOS_DELETE] = &WN2F_ios_delete;
01298    Ios_Handler[IOS_ENDFILE] = &WN2F_ios_endfile;
01299    Ios_Handler[IOS_FIND] = &WN2F_ios_find;
01300    Ios_Handler[IOS_INQUIRE] = &WN2F_ios_inquire;
01301    Ios_Handler[IOS_NAMELIST] = &WN2F_ios_namelist;
01302    Ios_Handler[IOS_OPEN] = &WN2F_ios_open;
01303    Ios_Handler[IOS_REWIND] = &WN2F_ios_rewind;
01304    Ios_Handler[IOS_UNLOCK] = &WN2F_ios_unlock;
01305    Ios_Handler[IOS_ACCEPT] = &WN2F_ios_accept;
01306    Ios_Handler[IOS_DECODE] = &WN2F_ios_decode;
01307    Ios_Handler[IOS_ENCODE] = &WN2F_ios_encode;
01308    Ios_Handler[IOS_PRINT] = &WN2F_ios_print;
01309    Ios_Handler[IOS_READ] = &WN2F_ios_read;
01310    Ios_Handler[IOS_REWRITE] = &WN2F_ios_rewrite;
01311    Ios_Handler[IOS_TYPE] = &WN2F_ios_type;
01312    Ios_Handler[IOS_WRITE] = &WN2F_ios_write;
01313    Ios_Handler[IOS_CR_FWF]   = &WN2F_ios_cr;
01314    Ios_Handler[IOS_CR_FRN]   = &WN2F_ios_read;  
01315    Ios_Handler[IOS_CR_FWN]   = &WN2F_ios_write;  
01316    Ios_Handler[IOS_CR_FWU]   = &WN2F_ios_cr;
01317    Ios_Handler[IOS_CR_FRF]   = &WN2F_ios_cr;
01318    Ios_Handler[IOS_CR_FRU]   = &WN2F_ios_cr;
01319    Ios_Handler[IOS_CR_OPEN]  = &WN2F_ios_open;
01320    Ios_Handler[IOS_CR_CLOSE] = &WN2F_ios_close;
01321    Ios_Handler[IOS_CR_REWIND] = &WN2F_ios_rewind;
01322    Ios_Handler[IOS_CR_INQUIRE] = &WN2F_ios_inquire;
01323    Ios_Handler[IOS_CR_ENDFILE] = &WN2F_ios_endfile;
01324    Ios_Handler[IOS_CR_BACKSPACE] = &WN2F_ios_backspace;
01325    Ios_Handler[IOS_INQLENGTH] = &WN2F_ios_inqlength;
01326 
01327 
01328 
01329 } /* WN2F_Io_initialize */
01330 
01331 void WN2F_Io_finalize(void)
01332 {
01333    /* Do nothing for now! */
01334 } /* WN2F_Io_finalize */
01335 
01336 static BOOL
01337 Is_Cray_IO(IOSTATEMENT ios)
01338 {
01339   BOOL res ;
01340  
01341   res = (ios == IOS_CR_FWF) ||
01342         (ios == IOS_CR_FWU) ||
01343         (ios == IOS_CR_FRF) ||
01344         (ios == IOS_CR_FRU) ||
01345         (ios == IOS_CR_OPEN) ||
01346         (ios == IOS_CR_CLOSE) ||
01347         (ios == IOS_CR_REWIND) ||
01348         (ios == IOS_CR_INQUIRE) ||
01349         (ios == IOS_CR_ENDFILE) ||
01350         (ios == IOS_CR_FRN) ||         
01351         (ios == IOS_CR_FWN) ||          
01352         (ios == IOS_CR_BACKSPACE);
01353 
01354   return res ;
01355 }
01356 
01357 TOKEN_BUFFER
01358 WN2F_io_prefix_tokens(void)
01359 {
01360    return Ios_Prefix_Tokens;
01361 }
01362 
01363 WN2F_STATUS 
01364 WN2F_io(TOKEN_BUFFER tokens, WN *wn, WN2F_CONTEXT context)
01365 {
01366    INT          ios_kid;
01367    TOKEN_BUFFER ios_tokens = New_Token_Buffer();
01368 
01369    ASSERT_DBG_FATAL(WN_opc_operator(wn) == OPR_IO, 
01370                     (DIAG_W2F_UNEXPECTED_OPC, "WN2F_io"));
01371    
01372    /* Should we use the string given by an IOC_VARFMT_ORIGFMT
01373     * for a IOF_LABEL?
01374     */
01375    for (ios_kid = 0; 
01376         (ios_kid < WN_kid_count(wn) &&
01377          WN_io_item(WN_kid(wn, ios_kid)) != IOC_VARFMT_ORIGFMT); 
01378         ios_kid++);
01379    if (ios_kid < WN_kid_count(wn))
01380    {
01381       set_WN2F_CONTEXT_origfmt_ioctrl(context);
01382       Origfmt_Ioctrl_Label = W2CF_Symtab_Unique_Label();
01383    }
01384 
01385    /* Now dispatch to the appropriate handler routine for each
01386     * kind of IO statement, after beginning the statement on a
01387     * new line and setting the appropriate context flags.
01388     */
01389    WN2F_Stmt_Newline(tokens, NULL/*label*/, WN_linenum(wn), context);
01390    set_WN2F_CONTEXT_io_stmt(context);
01391    set_WN2F_CONTEXT_no_newline(context);
01392    Ios_Prefix_Tokens = New_Token_Buffer();
01393 
01394    const IOSTATEMENT ios = WN_IOSTMT(wn);
01395 
01396    if (Is_Cray_IO(ios)) 
01397      set_WN2F_CONTEXT_cray_io(context) ;             
01398 
01399    if (Ios_Handler[ios] == NULL)
01400    {
01401       Append_Token_String(ios_tokens, "<<FLIST cannot handle ");
01402       Append_Token_String(ios_tokens, 
01403                           get_iostatement_name(ios));
01404       Append_Token_String(ios_tokens, " io statement>>");
01405    }
01406    else
01407    {
01408       Ios_Handler[ios](ios_tokens, wn, context);
01409    }
01410 
01411    if (Ios_Prefix_Tokens != NULL)
01412       Append_And_Reclaim_Token_List(tokens, &Ios_Prefix_Tokens);
01413    Append_And_Reclaim_Token_List(tokens, &ios_tokens);
01414    if (Format_Stmts != NULL)
01415       Append_And_Reclaim_Token_List(tokens, &Format_Stmts);
01416    
01417    reset_WN2F_CONTEXT_cray_io(context) ;             
01418 
01419    return EMPTY_WN2F_STATUS;
01420 } /* WN2F_io */
01421 
01422 
01423 BOOL
01424 WN2F_io_item(TOKEN_BUFFER tokens, WN *item, WN2F_CONTEXT context)
01425 {
01426    /* Returns TRUE when something (anything) was emitted for this item.
01427     */
01428    BOOL emitted = FALSE;
01429 
01430    /* Any pointer-argument to an io-item should be dereferenced.  Most
01431     * notably, this applies for an LDA of a character string in a FMT
01432     * specifier, but it also applies for a variety of other arguments.
01433     * Such dereferences are specified within the WN2F_io routines.
01434     */
01435    if (WN2F_CONTEXT_deref_io_item(context))
01436       set_WN2F_CONTEXT_deref_addr(context);
01437    else
01438       reset_WN2F_CONTEXT_deref_addr(context);
01439 
01440    if (WN2F_IS_IOU(item))
01441       emitted = WN2F_io_unit(tokens, item, context);
01442    else if (WN2F_IS_IOF(item))
01443       emitted = WN2F_io_format(tokens, item, context);
01444    else if (WN2F_IS_IOC(item))
01445       emitted = WN2F_io_control(tokens, item, context);
01446    else if (WN2F_IS_IOL(item))
01447       emitted = WN2F_io_list(tokens, item, context);
01448    else
01449       ASSERT_DBG_WARN(FALSE, 
01450                       (DIAG_W2F_UNEXPECTED_IOL, 
01451                        (IOITEM_name(WN_IOITEM(item)) != NULL? 
01452                         IOITEM_name(WN_IOITEM(item)):"unknown_name"), 
01453                        "WN2F_io_item"));
01454 
01455    return emitted;
01456 } /* WN2F_io_item */
01457 
01458 
01459 
01460 
01461 
01462 
01463 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines