Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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