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 /* -*-Mode: c++;-*- (Tell emacs to use c++ mode) */ 00037 00038 #include "anl_common.h" 00039 #include "anl_diagnostics.h" // For warnings and errors 00040 #include "anl_file_mngr.h" // For managing files 00041 #include "w2cf_translator.h" // For translating WHIRL into high-level-language 00042 #include "anl_func_entry.h" 00043 #include "anl_pragma_attribute.h" 00044 00045 extern ANL_DIAGNOSTICS *Anl_Diag; // Defined in anl_driver.cxx 00046 00047 00048 #define MAX_DISTRIBUTION_PRAGMAS 32 00049 00050 00051 // =============== Class Utilities (hidden) =============== 00052 // ======================================================== 00053 00054 void 00055 ANL_PRAGMA_ATTRIBUTE::_Append_Arg_Numbers(ANL_CBUF *cbuf, 00056 INT32 val1, 00057 INT32 val2) 00058 { 00059 cbuf->Write_Char('('); 00060 if (val1 != -1) 00061 cbuf->Write_Int(val1); 00062 00063 if (val2 != -1) 00064 { 00065 cbuf->Write_String(", "); 00066 cbuf->Write_Int(val2); 00067 } 00068 cbuf->Write_Char(')'); 00069 } /* ANL_PRAGMA_ATTRIBUTE::_Append_Arg_Numbers */ 00070 00071 00072 // =============== Class Utilities (public) =============== 00073 // ======================================================== 00074 00075 BOOL 00076 ANL_PRAGMA_ATTRIBUTE::Is_ProMpf_Pragma_Attribute(WN *stmt) 00077 { 00078 BOOL predicate = (stmt != NULL && 00079 (WN_operator(stmt) == OPR_PRAGMA || 00080 WN_operator(stmt) == OPR_XPRAGMA)); 00081 00082 if (predicate) 00083 switch (WN_pragma(stmt)) 00084 { 00085 case WN_PRAGMA_PREFETCH_REF: 00086 predicate = (WN_next(stmt) != NULL && 00087 WN_operator(WN_next(stmt)) == OPR_PREFETCH); 00088 break; 00089 case WN_PRAGMA_DISTRIBUTE: 00090 case WN_PRAGMA_REDISTRIBUTE: 00091 case WN_PRAGMA_DISTRIBUTE_RESHAPE: 00092 predicate = (WN_pragma_index(stmt) == 0); 00093 break; 00094 case WN_PRAGMA_DYNAMIC: 00095 case WN_PRAGMA_COPYIN: 00096 case WN_PRAGMA_NUMTHREADS: 00097 case WN_PRAGMA_PAGE_PLACE: 00098 case WN_PRAGMA_KAP_CONCURRENTIZE: 00099 case WN_PRAGMA_KAP_NOCONCURRENTIZE: 00100 case WN_PRAGMA_KAP_ASSERT_PERMUTATION: 00101 case WN_PRAGMA_CRI_CNCALL: 00102 case WN_PRAGMA_KAP_ASSERT_CONCURRENT_CALL: 00103 case WN_PRAGMA_KAP_ASSERT_DO: 00104 case WN_PRAGMA_KAP_ASSERT_DOPREFER: 00105 case WN_PRAGMA_IVDEP: 00106 break; 00107 default: 00108 predicate = FALSE; 00109 break; 00110 } 00111 return predicate; 00112 } // ANL_PRAGMA_ATTRIBUTE::Is_ProMpf_Pragma_attribute 00113 00114 00115 // =============== Private Member Functions =============== 00116 // ======================================================== 00117 00118 00119 BOOL 00120 ANL_PRAGMA_ATTRIBUTE::_Is_Assertion() 00121 { 00122 BOOL predicate; 00123 00124 switch(_pragma_kind) 00125 { 00126 case ANL_ASSERT_PERMUTATION: 00127 case ANL_ASSERT_CONCURRENT_CALL: 00128 case ANL_ASSERT_DO: 00129 case ANL_ASSERT_DOPREFER: 00130 predicate = TRUE; 00131 break; 00132 default: 00133 predicate = FALSE; 00134 break; 00135 } 00136 return predicate; 00137 } // ANL_PRAGMA_ATTRIBUTE::_Is_Assertion 00138 00139 00140 void 00141 ANL_PRAGMA_ATTRIBUTE::_Write_Distribution(ANL_CBUF *cbuf, WN **next) 00142 { 00143 // Write the symbol to be distributed and the distribution parameters, 00144 // then return the next statement, following the last distribution 00145 // parameter, which where any applicable clauses will begin. The 00146 // *next parameter is only written in this routine. 00147 // 00148 INT32 num_dims; 00149 WN *distr_pragma[MAX_DISTRIBUTION_PRAGMAS]; 00150 WN *distr_cyclic[MAX_DISTRIBUTION_PRAGMAS]; 00151 WN *distr_bound[MAX_DISTRIBUTION_PRAGMAS]; 00152 WN_PRAGMA_ID id = (WN_PRAGMA_ID)WN_pragma(_apragma); 00153 00154 if (WN_operator(_apragma) != OPR_PRAGMA) 00155 cbuf->Write_String("<ERROR: unexpected opcode in _Write_Distribution>"); 00156 00157 // Write the distribution symbol to file 00158 // 00159 _func_entry->Pu_Translator()-> 00160 Original_Symname_To_String(cbuf, WN_st(_apragma)); 00161 00162 // Determine the number of dimensions and accumulate the distribution 00163 // kind for each dimension. 00164 // 00165 WN *wn = _apragma; 00166 for (num_dims = 0; 00167 (wn != NULL && 00168 WN_operator(wn) == OPR_PRAGMA && 00169 WN_pragma(wn) == id && 00170 num_dims == WN_pragma_index(wn)); 00171 num_dims++) 00172 { 00173 distr_pragma[num_dims] = wn; 00174 if (WN_pragma_distr_type(wn) == DISTRIBUTE_CYCLIC_EXPR) 00175 { 00176 wn = WN_next(wn); 00177 distr_cyclic[num_dims] = wn; 00178 } 00179 wn = WN_next(wn); 00180 distr_bound[num_dims] = wn; 00181 wn = WN_next(wn); 00182 } 00183 00184 /* Skip two stores, which are generated purely for dependency analysis 00185 * purposes. 00186 */ 00187 if (WN_operator(wn)==OPR_STID && ST_class(WN_st(wn))==CLASS_PREG) 00188 { 00189 wn = WN_next(wn); 00190 if (WN_operator(wn)==OPR_STID && ST_class(WN_st(wn))==CLASS_PREG) 00191 wn = WN_next(wn); 00192 } 00193 *next = wn; 00194 00195 // Translate the sequence of distribution kinds, in Fortran order, i.e. 00196 // in reverse order from the given WHIRL representation. 00197 // 00198 cbuf->Write_Char('('); 00199 for (INT32 dim = num_dims-1; dim >= 0; dim--) 00200 { 00201 switch (WN_pragma_distr_type(distr_pragma[dim])) 00202 { 00203 case DISTRIBUTE_STAR: 00204 cbuf->Write_Char('*'); 00205 break; 00206 00207 case DISTRIBUTE_BLOCK: 00208 cbuf->Write_String("block"); 00209 break; 00210 00211 case DISTRIBUTE_CYCLIC_EXPR: 00212 cbuf->Write_String("cyclic"); 00213 cbuf->Write_Char('('); 00214 _func_entry->Pu_Translator()-> 00215 Expr_To_String(cbuf, WN_kid0(distr_cyclic[dim])); 00216 cbuf->Write_Char(')'); 00217 break; 00218 00219 case DISTRIBUTE_CYCLIC_CONST: 00220 cbuf->Write_String("cyclic"); 00221 _Append_Arg_Numbers(cbuf, WN_pragma_preg(distr_pragma[dim]), -1); 00222 break; 00223 00224 default: 00225 cbuf->Write_String("unknown_distribution"); 00226 break; 00227 } 00228 00229 if (dim > 0) 00230 cbuf->Write_Char(','); 00231 00232 } // For each dimension 00233 00234 cbuf->Write_Char(')'); 00235 00236 } // ANL_PRAGMA_ATTRIBUTE::_Write_Distribution 00237 00238 00239 void 00240 ANL_PRAGMA_ATTRIBUTE::_Write_Pragma_Arguments(ANL_CBUF *cbuf) 00241 { 00242 // Write out a sequence of symbols or expressions, as specified by the 00243 // pragma, provided they where grouped together as one pragma in the 00244 // original source. 00245 // 00246 WN *next = Next_Stmt(); 00247 ANL_SRCPOS pos(_apragma); 00248 WN_PRAGMA_ID id = (WN_PRAGMA_ID)WN_pragma(_apragma); 00249 00250 cbuf->Write_Char('('); 00251 for (WN *wn = _apragma; wn != next; wn = WN_next(wn)) 00252 { 00253 if (wn != _apragma) 00254 cbuf->Write_Char(','); 00255 00256 if (WN_operator(wn) == OPR_XPRAGMA) 00257 { 00258 _func_entry->Pu_Translator()->A_Pragma_Expr_To_String(cbuf, wn); 00259 } 00260 else 00261 { 00262 // A common symbol? 00263 // 00264 if (ST_IS_COMMON_BLOCK(WN_st(wn))) 00265 cbuf->Write_Char('/'); 00266 00267 _func_entry-> 00268 Pu_Translator()->Original_Symname_To_String(cbuf, WN_st(wn)); 00269 00270 if (ST_IS_COMMON_BLOCK(WN_st(wn))) 00271 cbuf->Write_Char('/'); 00272 } 00273 } 00274 cbuf->Write_Char(')'); 00275 } // ANL_PRAGMA_ATTRIBUTE::_Write_Pragma_Arguments 00276 00277 00278 void 00279 ANL_PRAGMA_ATTRIBUTE::_Write_Pragma(ANL_CBUF *cbuf) 00280 { 00281 WN *next = _apragma; 00282 00283 switch (_pragma_kind) 00284 { 00285 case ANL_PREFETCH_REF_ATTR: 00286 cbuf->Write_String("PREFETCH_REF \""); 00287 _func_entry->Pu_Translator()-> 00288 Prefetch_Attributes_To_String(cbuf, 00289 WN_next(_apragma), 00290 WN_pragma_arg2(_apragma)); 00291 cbuf->Write_String("\""); 00292 break; 00293 case ANL_DISTRIBUTE_ATTR: 00294 cbuf->Write_String("DISTRIBUTE \""); 00295 _Write_Distribution(cbuf, &next); 00296 cbuf->Write_Char(' '); 00297 _func_entry->Pu_Translator()->ClauseList_To_String(cbuf, &next); 00298 cbuf->Write_String("\""); 00299 break; 00300 case ANL_REDISTRIBUTE_ATTR: 00301 cbuf->Write_String("REDISTRIBUTE \""); 00302 _Write_Distribution(cbuf, &next); 00303 cbuf->Write_Char(' '); 00304 _func_entry->Pu_Translator()->ClauseList_To_String(cbuf, &next); 00305 cbuf->Write_String("\""); 00306 break; 00307 case ANL_DISTRIBUTE_RESHAPE_ATTR: 00308 cbuf->Write_String("DISTRIBUTE RESHAPE \""); 00309 _Write_Distribution(cbuf, &next); 00310 cbuf->Write_Char(' '); 00311 _func_entry->Pu_Translator()->ClauseList_To_String(cbuf, &next); 00312 cbuf->Write_String("\""); 00313 break; 00314 case ANL_DYNAMIC_ATTR: 00315 cbuf->Write_String("DYNAMIC \""); 00316 _func_entry->Pu_Translator()-> 00317 Original_Symname_To_String(cbuf, WN_st(_apragma)); 00318 cbuf->Write_String("\""); 00319 break; 00320 case ANL_COPYIN_ATTR: 00321 cbuf->Write_String("COPYIN "); 00322 _Write_Pragma_Arguments(cbuf); 00323 break; 00324 case ANL_NUMTHREADS_ATTR: 00325 cbuf->Write_String("NUMTHREADS "); 00326 _Write_Pragma_Arguments(cbuf); 00327 break; 00328 case ANL_PAGE_PLACE_ATTR: 00329 cbuf->Write_String("PAGE_PLACE "); 00330 _Write_Pragma_Arguments(cbuf); 00331 break; 00332 case ANL_CONCURRENTIZE: 00333 cbuf->Write_String("CONCURRENTIZE"); 00334 break; 00335 case ANL_NOCONCURRENTIZE: 00336 cbuf->Write_String("NO CONCURRENTIZE"); 00337 break; 00338 case ANL_ASSERT_PERMUTATION: 00339 cbuf->Write_String("ASSERT PERMUTATION "); 00340 _Write_Pragma_Arguments(cbuf); 00341 break; 00342 case ANL_ASSERT_CONCURRENT_CALL: 00343 cbuf->Write_String("ASSERT CONCURRENT CALL"); 00344 break; 00345 case ANL_ASSERT_DO: 00346 if (WN_pragma_arg1(next) == ASSERT_DO_CONCURRENT) 00347 cbuf->Write_String("ASSERT DO (CONCURRENT)"); 00348 else 00349 cbuf->Write_String("ASSERT DO (SERIAL)"); 00350 break; 00351 case ANL_ASSERT_DOPREFER: 00352 if (WN_pragma_arg1(next) == ASSERT_DO_CONCURRENT) 00353 cbuf->Write_String("ASSERT DO PREFER (CONCURRENT)"); 00354 else 00355 cbuf->Write_String("ASSERT DO PREFER (SERIAL)"); 00356 break; 00357 case ANL_IVDEP: 00358 cbuf->Write_String("IVDEP"); 00359 break; 00360 default: 00361 cbuf->Write_String("UNKNOWN "); 00362 break; 00363 } 00364 } // ANL_PRAGMA_ATTRIBUTE::_Write_Pragma 00365 00366 00367 // =============== Public Member Functions ================ 00368 // ======================================================== 00369 00370 00371 ANL_PRAGMA_ATTRIBUTE::ANL_PRAGMA_ATTRIBUTE(WN *apragma, 00372 INT32 enclosing_construct_level, 00373 ANL_FUNC_ENTRY *func_entry, 00374 MEM_POOL *pool): 00375 _apragma(apragma), 00376 _func_entry(func_entry), 00377 _enclosing_construct_level(enclosing_construct_level), 00378 _pool(pool) 00379 { 00380 if (WN_operator(apragma) == OPR_PRAGMA || 00381 WN_operator(apragma) == OPR_XPRAGMA) 00382 { 00383 switch (WN_pragma(apragma)) 00384 { 00385 case WN_PRAGMA_PREFETCH_REF: 00386 _pragma_kind = ANL_PREFETCH_REF_ATTR; 00387 break; 00388 case WN_PRAGMA_DISTRIBUTE: 00389 _pragma_kind = ANL_DISTRIBUTE_ATTR; 00390 break; 00391 case WN_PRAGMA_REDISTRIBUTE: 00392 _pragma_kind = ANL_REDISTRIBUTE_ATTR; 00393 break; 00394 case WN_PRAGMA_DISTRIBUTE_RESHAPE: 00395 _pragma_kind = ANL_DISTRIBUTE_RESHAPE_ATTR; 00396 break; 00397 case WN_PRAGMA_DYNAMIC: 00398 _pragma_kind = ANL_DYNAMIC_ATTR; 00399 break; 00400 case WN_PRAGMA_COPYIN: 00401 _pragma_kind = ANL_COPYIN_ATTR; 00402 break; 00403 case WN_PRAGMA_NUMTHREADS: 00404 _pragma_kind = ANL_NUMTHREADS_ATTR; 00405 break; 00406 case WN_PRAGMA_PAGE_PLACE: 00407 _pragma_kind = ANL_PAGE_PLACE_ATTR; 00408 break; 00409 case WN_PRAGMA_KAP_CONCURRENTIZE: 00410 _pragma_kind = ANL_CONCURRENTIZE; 00411 break; 00412 case WN_PRAGMA_KAP_NOCONCURRENTIZE: 00413 _pragma_kind = ANL_NOCONCURRENTIZE; 00414 break; 00415 case WN_PRAGMA_KAP_ASSERT_PERMUTATION: 00416 _pragma_kind = ANL_ASSERT_PERMUTATION; 00417 break; 00418 case WN_PRAGMA_CRI_CNCALL: 00419 case WN_PRAGMA_KAP_ASSERT_CONCURRENT_CALL: 00420 _pragma_kind = ANL_ASSERT_CONCURRENT_CALL; 00421 break; 00422 case WN_PRAGMA_KAP_ASSERT_DO: 00423 _pragma_kind = ANL_ASSERT_DO; 00424 break; 00425 case WN_PRAGMA_KAP_ASSERT_DOPREFER: 00426 _pragma_kind = ANL_ASSERT_DOPREFER; 00427 break; 00428 case WN_PRAGMA_IVDEP: 00429 _pragma_kind = ANL_IVDEP; 00430 break; 00431 default: 00432 _pragma_kind = ANL_UNKNOWN_ATTR; 00433 break; 00434 } 00435 } 00436 else 00437 { 00438 _pragma_kind = ANL_UNKNOWN_ATTR; 00439 } 00440 } // ANL_PRAGMA_ATTRIBUTE::ANL_PRAGMA_ATTRIBUTE 00441 00442 00443 BOOL 00444 ANL_PRAGMA_ATTRIBUTE::Is_Pragma_Construct_Attribute(INT32 construct_level) 00445 { 00446 BOOL predicate; 00447 00448 switch (_pragma_kind) 00449 { 00450 case ANL_DISTRIBUTE_ATTR: 00451 case ANL_DISTRIBUTE_RESHAPE_ATTR: 00452 case ANL_DYNAMIC_ATTR: 00453 case ANL_CONCURRENTIZE: 00454 case ANL_NOCONCURRENTIZE: 00455 case ANL_ASSERT_PERMUTATION: 00456 case ANL_ASSERT_CONCURRENT_CALL: 00457 case ANL_ASSERT_DO: 00458 case ANL_ASSERT_DOPREFER: 00459 case ANL_IVDEP: 00460 case ANL_UNKNOWN_ATTR: 00461 predicate = FALSE; 00462 break; 00463 default: 00464 // True if the directive is nested within the construct. 00465 // 00466 predicate = (construct_level <= _enclosing_construct_level); 00467 break; 00468 } 00469 return predicate; 00470 } // ANL_PRAGMA_ATTRIBUTE::Is_Pragma_Construct_Attribute 00471 00472 00473 BOOL 00474 ANL_PRAGMA_ATTRIBUTE::Is_Region_Construct_Attribute(INT32 construct_level) 00475 { 00476 return Is_Pragma_Construct_Attribute(construct_level); 00477 } // ANL_PRAGMA_ATTRIBUTE::Is_Region_Construct_Attribute 00478 00479 00480 BOOL 00481 ANL_PRAGMA_ATTRIBUTE::Is_Loop_Construct_Attribute(INT32 construct_level) 00482 { 00483 BOOL predicate; 00484 00485 switch (_pragma_kind) 00486 { 00487 case ANL_CONCURRENTIZE: 00488 case ANL_NOCONCURRENTIZE: 00489 case ANL_ASSERT_PERMUTATION: 00490 predicate = FALSE; 00491 break; 00492 case ANL_ASSERT_CONCURRENT_CALL: 00493 case ANL_ASSERT_DO: 00494 case ANL_ASSERT_DOPREFER: 00495 case ANL_IVDEP: 00496 predicate = (construct_level == _enclosing_construct_level+1); 00497 break; 00498 default: 00499 predicate = Is_Pragma_Construct_Attribute(construct_level); 00500 break; 00501 } 00502 return predicate; 00503 } // ANL_PRAGMA_ATTRIBUTE::Is_Loop_Construct_Attribute 00504 00505 00506 WN * 00507 ANL_PRAGMA_ATTRIBUTE::Next_Stmt() 00508 { 00509 ANL_SRCPOS pos(_apragma); 00510 WN_PRAGMA_ID id = (WN_PRAGMA_ID)WN_pragma(_apragma); 00511 WN *next = WN_next(_apragma); 00512 INT32 num_dims; 00513 00514 switch (_pragma_kind) 00515 { 00516 case ANL_COPYIN_ATTR: 00517 case ANL_NUMTHREADS_ATTR: 00518 case ANL_PAGE_PLACE_ATTR: 00519 case ANL_CONCURRENTIZE: 00520 case ANL_NOCONCURRENTIZE: 00521 case ANL_ASSERT_PERMUTATION: 00522 case ANL_ASSERT_CONCURRENT_CALL: 00523 case ANL_ASSERT_DO: 00524 case ANL_ASSERT_DOPREFER: 00525 case ANL_IVDEP: 00526 while (next != NULL && 00527 (WN_operator(next) == OPR_XPRAGMA || 00528 WN_operator(next) == OPR_PRAGMA) && 00529 WN_pragma(next) == id && 00530 ANL_SRCPOS(next).Linenum() == pos.Linenum()) 00531 { 00532 next = WN_next(next); 00533 } 00534 break; 00535 case ANL_DISTRIBUTE_ATTR: 00536 case ANL_REDISTRIBUTE_ATTR: 00537 case ANL_DISTRIBUTE_RESHAPE_ATTR: 00538 // See _Write_Distribution for details on what we need to do 00539 // here. 00540 // 00541 next = _apragma; 00542 for (num_dims = 0; 00543 (next != NULL && 00544 WN_operator(next) == OPR_PRAGMA && 00545 WN_pragma(next) == id && 00546 num_dims == WN_pragma_index(next)); 00547 num_dims++) 00548 { 00549 if (WN_pragma_distr_type(next) == DISTRIBUTE_CYCLIC_EXPR) 00550 next = WN_next(next); 00551 next = WN_next(next); // skip this OPR_PRAGMA 00552 next = WN_next(next); // skip the following OPR_XPRAGMA 00553 } 00554 00555 /* Skip two stores, which are generated purely for dependency analysis 00556 * purposes. 00557 */ 00558 if (WN_operator(next)==OPR_STID && ST_class(WN_st(next))==CLASS_PREG) 00559 { 00560 next = WN_next(next); 00561 if (WN_operator(next)==OPR_STID && 00562 ST_class(WN_st(next))==CLASS_PREG) 00563 next = WN_next(next); 00564 } 00565 break; 00566 default: 00567 break; 00568 } 00569 while (next != NULL && 00570 _func_entry->Pu_Translator()->Is_A_Pragma_Clause(next)) 00571 { 00572 next = WN_next(next); 00573 } 00574 00575 return next; 00576 } // ANL_PRAGMA_ATTRIBUTE::Next_Stmt 00577 00578 00579 void 00580 ANL_PRAGMA_ATTRIBUTE::Write(ANL_CBUF *cbuf, INT32 id) 00581 { 00582 if (_pragma_kind != ANL_UNKNOWN_ATTR) 00583 { 00584 WN *next_stmt = _apragma; 00585 ANL_SRCPOS begin_pos; 00586 ANL_SRCPOS end_pos; 00587 00588 // Some preliminiaries. 00589 // 00590 _func_entry->Get_Pragma_Srcpos_Range(_apragma, &begin_pos, &end_pos); 00591 00592 // The dir clause. 00593 // 00594 if (_Is_Assertion()) 00595 cbuf->Write_String("asrtn "); 00596 else 00597 cbuf->Write_String("dir "); 00598 cbuf->Write_Int(id); 00599 cbuf->Write_Char(' '); 00600 begin_pos.Write(cbuf); 00601 cbuf->Write_Char('-'); 00602 end_pos.Write(cbuf); 00603 cbuf->Write_Char(' '); 00604 _Write_Pragma(cbuf); 00605 cbuf->Write_String("\n"); 00606 } 00607 } // ANL_PRAGMA_ATTRIBUTE::Write 00608