Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
cwh_stk.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  *  dd-mmm-95 - Original Version
00042  *
00043  * Description: maintains a stack to evaluate expressions. Items on
00044  *              the stack are tagged as WN,ST,FLD (an offset) or 
00045  *              STRs(strings). The STR_items are NULL and just mark
00046  *              the length and address below. ADDR_items and DEREF_items
00047  *              are WN's that have been tagged because they were marked
00048  *              as an argument address or a deref of a dope vector respectively.
00049  *              The TY field is usually NULL, but in a few instances where
00050  *              the address of a FLD has been formed,  the TY of the FLD
00051  *              has to be preserved until later eg: to go into a PARM node.
00052  *              Logicals and small integer constants have TYs too.
00053  *
00054  * ====================================================================
00055  * ====================================================================
00056  */
00057 
00058 static char *source_file = __FILE__;
00059 
00060 #ifdef _KEEP_RCS_ID
00061 #endif /* _KEEP_RCS_ID */
00062 
00063 
00064 /* sgi includes */
00065 
00066 #include "defs.h"
00067 #include "symtab.h"
00068 #include "wn.h"
00069 #include "wn_util.h"
00070 #include "ir_reader.h"
00071 
00072 /* conversion includes */
00073 
00074 #include "cwh_defines.h"
00075 #include "cwh_stk.h"
00076 
00077 typedef struct {
00078   void * item  ;
00079   TY_IDX it_ty ;
00080   enum   item_class Class;
00081 } stk_entry_t ;
00082 
00083 #define STK_SIZE_CHANGE 512
00084 #define STK_EMPTY -1
00085 
00086 static INT32 current_size = 0;
00087 static stk_entry_t *stk=NULL;
00088 static INT32 top = STK_EMPTY ;
00089 
00090 /*===============================================
00091  *
00092  * cwh_stk_push
00093  *
00094  * Push an item onto the expression stack.
00095  *
00096  *===============================================
00097  */ 
00098 extern void
00099 cwh_stk_push( void * item, enum item_class Class)
00100 {
00101   cwh_stk_push_typed(item,Class,0) ;
00102 
00103   return ;
00104 }
00105 
00106 /*===============================================
00107  *
00108  * cwh_stk_push_typed
00109  *
00110  * Push an item (WN/ADDR) on the expression stack.
00111  * This is used directly when the TY of a FLD is 
00112  * needed - the address of the FLD has been computed,
00113  * but the TY has to be preserved until later. 
00114  * 
00115  * It's used above, in the general case.
00116  *
00117  *===============================================
00118  */ 
00119 extern void
00120 cwh_stk_push_typed( void * item, enum item_class Class, TY_IDX ty)
00121 {
00122   if (ty != 0) {
00123     DevAssert(((Class == ADDR_item) || 
00124                (Class == WN_item)   || 
00125                (Class == WN_item_whole_array) ||
00126                (Class == ST_item)   || 
00127                (Class == ST_item_whole_array)   || 
00128                (Class == DEREF_item)),
00129               (" Cannot type this item"));
00130   }
00131              
00132   top ++ ;
00133 
00134   if (top >= current_size) {  /* More space for the stack ? */
00135      
00136      current_size += STK_SIZE_CHANGE;
00137      stk = (stk_entry_t *) realloc(stk,sizeof(stk_entry_t)*current_size);
00138   }
00139 
00140   stk[top].item  = item ;
00141   stk[top].Class = Class ;
00142   stk[top].it_ty = ty ; 
00143 
00144   return ;
00145 }
00146 
00147 /*===============================================
00148  *
00149  * cwh_stk_push_STR
00150  *
00151  * Push a STR_item onto the expression stack.
00152  * This is length, address, ty, and marker. 
00153  * The item_class is that of the address (ST/WN).
00154  *
00155  *===============================================
00156  */ 
00157 extern void
00158 cwh_stk_push_STR(void * len,void * addr, TY_IDX ty, enum item_class addr_class)
00159 {
00160   DevAssert((ty != NULL),("STR missing TY"));
00161   cwh_stk_push_typed(addr,addr_class,ty) ;
00162   cwh_stk_push(len,WN_item);      
00163   cwh_stk_push(NULL,STR_item);
00164 }
00165 
00166 /*===============================================
00167  *
00168  * cwh_stk_pop_WN
00169  *
00170  * Pop a WN from the expression stack.
00171  *
00172  *===============================================
00173  */ 
00174 extern WN *
00175 cwh_stk_pop_WN(void)
00176 {
00177 
00178   DevAssert((top >= 0), ("Stack underflow"));
00179   DevAssert((stk[top].Class == WN_item || stk[top].Class == WN_item_whole_array), (" TOS is not WN"));
00180 
00181   stk[top].Class = UNDEF ;
00182   return ((WN *) stk[top--].item) ;
00183 }
00184 
00185 /*===============================================
00186  *
00187  * cwh_stk_pop_WHIRL
00188  *
00189  * Pop a WHIRL node from the expression stack.
00190  * This is used when it doesn't matter if it's
00191  * a WN/ADDR/DEREF and distinguishing the cases
00192  * would be tiresome.
00193  *
00194  *===============================================
00195  */ 
00196 extern WN *
00197 cwh_stk_pop_WHIRL(void)
00198 {
00199 
00200   DevAssert((top >= 0), ("Stack underflow"));
00201   DevAssert((stk[top].Class == WN_item  ||
00202              stk[top].Class == WN_item_whole_array ||
00203              stk[top].Class == DEREF_item ||
00204              stk[top].Class == ADDR_item), (" TOS is not WN"));
00205 
00206   stk[top].Class = UNDEF ;
00207   return ((WN *) stk[top--].item) ;
00208 }
00209 
00210 /*===============================================
00211  *
00212  * cwh_stk_pop_ST
00213  *
00214  * Pop an ST from the expression stack.
00215  *
00216  *===============================================
00217  */ 
00218 extern ST *
00219 cwh_stk_pop_ST(void)
00220 {
00221   DevAssert((top >= 0), ("Stack underflow"));
00222   DevAssert((stk[top].Class == ST_item || stk[top].Class == ST_item_whole_array), (" TOS is not ST"));
00223 
00224   stk[top].Class = UNDEF ;  
00225   return ((ST *) stk[top--].item) ;
00226 
00227 }
00228 
00229 /*===============================================
00230  *
00231  * cwh_stk_pop_FLD
00232  *
00233  * Pop a FLD from the expression stack.
00234  *
00235  *===============================================
00236  */ 
00237 extern FLD_IDX 
00238 cwh_stk_pop_FLD(void)
00239 {
00240   DevAssert((top >= 0), ("Stack underflow"));
00241   DevAssert((stk[top].Class == FLD_item), (" TOS is not FLD"));
00242 
00243   stk[top].Class = UNDEF ;  
00244   return ((FLD_IDX )((long)stk[top--].item)) ;
00245 }
00246 
00247 /*===============================================
00248  *
00249  * cwh_stk_pop_ADDR
00250  *
00251  * Pop a ADDR from the expression stack. This is
00252  * used as a marker for an address, where a WN 
00253  * isn't sufficient context. eg: don't want to
00254  * load the thing.
00255  *
00256  *===============================================
00257  */ 
00258 extern WN *
00259 cwh_stk_pop_ADDR(void)
00260 {
00261   DevAssert((top >= 0), ("Stack underflow"));
00262   DevAssert((stk[top].Class == ADDR_item), (" TOS is not ADDR"));
00263 
00264   stk[top].Class = UNDEF ;  
00265   return ((WN *) stk[top--].item) ;
00266 }
00267 
00268 /*===============================================
00269  *
00270  * cwh_stk_pop_DEREF
00271  *
00272  * Pop a DEREF from the expression stack. This is
00273  * used as a marker for a dope vector dereference.
00274  * It's of interest in fei_nseq_subscr, but appears
00275  * in a few places where addresses do.
00276  *
00277  *===============================================
00278  */ 
00279 extern WN *
00280 cwh_stk_pop_DEREF(void)
00281 {
00282   DevAssert((top >= 0), ("Stack underflow"));
00283   DevAssert((stk[top].Class == DEREF_item), (" TOS is not DEREF"));
00284 
00285   stk[top].Class = UNDEF ;  
00286   return ((WN *) stk[top--].item) ;
00287 }
00288 
00289 /*===============================================
00290  *
00291  * cwh_stk_pop_STR
00292  *
00293  * Pop an STR from the expression stack.
00294  *
00295  *===============================================
00296  */ 
00297 extern void
00298 cwh_stk_pop_STR(void)
00299 {
00300   DevAssert((top-2 >= 0), ("Stack underflow"));
00301   DevAssert((stk[top].Class == STR_item), (" TOS is not STR"));
00302   DevAssert((stk[top-2].Class != NULL), (" STR missing TY"));
00303 
00304   stk[top--].Class = UNDEF ;  
00305 }
00306 
00307 /*===============================================
00308  *
00309  * cwh_stk_pop_PCONST
00310  *
00311  * Pop a PCONST from the expression stack. This is
00312  * used only for bit string constants, during
00313  * static initialization. Not to be used elsewhere.
00314  *
00315  *===============================================
00316  */ 
00317 extern ST *
00318 cwh_stk_pop_PCONST(void)
00319 {
00320   DevAssert((top >= 0), ("Stack underflow"));
00321   DevAssert((stk[top].Class == PCONST_item), (" TOS is not PCONST"));
00322 
00323   stk[top].Class = UNDEF ;  
00324   return ((ST *) stk[top--].item) ;
00325 }
00326 
00327 /*===============================================
00328  *
00329  * cwh_stk_pop_LBL
00330  *
00331  * Pop a LABEL_IDX from the expression stack. 
00332  *
00333  *===============================================
00334  */ 
00335 extern LABEL_IDX
00336 cwh_stk_pop_LB(void)
00337 {
00338   DevAssert((top >= 0), ("Stack underflow"));
00339   DevAssert((stk[top].Class == LB_item), (" TOS is not LB"));
00340 
00341   stk[top].Class = UNDEF ;  
00342   return ((LABEL_IDX) (long)stk[top--].item) ;
00343 }
00344 
00345 /*===============================================
00346  *
00347  * cwh_stk_pop_whatever
00348  *
00349  * Pop whatever is TOS.
00350  *
00351  *===============================================
00352  */ 
00353 extern void
00354 cwh_stk_pop_whatever(void)
00355 {
00356   DevAssert((top >= 0), ("Stack underflow"));
00357 
00358   stk[top--].Class = UNDEF ;
00359 
00360 }
00361 
00362 /*===============================================
00363  *
00364  * cwh_stk_get_class
00365  *
00366  * Find out what sort of item is TOS.
00367  *
00368  *===============================================
00369  */ 
00370 extern enum item_class
00371 cwh_stk_get_class(void)
00372 {
00373   DevAssert((top >= 0), ("Stack underflow"));
00374   
00375   return (stk[top].Class) ;
00376 
00377 }
00378 /*===============================================
00379  *
00380  * cwh_stk_get_TY
00381  *
00382  * Find out TY at TOS.
00383  *
00384  *===============================================
00385  */ 
00386 extern TY_IDX
00387 cwh_stk_get_TY(void)
00388 {
00389   DevAssert((top >= 0), ("Stack underflow"));
00390   
00391   return (stk[top].it_ty) ;
00392 
00393 }
00394 
00395 /*===============================================
00396  *
00397  * cwh_stk_get_FLD_TY
00398  *
00399  * Find out TY at for FLD item. It works for 
00400  * nested FLDs, because the top FLD is the innermost
00401  * (as written in the source eg: a%b%c%d - D is TOS).
00402  *
00403  *===============================================
00404  */ 
00405 extern TY_IDX
00406 cwh_stk_get_FLD_TY(void)
00407 {
00408   FLD_IDX fld ;
00409   DevAssert((top >= 0), ("Stack underflow"));
00410   DevAssert((stk[top].Class == FLD_item), (" TOS is not FLD"));
00411 
00412   fld = (FLD_IDX )(long) stk[top].item;
00413   return (FLD_type(FLD_HANDLE (fld)));
00414 }
00415 
00416 /*===============================================
00417  *
00418  * cwh_stk_count_STRs
00419  *
00420  * Count the STR_items in the n items at TOS
00421  *
00422  *===============================================
00423  */ 
00424 extern INT32
00425 cwh_stk_count_STRs(INT32 n)
00426 {
00427   INT32 i = top;
00428   INT32 c = 0 ;
00429 
00430 
00431   while (n-- > 0) {
00432     DevAssert((i >= 0 ), (" stk miscount"));    
00433 
00434     if (stk[i].Class == STR_item) {
00435       c++ ;
00436       i -= 3 ;
00437     } else
00438       i -- ;
00439     
00440   }
00441   return (c) ;
00442 
00443 }
00444 
00445 /*===============================================
00446  *
00447  * cwh_stk_is_byte_STR
00448  *
00449  * is the STR item at depth n, a single byte?
00450  * 0 == TOS. Assumes all items above are STRs.
00451  * Says not a byte if the expression isn't a 
00452  * simple load - ie: no transformationals etc.
00453  * Utility routine for cwh_stmt_character_store.
00454  *
00455  *===============================================
00456  */ 
00457 extern BOOL
00458 cwh_stk_is_byte_STR(INT32 n)
00459 {
00460   INT32 i = top;
00461   BOOL  res = FALSE;
00462 
00463   while (n-- > 0) {
00464 
00465     DevAssert((i >= 0 ), (" stk miscount"));    
00466     DevAssert((stk[i].Class == STR_item),(" all STRs?"));
00467 
00468     i -= 3 ;
00469   }
00470 
00471   DevAssert((stk[i].Class == STR_item),(" all STRs?"));
00472   i -- ;
00473   DevAssert((stk[i].Class == WN_item),("size?"));
00474 
00475   if (WN_operator((WN *)stk[i].item) == OPR_INTCONST) {
00476     if (WN_const_val((WN *)stk[i].item) == 1) {
00477 
00478       /* does this look like a simple load? */
00479 
00480       i --;
00481       if ((stk[i].Class == ST_item) ||
00482           (stk[i].Class == ST_item_whole_array) ||
00483           (stk[i].Class == FLD_item))
00484         res = TRUE;
00485 
00486       else if ((stk[i].Class == WN_item) ||
00487                (stk[i].Class == WN_item_whole_array) ||
00488                (stk[i].Class == DEREF_item)) {
00489 
00490         WN * wn = (WN *)stk[i].item ;
00491         OPERATOR op = WN_operator(wn);
00492       
00493         if (op == OPR_ARRAYEXP) {
00494           wn = WN_kid0(wn);
00495           op = WN_operator(wn);
00496         }
00497 
00498         if (op == OPR_INTRINSIC_OP && WN_intrinsic(wn) == INTRN_CHAR) {
00499           wn = WN_kid0(WN_kid0(wn)); /* skip PARM */
00500           op = WN_operator(wn);
00501         }
00502       
00503         res = (op == OPR_ARRAY) || (op == OPR_ARRSECTION) ||
00504               (op == OPR_LDID)  || (op == OPR_ILOAD);
00505       }
00506     }
00507   }
00508   return (res) ;
00509 }
00510 
00511 /*===============================================
00512  *
00513  * cwh_stk_verify_empty
00514  *
00515  * check to see nothing is left on the stack.
00516  * and to clear it if so..
00517  *
00518  *===============================================
00519  */ 
00520 extern void
00521 cwh_stk_verify_empty(void)
00522 {
00523   DevAssert((top == STK_EMPTY), ("Stack not empty"));
00524 
00525   top = STK_EMPTY ;
00526 
00527 }
00528 
00529 /*===============================================
00530  *
00531  * cwh_stk_dump
00532  *
00533  * Dump the stack.
00534  *
00535  *===============================================
00536  */ 
00537 
00538 extern void
00539 cwh_stk_dump(void)
00540 {
00541   static const char * str_name[] = {
00542     " ???? ",
00543     "WN_item",
00544     "ADDR_item",
00545     "DEREF_item",
00546     "FLD_item",
00547     "ST_item",
00548     "PCONST_item",
00549     "STR_item - length & address below",
00550     "ST_item_whole_array",
00551     "WN_item_whole_array",
00552     "LB_item"
00553   };
00554   
00555   static const char * null_str = "   <null>\n";
00556   int i,j ;
00557   
00558   printf ("\n Stack --- \n\n");
00559 
00560   for (i = top ; i >= 0 ; i-- ) {
00561     switch(stk[i].Class) {
00562     case WN_item:    j = 1;  break;
00563     case ADDR_item:  j = 2;  break;
00564     case DEREF_item: j = 3;  break;
00565     case FLD_item:   j = 4;  break;
00566     case ST_item:    j = 5;  break;
00567     case PCONST_item:j = 6;  break;
00568     case STR_item:   j = 7;  break;
00569     case ST_item_whole_array:  j=8;  break;
00570     case WN_item_whole_array:  j=9;  break;
00571     case LB_item            : j=10;  break;
00572     default:         j = 0;  break;
00573 
00574     }
00575 
00576     if (stk[i].it_ty == 0)
00577       printf("%s\n",str_name[j]);
00578     else 
00579       printf("%s    TY = 0x%x \n",str_name[j],stk[i].it_ty) ;
00580 
00581     switch(stk[i].Class) {
00582     case WN_item: 
00583     case WN_item_whole_array:
00584     case ADDR_item: 
00585     case DEREF_item: 
00586       if (stk[i].item == NULL)
00587         printf("%s",null_str);
00588       else
00589         DUMP_WN((WN *)stk[i].item) ;
00590       break ;
00591         
00592     case PCONST_item:
00593     case ST_item: 
00594     case ST_item_whole_array:
00595       if (stk[i].item == NULL)
00596         printf("%s",null_str);
00597       else
00598         DUMP_ST((ST *)stk[i].item) ;
00599       break ;
00600         
00601     case FLD_item: 
00602       if (stk[i].item == NULL)
00603         printf("%s",null_str);
00604       else {
00605         FLD_HANDLE f ((FLD_IDX )(long)stk[i].item);
00606         printf ("%s: offset: %lld \n",FLD_name(f), FLD_ofst(f));
00607       }
00608       break;
00609 
00610     case LB_item:
00611       if (stk[i].item == NULL)
00612         printf("%s",null_str);
00613       else
00614         DUMP_LB((LABEL_IDX)(long)stk[i].item);
00615       break;
00616 
00617     case STR_item: 
00618       break ;
00619         
00620     }
00621   }
00622 }
00623 
00624 /*===============================================
00625  *
00626  * cwh_stk_pop_iostmt
00627  *
00628  * Pop the IO operands from the stack to make a 
00629  * whirl node representing an IO statement. If
00630  * an err=, end= or eor= clause was specified, there
00631  * might be an extra ST at the bottom of the stack to
00632  * hold the return status. We pass this along as an
00633  * IO_ITEM called "RETURN_TEMP" .
00634  *
00635  *===============================================
00636  */ 
00637 extern WN *
00638 cwh_stk_pop_iostmt ( IOSTATEMENT opc , INT32 eeeflag)
00639 {
00640   INT   i, j;
00641   WN  * wn;
00642   INT top_adjustment = 0;
00643   INT num_items = 0;
00644   INT bottom;
00645 
00646   for(i=top; i>=0; i--) {
00647      if (stk[i].Class == WN_item || stk[i].Class == WN_item_whole_array) {
00648        wn = (WN *)stk[i].item;
00649        if ((wn == NULL) || (WN_operator_is(wn, OPR_IO_ITEM))) {
00650           top_adjustment++;
00651        } else {
00652           break;
00653        }
00654      } else {
00655        break;
00656      }
00657   }
00658 
00659   bottom = top - top_adjustment + 1;
00660 
00661   for(i = bottom; i <= top; i++ )
00662     if (stk[i].item != NULL)
00663       num_items++;
00664 
00665 
00666   wn = WN_CreateIo ( opc, num_items);
00667 
00668   for ( i = bottom, j=0; i <= top;) {
00669     if (stk[i].item != NULL) {
00670       WN_kid(wn,j++) = (WN *)stk[i++].item ;
00671     } else {
00672       i++;
00673     }
00674   }
00675 
00676   top = top - top_adjustment;
00677 
00678   return wn;
00679 }
00680 
00681 /*===============================================
00682  *
00683  * cwh_stk_get_num_inquire_items
00684  *
00685  * Returns the number of iolist items for this
00686  * Inquire(iolength) statement.
00687  *
00688  *===============================================
00689  */
00690 
00691 extern INT32
00692 cwh_stk_get_num_inquire_items(void)
00693 {
00694   INT32 i;
00695   WN *wn;
00696   INT32 num_items = 0;
00697 
00698   for(i=top; i>=0; i--) {
00699      if (stk[i].Class == WN_item || stk[i].Class == WN_item_whole_array) {
00700         wn = (WN *)stk[i].item;
00701         if (wn == NULL) {
00702            cwh_stk_pop_WN();
00703            break;
00704         } else if (WN_operator_is(wn, OPR_IO_ITEM)) {
00705            num_items++;
00706         } else {
00707            break;
00708         }
00709      } else {
00710        break;
00711      }
00712   }
00713   return num_items;
00714 }
00715 
00716 /*===============================================
00717  *
00718  * cwh_stk_push_top_item_again
00719  *
00720  * Push the top item again on the stack
00721  *
00722  *===============================================
00723  */
00724 extern void
00725 cwh_stk_push_top_item_again(void)
00726 {
00727    INT fld_count,i;
00728 
00729    switch (stk[top].Class) {
00730     case ST_item:
00731     case ST_item_whole_array:
00732     case LB_item:
00733        cwh_stk_push_typed(stk[top].item,stk[top].Class,stk[top].it_ty) ;
00734        break;
00735 
00736     case ADDR_item:   
00737     case DEREF_item:  
00738     case WN_item:     
00739     case WN_item_whole_array:
00740     case PCONST_item: 
00741        /* Need to duplicate these first */
00742        cwh_stk_push_typed(WN_COPY_Tree((WN *)stk[top].item),stk[top].Class,stk[top].it_ty) ;
00743        break;
00744 
00745     case STR_item:    
00746        /* Need to get the three items, then duplicate them */
00747        /* This copies the addr */
00748        if (stk[top-2].Class == ST_item_whole_array ||
00749            stk[top-2].Class == ST_item) {
00750           cwh_stk_push_typed(stk[top-2].item,stk[top-2].Class,stk[top-2].it_ty) ;
00751        } else {
00752           cwh_stk_push_typed(WN_COPY_Tree((WN *)stk[top-2].item),stk[top-2].Class,stk[top-2].it_ty) ;
00753        }
00754        /* This copies the len */
00755        cwh_stk_push_typed(WN_COPY_Tree((WN *)stk[top-2].item),stk[top-2].Class,stk[top-2].it_ty) ;
00756        
00757        /* This copies the STR */
00758        cwh_stk_push_typed(stk[top-2].item,stk[top-2].Class,stk[top-2].it_ty) ;
00759     case FLD_item:    
00760        fld_count = 0;
00761        while ((stk[top-fld_count].Class == FLD_item) && fld_count <= top) {
00762           ++fld_count;
00763        }
00764        /* fld_count contains the number of FLD items to duplicate */
00765        /* First, duplicate the base address underlying the field */
00766        if (stk[top-fld_count].Class == ST_item_whole_array ||
00767            stk[top-fld_count].Class == ST_item) {
00768           cwh_stk_push_typed(stk[top-fld_count].item,stk[top-fld_count].Class,
00769                              stk[top-fld_count].it_ty) ;
00770        } else {
00771           cwh_stk_push_typed(WN_COPY_Tree((WN *)stk[top-fld_count].item),stk[top-fld_count].Class,
00772                              stk[top-fld_count].it_ty) ;
00773        }
00774        /* Now duplicate all the FLDs */
00775        for (i = 0; i < fld_count; i++) {
00776           cwh_stk_push_typed(stk[top-fld_count].item,stk[top-fld_count].Class,
00777                              stk[top-fld_count].it_ty) ;
00778        }
00779        break;
00780 
00781     default:
00782        DevAssert((0), (" unduplicatable stack item"));    
00783        break;
00784    }
00785 
00786    return ;
00787 }
00788 
00789 
00790 
00791 /*===============================================
00792  *
00793  * char * cwh_stk_fld_name
00794  *
00795  * get field names from top of the stack
00796  *
00797  *===============================================
00798  */
00799 extern char *
00800 cwh_stk_fld_name(void)
00801 {
00802    INT i;
00803    char *r;
00804    char *s, *fname;
00805 
00806    r = (char *) malloc(1);
00807    *r = 0;
00808 
00809    for (i=top; i >= 0; i--) {
00810       if (stk[i].Class != FLD_item) break;
00811       /* Add the field name at the beginning of the r string */
00812       
00813       if (stk[i].item != NULL) {
00814          fname = FLD_name(FLD_HANDLE ((FLD_IDX)(long)stk[i].item));
00815          s = (char *) malloc(strlen(r) + strlen(fname) + 2) ;
00816          sprintf(s,"%%%s%s",fname,r);
00817          free(r);
00818          r = s;
00819       }
00820    }
00821    
00822    return (r);
00823 }
00824   
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines