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.1 of the GNU Lesser General Public License 00007 as 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 Lesser General Public 00021 License along with this program; if not, write the Free Software 00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, 00023 USA. 00024 00025 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00026 Mountain View, CA 94043, or: 00027 00028 http://www.sgi.com 00029 00030 For further information regarding this notice, see: 00031 00032 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00033 00034 */ 00035 00036 00037 00038 #ifndef _OLD_ERROR_NUMBERS 00039 #pragma ident "@(#) libf/fio/fmtparse.c 92.3 06/18/99 19:52:04" 00040 #endif 00041 #include "lio.h" /* For spiffy IS_DIGIT() macro */ 00042 #include <ctype.h> 00043 #include <stdlib.h> 00044 #include <string.h> 00045 #include <cray/format.h> 00046 #include <cray/nassert.h> 00047 #include <cray/portdefs.h> 00048 00049 typedef struct { 00050 char fmt_ch; /* Current character in format */ 00051 char *fmt_ptr; /* Pointer to current format char. */ 00052 short caller; /* Caller is library or compiler */ 00053 short depth; /* Current format nesting depth */ 00054 short maxdepth; /* Maximum format nesting depth */ 00055 short fatal_err; /* Flag to indicate fatal error */ 00056 long desc_col; /* Pointer to actual edit desc. */ 00057 long fmt_pos; /* Current position in format */ 00058 long fmt_len; /* Number of characters in format */ 00059 fmt_type *parsed; /* Pointer to parsed format block */ 00060 fmt_type *pptr; /* Pointer to current parsed entry */ 00061 fmt_type *revert; /* Pointer to reversion point */ 00062 msg_type *stat; /* Pointer to error status word */ 00063 _Error_function *iss_msg; /* Pointer to format error handler */ 00064 } parse_block; 00065 00066 /* Declare 'forward' functions for type-checking */ 00067 00068 static void 00069 fmterr ( parse_block *pfmt, 00070 short msg_num, 00071 short code, 00072 long column); 00073 00074 static short 00075 process_paren_group ( parse_block *pfmt, 00076 fmt_type *ploc); 00077 00078 /* Table of nonrepeatable characters */ 00079 00080 static int64 non_repeatable[2] = { 00081 0x00000000297EFFE0, /* " $ ' ) * + , - . 0-9 : */ 00082 0x0000180800001800 /* S T \ s t */ 00083 }; 00084 00085 /* 00086 * Macros to return next character and gather up a number. 00087 * At start, fmt_ptr needs to be incremented. At end, 00088 * fmt_ptr points to the returned character. Input is 00089 * a Fortran character string, so EOS is not always '\0'. 00090 */ 00091 00092 #define GET(P) { \ 00093 do { \ 00094 if (++P->fmt_pos > P->fmt_len) { \ 00095 P->fmt_ch = '\0'; \ 00096 P->fmt_pos--; \ 00097 break; \ 00098 } \ 00099 P->fmt_ch = *(++P->fmt_ptr); \ 00100 } while (P->fmt_ch == ' ' || P->fmt_ch == '\t'); \ 00101 } 00102 00103 #define GETNUM(P, M) { \ 00104 do { \ 00105 M = (M + M + (M << 3)) + ((int64) P->fmt_ch - ZERO);\ 00106 GET(P); \ 00107 } while (IS_DIGIT(P->fmt_ch)); \ 00108 } 00109 00110 /* Bridge for symbol renaming */ 00111 00112 #ifndef E_WITH_D_NON_ANSI 00113 #define E_WITH_D_NON_ANSI DW_IS_NON_ANSI 00114 #endif 00115 00116 /* 00117 * _fmt_parse() 00118 * 00119 * Description: This routine initializes variables for the format 00120 * parser, positions the input to the first character, 00121 * calls the actual format parser and cleans up. 00122 * 00123 * Called By: cft77, cft90 and the I/O library. 00124 * 00125 * Calls: process_paren_group 00126 * calloc 00127 * realloc 00128 * fmterr 00129 * 00130 * Input parameters: 00131 * msg_rtn Pointer to a pointer to the message routine to 00132 * be called if this is a compiler call. NULL if 00133 * this is a library call. 00134 * format_str Pointer to the format string to be parsed. 00135 * routine_caller Library/compiler flag. 00136 * 00137 * Output parameters: 00138 * fmt_str_len The length in words of the parsed format. 00139 * msg_out_ptr Pointer to the list of messages found. 00140 * 00141 * Returns: A pointer to the parsed format string. The first 00142 * two-word entry of the parsed format is for control 00143 * information; the first word is reserved for use by 00144 * the compiler, the second word is reserved for use 00145 * by the parser and library. 00146 * 00147 * Note: The input parameters are pointers to interface with 00148 * Pascal. 00149 */ 00150 00151 fmt_type * 00152 _fmt_parse( 00153 _Error_function **msg_rtn, 00154 char *format_str, 00155 long routine_caller, 00156 long *fmt_str_len, 00157 msg_type *lib_err_msg 00158 ) 00159 { 00160 register short length; 00161 parse_block *pfmt, p; 00162 00163 /* Basic assertions */ 00164 00165 assert (format_str != NULL); 00166 assert (routine_caller >= 0 && routine_caller <= MAX_CALL_FLAG); 00167 assert (fmt_str_len != NULL); 00168 assert (*fmt_str_len > 0); 00169 assert (routine_caller == LIB_CALL ? lib_err_msg != NULL : 1); 00170 assert (routine_caller != LIB_CALL ? msg_rtn != NULL : 1); 00171 00172 /* 00173 * If this routine is called from the library (routine_caller = 00174 * LIB_CALL) then the parser returns the number and position of the 00175 * first fatal error found--if any--and then exits. Any other caller 00176 * (e.g., compilers) must provide their own error routine by passing 00177 * a pointer to the routine in the first argument. The parser will 00178 * continue parsing until the end of the format is reached. 00179 */ 00180 00181 pfmt = &p; 00182 00183 pfmt->fmt_pos = 0; 00184 pfmt->depth = 0; 00185 pfmt->maxdepth = 0; 00186 pfmt->fatal_err = FALSE; 00187 pfmt->iss_msg = (msg_rtn == NULL ? NULL : *msg_rtn); 00188 pfmt->stat = lib_err_msg; 00189 pfmt->fmt_ptr = format_str - 1; /* Set for first GET call */ 00190 pfmt->fmt_len = *fmt_str_len; 00191 pfmt->caller = routine_caller; 00192 00193 GET(pfmt); 00194 00195 pfmt->desc_col = pfmt->fmt_pos; 00196 00197 if (pfmt->fmt_ch == '(') { 00198 GET(pfmt); 00199 } 00200 else { 00201 fmterr(pfmt, EXPECTING_LEFT_PAREN, FALL, 0); 00202 00203 /* Library quits at first fatal error */ 00204 00205 if (pfmt->caller == LIB_CALL) 00206 return( (fmt_type *) NULL); 00207 } 00208 00209 /* 00210 * We need to allocate a parsed format structure with enough 00211 * entries to accommodate this format (we'll free any unused 00212 * entries when we're done). Our initial guess is the number 00213 * of characters in the format plus two (one for the header and 00214 * one for the REVERT_OP entry). Note that for a long, sparse 00215 * format (with lots of blanks), this will allocate way too 00216 * much space. 00217 */ 00218 00219 pfmt->parsed = (fmt_type *) calloc(pfmt->fmt_len + 2, 00220 sizeof(fmt_type)); 00221 00222 if (pfmt->parsed == NULL) { 00223 00224 fmterr(pfmt, UNABLE_TO_MALLOC_MEMORY, FALL, 0); 00225 00226 /* No place for format, so quit */ 00227 00228 return( (fmt_type *) NULL); 00229 } 00230 00231 pfmt->pptr = pfmt->parsed + 1; 00232 pfmt->revert = pfmt->pptr; 00233 00234 /* Parse the format string */ 00235 00236 (void) process_paren_group(pfmt, pfmt->pptr); 00237 00238 if (pfmt->fatal_err) { 00239 free( (char *) pfmt->parsed); /* Return memory */ 00240 pfmt->parsed = NULL; 00241 length = 0; 00242 } 00243 else { 00244 length = pfmt->pptr - pfmt->parsed; 00245 pfmt->parsed->offset = PARSER_LEVEL; 00246 pfmt->parsed->rep_count = pfmt->maxdepth + 1; 00247 00248 if (pfmt->fmt_ch != '\0') 00249 fmterr(pfmt, TRAILING_CHARS, FALL, 0); 00250 00251 if (pfmt->caller == LIB_CALL) 00252 pfmt->parsed = (fmt_type *) realloc ( 00253 (char *) pfmt->parsed, 00254 length * FMT_ENTRY_BYTE_SIZE ); 00255 } 00256 00257 *fmt_str_len = length * FMT_ENTRY_WORD_SIZE; 00258 00259 return(pfmt->parsed); 00260 00261 } /* _parsfmt */ 00262 00263 /* 00264 * fmterr() 00265 * 00266 * Description: This routine processes errors encountered while 00267 * parsing formats. 00268 * 00269 * Called By: All routines in this file. 00270 * 00271 * Input parameters: 00272 * pfmt Parsing information block 00273 * msg_num Message number (see format.h) 00274 * code Compiler applicability code 00275 * FALL Error/warning applies to all compilers 00276 * F77 Error/warning applies only to f77 00277 * F90 Error/warning applies only to f90 00278 * F95 Error/warning applies only to f95 00279 * column Column number corresponding to error. If 00280 * zero, use current position. 00281 * 00282 * Returns: Nothing 00283 * 00284 * Note: Two column pointers are passed to the error processing 00285 * routine. The first points to the position in the 00286 * format where the actual error occurred; the second 00287 * points to the edit descriptor being processed. 00288 */ 00289 00290 static void 00291 fmterr( 00292 parse_block *pfmt, 00293 short msg_num, 00294 short code, 00295 long column 00296 ) 00297 { 00298 register short callflg; 00299 00300 callflg = 0; /* Assume no call to error function */ 00301 00302 if (msg_num >= FIRST_FATAL_MESSAGE) 00303 pfmt->fatal_err = TRUE; 00304 00305 if (column == 0) 00306 column = pfmt->fmt_pos; 00307 00308 switch (pfmt->caller) { 00309 00310 case LIB_CALL: 00311 00312 /* Ignore warnings and non-ANSI messages */ 00313 00314 if (msg_num >= FIRST_FATAL_MESSAGE) { 00315 pfmt->stat->msg_number = msg_num; 00316 pfmt->stat->msg_column = column; 00317 pfmt->stat->desc_column = pfmt->desc_col; 00318 } 00319 break; 00320 00321 case COMPILER_CALL_NO_ANSI: 00322 00323 /* Ignore ANSI messages */ 00324 00325 callflg = (msg_num < FIRST_NON_ANSI_MESSAGE || 00326 msg_num >= FIRST_FATAL_MESSAGE); 00327 break; 00328 00329 case COMPILER_CALL_ANSI: 00330 00331 /* Call compiler error routine */ 00332 00333 callflg = 1; 00334 break; 00335 00336 case COMPILER_CALL_ANSI_77: 00337 00338 /* Ignore any non-f77 messages */ 00339 00340 callflg = (code & F77); 00341 break; 00342 00343 case COMPILER_CALL_ANSI_90: 00344 00345 /* Ignore any non-f90 messages */ 00346 00347 callflg = (code & F90); 00348 break; 00349 00350 case COMPILER_CALL_ANSI_95: 00351 00352 /* Ignore any non-f95 messages */ 00353 00354 callflg = (code & F95); 00355 break; 00356 } /* switch */ 00357 00358 if (callflg != 0) 00359 (*pfmt->iss_msg) (msg_num, column, pfmt->desc_col); 00360 00361 return; 00362 00363 } /* fmterr */ 00364 00365 /* 00366 * recover() 00367 * 00368 * Description: This routine tries to recover from a fatal error by 00369 * searching for the character: ',', ')', '(', '"', '*', 00370 * "'", or EOF after the error. This should position 00371 * the parser at a valid format descriptor. 00372 * 00373 * Called By: process_paren_group 00374 * process_defg 00375 * process_bioz 00376 * process_arl 00377 * process_minus 00378 * 00379 * Input parameters: 00380 * pfmt Parsing information block 00381 * 00382 * Returns: Nothing 00383 */ 00384 00385 static void 00386 recover( 00387 parse_block *pfmt 00388 ) 00389 { 00390 register short found_char; 00391 00392 found_char = FALSE; 00393 00394 if (pfmt->caller != LIB_CALL) 00395 do { 00396 switch (pfmt->fmt_ch) { 00397 case ',': 00398 case ')': 00399 case '(': 00400 case '"': 00401 case '*': 00402 case '\'': 00403 case '\0': 00404 found_char = TRUE; 00405 break; 00406 00407 default: 00408 GET(pfmt); 00409 break; 00410 } /* switch */ 00411 } while (!found_char); 00412 00413 return; 00414 00415 } /* recover */ 00416 00417 /* 00418 * nonzero_integer() 00419 * 00420 * Description: This routine finds and returns a nonzero integer 00421 * or issues an error. 00422 * 00423 * Called By: process_t 00424 * 00425 * Calls: fmterr 00426 * 00427 * Input parameters: 00428 * pfmt Parsing information block 00429 * 00430 * Output parameters: 00431 * size The nonzero integer. 00432 * 00433 * Returns: TRUE if a nonzero integer is found, else FALSE. 00434 */ 00435 00436 static short 00437 nonzero_integer( 00438 parse_block *pfmt, 00439 long *size 00440 ) 00441 { 00442 register short return_val; 00443 register int64 value; 00444 register long col; 00445 00446 if (IS_DIGIT(pfmt->fmt_ch)) { 00447 00448 col = pfmt->fmt_pos; 00449 return_val = TRUE; 00450 value = *size; 00451 00452 GETNUM(pfmt, value); 00453 00454 if (value == 0) { 00455 fmterr(pfmt, FIELD_WIDTH_ZERO, FALL, col); 00456 value = 1; 00457 } 00458 else 00459 if (value > MAX_FIELD_WIDTH) { 00460 fmterr(pfmt, FIELD_TOO_LARGE, FALL, col); 00461 value = MAX_FIELD_WIDTH; 00462 } 00463 } 00464 else { 00465 fmterr(pfmt, EXPECTING_INTEGER, FALL, 0); 00466 return_val = FALSE; 00467 value = 1; 00468 } 00469 00470 *size = value; /* Update value */ 00471 00472 return(return_val); 00473 00474 } /* nonzero_integer */ 00475 00476 /* 00477 * process_arl() 00478 * 00479 * Description: This does semantic checking and generates text for 00480 * the A, L and R data edit-descriptors. 00481 * 00482 * Called By: process_paren_group 00483 * 00484 * Calls: fmterr 00485 * 00486 * Input parameters: 00487 * pfmt Parsing information block 00488 * op_code Is it A, L or R? 00489 * 00490 * Valid forms: 00491 * A 00492 * Aw 00493 * L (MIPSpro extension) 00494 * Lw 00495 * R (MIPSpro extension) 00496 * Rw 00497 * 00498 * Returns: Nothing 00499 */ 00500 00501 static void 00502 process_arl( 00503 parse_block *pfmt, 00504 unsigned short op_code 00505 ) 00506 { 00507 register long col; 00508 register int64 size; 00509 00510 size = 0; 00511 00512 GET(pfmt); 00513 00514 if (IS_DIGIT(pfmt->fmt_ch)) { 00515 00516 col = pfmt->fmt_pos; 00517 00518 GETNUM(pfmt, size); 00519 00520 if (size == 0) { 00521 #ifdef _OLD_ERROR_NUMBERS 00522 fmterr(pfmt, FIELD_WIDTH_ZERO, FALL, col); 00523 size = 1; 00524 #else 00525 fmterr(pfmt, ZERO_WIDTH_NON_ANSI, FALL, col); 00526 #endif 00527 } 00528 else 00529 if (size > MAX_FIELD_WIDTH) { 00530 fmterr(pfmt, FIELD_TOO_LARGE, FALL, col); 00531 size = MAX_FIELD_WIDTH; 00532 } 00533 } 00534 else 00535 if (op_code != A_ED) { 00536 #ifdef _OLD_ERROR_NUMBERS 00537 fmterr(pfmt, EXPECTING_INTEGER, FALL, 0); 00538 recover(pfmt); 00539 #else 00540 fmterr(pfmt, MISSING_WIDTH_NON_ANSI, FALL, pfmt->fmt_pos); 00541 #endif 00542 } 00543 00544 pfmt->pptr->op_code = op_code; 00545 pfmt->pptr->field_width = size; 00546 pfmt->pptr = pfmt->pptr + 1; 00547 00548 return; 00549 00550 } /* process_arl */ 00551 00552 /* 00553 * process_defg() 00554 * 00555 * Description: This does semantic checking and generates text for 00556 * the D, E, EN, ES, F, and G data edit-descriptors. 00557 * 00558 * Called By: process_paren_group 00559 * 00560 * Calls: fmterr 00561 * 00562 * Input parameters: 00563 * pfmt Parsing information block 00564 * op_code Is it D, E, EN, ES, F or G? 00565 * 00566 * Valid forms: 00567 * D (MIPSpro extension) 00568 * Dw.d 00569 * Dw.dEe (Cray extension) 00570 * E (MIPSpro extension) 00571 * Ew.d 00572 * Ew.dEe 00573 * EN (f90 or later, MIPSpro-style extension) 00574 * ENw.d (f90 or later) 00575 * ENw.dEe (f90 or later) 00576 * ES (f90 or later, MIPSpro-style extension) 00577 * ESw.d (f90 or later) 00578 * ESw.dEe (f90 or later) 00579 * F (MIPSpro extension) 00580 * Fw.d (w can be zero in f95 or later) 00581 * G (MIPSpro extension) 00582 * Gw.d 00583 * Gw.dEe 00584 * 00585 * Returns: Nothing 00586 */ 00587 00588 static void 00589 process_defg( 00590 parse_block *pfmt, 00591 unsigned short op_code 00592 ) 00593 { 00594 register short dset; 00595 register long col; 00596 register int64 esize; 00597 register int64 dsize; 00598 register int64 wsize; 00599 00600 dset = 1; 00601 dsize = 0; 00602 esize = 0; 00603 wsize = 0; 00604 00605 GET(pfmt); 00606 00607 if (IS_DIGIT(pfmt->fmt_ch)) { 00608 00609 col = pfmt->fmt_pos; 00610 00611 GETNUM(pfmt, wsize); 00612 00613 if (wsize == 0) { 00614 #ifdef _OLD_ERROR_NUMBERS 00615 fmterr(pfmt, FIELD_WIDTH_ZERO, FALL, col); 00616 wsize = 1; 00617 #else 00618 register short code; 00619 00620 code = (op_code == F_ED) ? (F77 | F90) : FALL; 00621 00622 fmterr(pfmt, ZERO_WIDTH_NON_ANSI, code, col); 00623 #endif 00624 } 00625 else 00626 if (wsize > MAX_FIELD_WIDTH) { 00627 fmterr(pfmt, FIELD_TOO_LARGE, FALL, col); 00628 wsize = MAX_FIELD_WIDTH; 00629 } 00630 00631 if (pfmt->fmt_ch == '.') { 00632 00633 GET(pfmt); 00634 00635 if (IS_DIGIT(pfmt->fmt_ch)) { 00636 00637 col = pfmt->fmt_pos; 00638 dset = 0; 00639 dsize = 0; 00640 00641 GETNUM(pfmt, dsize); 00642 00643 if (dsize > MAX_DECIMAL_FIELD) { 00644 fmterr(pfmt, FIELD_TOO_LARGE, FALL, col); 00645 dsize = MAX_DECIMAL_FIELD; 00646 } 00647 00648 if (toupper(pfmt->fmt_ch) == 'E' && 00649 op_code != F_ED) { 00650 register long col_e; 00651 00652 col_e = pfmt->fmt_pos; /* Position of 'E' */ 00653 00654 GET(pfmt); 00655 00656 if (IS_DIGIT(pfmt->fmt_ch)) { 00657 00658 col = pfmt->fmt_pos; 00659 00660 GETNUM(pfmt, esize); 00661 00662 if (esize == 0) { 00663 fmterr(pfmt, 00664 FIELD_WIDTH_ZERO, 00665 FALL, 00666 col); 00667 esize = 1; 00668 } 00669 else 00670 if (esize > MAX_EXPONENT) { 00671 fmterr(pfmt, 00672 FIELD_TOO_LARGE, 00673 FALL, col); 00674 esize = MAX_EXPONENT; 00675 } 00676 00677 if (op_code == D_ED) 00678 fmterr(pfmt, E_WITH_D_NON_ANSI, 00679 FALL, col_e); 00680 } 00681 else { 00682 fmterr(pfmt, EXPECTING_INTEGER, 00683 FALL, 0); 00684 recover(pfmt); 00685 } 00686 } 00687 } 00688 else { 00689 fmterr(pfmt, EXPECTING_INTEGER, FALL, 0); 00690 recover(pfmt); 00691 } 00692 } 00693 else { 00694 fmterr(pfmt, EXPECTING_PERIOD, FALL, 0); 00695 recover(pfmt); 00696 } 00697 } 00698 else { 00699 #ifdef _OLD_ERROR_NUMBERS 00700 fmterr(pfmt, EXPECTING_INTEGER, FALL, 0); 00701 recover(pfmt); 00702 #else 00703 fmterr(pfmt, MISSING_WIDTH_NON_ANSI, FALL, pfmt->fmt_pos); 00704 #endif 00705 } 00706 00707 pfmt->pptr->op_code = op_code; 00708 pfmt->pptr->exponent = esize; 00709 pfmt->pptr->field_width = wsize; 00710 pfmt->pptr->digits_field = dsize; 00711 pfmt->pptr->default_digits = dset; 00712 pfmt->pptr = pfmt->pptr + 1; 00713 00714 return; 00715 00716 } /* process_defg */ 00717 00718 /* 00719 * process_bioz() 00720 * 00721 * Description: This does semantic checking and generates text for 00722 * the B, I, O, and Z data edit-descriptors. 00723 * 00724 * Called By: process_paren_group 00725 * 00726 * Calls: fmterr 00727 * 00728 * Input parameters: 00729 * pfmt Parsing information block 00730 * op_code Is it B, I, O or Z? 00731 * 00732 * Valid forms: 00733 * B (MIPSpro extension) 00734 * Bw (w can be zero in f95 or later) 00735 * Bw.m (w can be zero in f95 or later) 00736 * I (MIPSpro extension) 00737 * Iw (w can be zero in f95 or later) 00738 * Iw.m (w can be zero in f95 or later) 00739 * O (MIPSpro extension) 00740 * Ow (w can be zero in f95 or later) 00741 * Ow.m (w can be zero in f95 or later) 00742 * Z (MIPSpro extension) 00743 * Zw (w can be zero in f95 or later) 00744 * Zw.m (w can be zero in f95 or later) 00745 * 00746 * Returns: Nothing 00747 */ 00748 00749 static void 00750 process_bioz( 00751 parse_block *pfmt, 00752 unsigned short op_code 00753 ) 00754 { 00755 register short dset; 00756 register long col; 00757 register int64 dsize; 00758 register int64 wsize; 00759 00760 dset = 1; 00761 dsize = 1; 00762 wsize = 0; 00763 00764 GET(pfmt); 00765 00766 if (IS_DIGIT(pfmt->fmt_ch)) { 00767 00768 col = pfmt->fmt_pos; 00769 00770 GETNUM(pfmt, wsize); 00771 00772 if (wsize == 0) { 00773 #ifdef _OLD_ERROR_NUMBERS 00774 fmterr(pfmt, FIELD_WIDTH_ZERO, FALL, col); 00775 wsize = 1; 00776 #else 00777 fmterr(pfmt, ZERO_WIDTH_NON_ANSI, (F77 | F90), col); 00778 #endif 00779 } else 00780 if (wsize > MAX_FIELD_WIDTH) { 00781 fmterr(pfmt, FIELD_TOO_LARGE, FALL, col); 00782 wsize = MAX_FIELD_WIDTH; 00783 } 00784 00785 if (pfmt->fmt_ch == '.') { 00786 00787 GET(pfmt); 00788 00789 if (IS_DIGIT(pfmt->fmt_ch)) { 00790 00791 col = pfmt->fmt_pos; 00792 dsize = 0; 00793 dset = 0; 00794 00795 GETNUM(pfmt, dsize); 00796 00797 if (dsize > MAX_DECIMAL_FIELD) { 00798 fmterr(pfmt, FIELD_TOO_LARGE, FALL, col); 00799 dsize = MAX_DECIMAL_FIELD; 00800 } 00801 } 00802 else { 00803 fmterr(pfmt, EXPECTING_INTEGER, FALL, 0); 00804 recover(pfmt); 00805 } 00806 } 00807 } 00808 else { 00809 #ifdef _OLD_ERROR_NUMBERS 00810 fmterr(pfmt, EXPECTING_INTEGER, FALL, 0); 00811 recover(pfmt); 00812 #else 00813 fmterr(pfmt, MISSING_WIDTH_NON_ANSI, FALL, pfmt->fmt_pos); 00814 #endif 00815 } 00816 00817 pfmt->pptr->op_code = op_code; 00818 pfmt->pptr->field_width = wsize; 00819 pfmt->pptr->digits_field = dsize; 00820 pfmt->pptr->default_digits = dset; 00821 pfmt->pptr = pfmt->pptr + 1; 00822 00823 return; 00824 00825 } /* process_bioz */ 00826 00827 /* 00828 * process_t() 00829 * 00830 * Description: This does semantic checking and generates text for 00831 * the Tw, TLw and TRw edit-descriptors. 00832 * 00833 * Called By: process_paren_group 00834 * 00835 * Calls: nonzero_integer 00836 * 00837 * Input parameters: 00838 * pfmt Parsing information block 00839 * 00840 * Returns: Nothing 00841 */ 00842 00843 static void 00844 process_t( 00845 parse_block *pfmt 00846 ) 00847 { 00848 long size; 00849 register char ch; 00850 00851 size = 0; 00852 00853 GET(pfmt); 00854 00855 ch = toupper(pfmt->fmt_ch); 00856 00857 if (ch == 'R') { 00858 00859 GET(pfmt); 00860 00861 if (nonzero_integer(pfmt, &size)) { 00862 pfmt->pptr->op_code = TR_ED; 00863 pfmt->pptr->field_width = size; 00864 pfmt->pptr = pfmt->pptr + 1; 00865 } 00866 } 00867 else 00868 if (ch == 'L') { 00869 00870 GET(pfmt); 00871 00872 if (nonzero_integer(pfmt, &size)) { 00873 pfmt->pptr->op_code = TL_ED; 00874 pfmt->pptr->field_width = size; 00875 pfmt->pptr = pfmt->pptr + 1; 00876 } 00877 } 00878 else 00879 if (nonzero_integer(pfmt, &size)) { 00880 pfmt->pptr->op_code = T_ED; 00881 pfmt->pptr->field_width = size; 00882 pfmt->pptr->rep_count = 1; 00883 pfmt->pptr = pfmt->pptr + 1; 00884 } 00885 00886 return; 00887 00888 } /* process_t */ 00889 00890 /* 00891 * process_p() 00892 * 00893 * Description: This does semantic checking and generates text for 00894 * the P edit-descriptor. It also checks for the ANSI 00895 * comma requirement. 00896 * 00897 * Called By: process_paren_group 00898 * process_minus 00899 * 00900 * Calls: fmterr 00901 * 00902 * Input parameters: 00903 * pfmt Parsing information block 00904 * scale_factor The P edit-descriptor scale factor. Because 00905 * the scale_factor is a signed quantity, it is 00906 * stored in the rep_count field. 00907 * 00908 * Returns: Nothing 00909 */ 00910 00911 static void 00912 process_p( 00913 parse_block *pfmt, 00914 long scale_factor 00915 ) 00916 { 00917 pfmt->pptr->op_code = P_ED; 00918 pfmt->pptr->offset = pfmt->fmt_pos; 00919 pfmt->pptr->rep_count = scale_factor; 00920 pfmt->pptr = pfmt->pptr + 1; 00921 00922 GET(pfmt); 00923 00924 switch (pfmt->fmt_ch) { 00925 case ',': 00926 case 'D': 00927 case 'E': 00928 case 'F': 00929 case 'G': 00930 case 'd': 00931 case 'e': 00932 case 'f': 00933 case 'g': 00934 case ')': 00935 case ':': 00936 case '/': 00937 case '\0': 00938 break; /* Do Nothing */ 00939 00940 default: 00941 fmterr(pfmt, ANSI_COMMA_REQ, FALL, 0); 00942 break; 00943 } /* switch */ 00944 00945 return; 00946 00947 } /* process_p */ 00948 00949 /* 00950 * process_char_string() 00951 * 00952 * Description: This does semantic checking of and moves the 00953 * character string to the intermediate text. 00954 * 00955 * Called By: process_paren_group 00956 * 00957 * Calls: fmterr 00958 * 00959 * Input parameters: 00960 * pfmt Parsing information block 00961 * 00962 * Returns: Nothing 00963 */ 00964 00965 static void 00966 process_char_string( 00967 parse_block *pfmt 00968 ) 00969 { 00970 char *str_ptr; 00971 register long size; 00972 00973 size = 0; 00974 str_ptr = (char *) (pfmt->pptr + 1); 00975 00976 for ( ; ; ) { 00977 00978 if (++pfmt->fmt_pos > pfmt->fmt_len) { 00979 pfmt->fmt_pos = pfmt->fmt_pos - 1; 00980 pfmt->fmt_ch = '\0'; 00981 fmterr(pfmt, NONTERMINATED_LITERAL, FALL, 0); 00982 break; 00983 } 00984 00985 if (*(++pfmt->fmt_ptr) == pfmt->fmt_ch) { 00986 00987 if (pfmt->fmt_pos == pfmt->fmt_len) { 00988 pfmt->fmt_ch = '\0'; 00989 break; 00990 } 00991 00992 if (*(pfmt->fmt_ptr+1) != pfmt->fmt_ch) { 00993 GET(pfmt); 00994 break; 00995 } 00996 else { 00997 pfmt->fmt_pos = pfmt->fmt_pos + 1; 00998 pfmt->fmt_ptr = pfmt->fmt_ptr + 1; 00999 } 01000 } 01001 01002 *str_ptr++ = *pfmt->fmt_ptr; 01003 size = size + 1; 01004 } /* for */ 01005 01006 pfmt->pptr->op_code = STRING_ED; 01007 pfmt->pptr->field_width = size; 01008 pfmt->pptr = pfmt->pptr + 01009 ((size + FMT_ENTRY_BYTE_SIZE - 1) / FMT_ENTRY_BYTE_SIZE) + 1; 01010 01011 return; 01012 01013 } /* process_char_string */ 01014 01015 /* 01016 * process_minus() 01017 * 01018 * Description: This does semantic checking for the use of the '-' 01019 * in a format string. 01020 * 01021 * Called By: process_paren_group 01022 * 01023 * Calls: fmterr 01024 * process_p 01025 * 01026 * Input parameters: 01027 * pfmt Parsing information block 01028 * 01029 * Returns: FALSE if +/-P, because a comma is not required by 01030 * the P edit-descriptor; TRUE otherwise, because a 01031 * comma is required. 01032 */ 01033 01034 static short 01035 process_minus( 01036 parse_block *pfmt 01037 ) 01038 { 01039 register short return_val; 01040 register long col_m; 01041 register long col_n; 01042 01043 return_val = TRUE; /* Assume TRUE */ 01044 col_m = pfmt->fmt_pos; /* Position of '-' */ 01045 01046 GET(pfmt); 01047 01048 col_n = pfmt->fmt_pos; /* Position of token after '-' */ 01049 01050 if (IS_DIGIT(pfmt->fmt_ch)) { 01051 register int64 size; 01052 register char ch; 01053 01054 size = 0; 01055 01056 GETNUM(pfmt, size); 01057 01058 ch = toupper(pfmt->fmt_ch); 01059 01060 if (ch == 'P') { 01061 01062 pfmt->desc_col = pfmt->fmt_pos; 01063 return_val = FALSE; 01064 01065 if (size > MAX_REP_COUNT) { 01066 fmterr(pfmt, FIELD_TOO_LARGE, FALL, col_n); 01067 size = MAX_REP_COUNT; 01068 } 01069 01070 process_p(pfmt, (long) -size); 01071 } 01072 else 01073 if (ch == 'X') { 01074 01075 pfmt->desc_col = pfmt->fmt_pos; 01076 01077 fmterr(pfmt, MINUS_X_NON_ANSI, FALL, col_m); 01078 01079 if (size == 0) { 01080 fmterr(pfmt, FIELD_WIDTH_ZERO, FALL, 01081 col_n); 01082 size = 1; 01083 } 01084 else 01085 if (size > MAX_FIELD_WIDTH) { 01086 fmterr(pfmt, FIELD_TOO_LARGE, 01087 FALL, col_n); 01088 size = MAX_FIELD_WIDTH; 01089 } 01090 01091 pfmt->pptr->op_code = TL_ED; 01092 pfmt->pptr->offset = pfmt->fmt_pos; 01093 pfmt->pptr->field_width = size; 01094 pfmt->pptr = pfmt->pptr + 1; 01095 01096 GET(pfmt); 01097 } 01098 else { 01099 fmterr(pfmt, EXPECTING_P_OR_X, FALL, col_n); 01100 recover(pfmt); 01101 } 01102 } 01103 else { 01104 fmterr(pfmt, EXPECTING_INTEGER, FALL, col_n); 01105 recover(pfmt); 01106 } 01107 01108 return(return_val); 01109 01110 } /* process_minus */ 01111 01112 /* 01113 * process_paren_group() 01114 * 01115 * Description: This is a recursive routine that processes a 01116 * parentheses group and all edit-descriptors in 01117 * that group. Whenever an open parenthesis is 01118 * found (which is not immediately followed by a 01119 * close parenthesis), this routine calls itself. 01120 * It does semantic checking, ANSI checking, creates 01121 * a parsed output that is directly usable by the 01122 * run-time I/O libraries. It also performs the 01123 * following optimizations: 01124 * 01125 * 1) Discards empty parentheses groups, 01126 * 2) Combines edit-descriptors that are alike, such 01127 * as: X becomes TR, -X becomes TL, and Hollerith 01128 * and character strings become STRING, 01129 * 3) Changes things like 6(4a3) to 24a3. 01130 * 01131 * Called By: process_paren_group 01132 * _parsfmt 01133 * 01134 * Calls: fmterr 01135 * process_arl 01136 * process_bioz 01137 * process_char_string 01138 * process_defg 01139 * process_minus 01140 * process_p 01141 * process_t 01142 * 01143 * Input parameters: 01144 * pfmt Parsing information block 01145 * ploc The location of the current open parenthesis 01146 * in the parsed format. 01147 * 01148 * Returns: The number of edit-descriptors encountered. If at 01149 * least one of the edit-descriptors was a data edit- 01150 * descriptor, then the number of edit-descriptors is 01151 * negated. 01152 */ 01153 01154 static short 01155 process_paren_group( 01156 parse_block *pfmt, 01157 fmt_type *ploc 01158 ) 01159 { 01160 register short comma_req_flag; 01161 register short data_ed; 01162 register short found_rep_count; 01163 register short outer_paren; 01164 register short num_eds; 01165 register short op_code; 01166 register short temp; 01167 register long num_start; 01168 register long old_pos; 01169 register int64 repeat_count; 01170 register char ch; 01171 char *old_ptr; 01172 01173 num_eds = 0; 01174 data_ed = FALSE; 01175 outer_paren = (pfmt->pptr == ploc); 01176 01177 do { /* for each item in the parentheses group */ 01178 01179 num_start = pfmt->fmt_pos; 01180 pfmt->desc_col = pfmt->fmt_pos; 01181 comma_req_flag = TRUE; 01182 num_eds = num_eds + 1; /* Assume an edit-descriptor */ 01183 01184 if (IS_DIGIT(pfmt->fmt_ch)) { 01185 register short j, k; 01186 01187 repeat_count = 0; 01188 found_rep_count = TRUE; 01189 01190 GETNUM(pfmt, repeat_count); 01191 01192 pfmt->desc_col = pfmt->fmt_pos; 01193 01194 /* Check if nonrepeatable edit-descriptor */ 01195 01196 j = (((short) pfmt->fmt_ch) >> 6) & 1; 01197 k = ((short) pfmt->fmt_ch) & 077; 01198 01199 if ((non_repeatable[j] << k) < 0) 01200 fmterr(pfmt, INVALID_REP_COUNT, FALL, num_start); 01201 else { /* 0P is valid */ 01202 01203 ch = toupper(pfmt->fmt_ch); 01204 01205 if (repeat_count == 0 && ch != 'P') { 01206 01207 if (ch == 'H') 01208 fmterr(pfmt, 01209 ZERO_OR_NO_HOLLERITH_CNT, 01210 FALL, num_start); 01211 01212 /* 01213 * Do not issue message for B here 01214 * because it may be a BN or BZ edit- 01215 * descriptor. The INVALID_REP_COUNT 01216 * error will be issued, if necessary, 01217 * when the B edit-descriptor is 01218 * processed. 01219 */ 01220 01221 else 01222 if (ch != 'B') 01223 fmterr(pfmt, 01224 ZERO_REP_COUNT, 01225 FALL, num_start); 01226 } 01227 01228 /* 01229 * Ensure that the repeat count hasn't overflowed. We 01230 * skip this check for the H, X and / edit-descriptors 01231 * since they use the repeat count as the field width 01232 * and will check it against a different limit. 01233 */ 01234 01235 if (repeat_count > MAX_REP_COUNT) 01236 if (ch != 'X' && ch != 'H' && ch != '/') { 01237 fmterr(pfmt, FIELD_TOO_LARGE, 01238 FALL, num_start); 01239 repeat_count = MAX_REP_COUNT; 01240 } 01241 } 01242 } 01243 else { /* not a digit */ 01244 repeat_count = 1; 01245 found_rep_count = FALSE; 01246 } 01247 01248 pfmt->pptr->offset = pfmt->fmt_pos; 01249 pfmt->pptr->rep_count = repeat_count; 01250 01251 switch (toupper(pfmt->fmt_ch)) { 01252 01253 case '(': /* Start of parentheses group */ 01254 01255 num_eds = num_eds - 1; 01256 pfmt->pptr->op_code = REPEAT_OP; 01257 pfmt->pptr = pfmt->pptr + 1; 01258 pfmt->depth = pfmt->depth + 1; 01259 01260 /* 01261 * If level one parentheses group, then 01262 * it's a possible reversion point. 01263 */ 01264 01265 if (pfmt->depth == 1) 01266 data_ed = FALSE; 01267 01268 GET(pfmt); 01269 01270 /* 01271 * process_paren_group() is called 01272 * recursively and returns the number 01273 * of edit-descriptors found in the 01274 * parentheses group. The negative 01275 * count of edit-descriptors is 01276 * returned if at least one of them 01277 * is a data edit-descriptor. 01278 */ 01279 01280 temp = process_paren_group(pfmt, 01281 pfmt->pptr - 1); 01282 01283 /* 01284 * Check if at least one data edit- 01285 * descriptor was found. 01286 */ 01287 01288 if (temp < 0) { 01289 data_ed = TRUE; 01290 temp = -temp; 01291 } 01292 01293 num_eds = num_eds + temp; 01294 break; 01295 01296 case 'A': /* A[w] data edit-descriptor */ 01297 data_ed = TRUE; 01298 process_arl(pfmt, A_ED); 01299 break; 01300 01301 case 'D': /* Dw.d[Ee] data edit-descriptor */ 01302 data_ed = TRUE; 01303 process_defg(pfmt, D_ED); 01304 break; 01305 01306 case 'F': /* Fw.d data edit-descriptor */ 01307 data_ed = TRUE; 01308 process_defg(pfmt, F_ED); 01309 break; 01310 01311 case 'I': /* Iw[.m] data edit-descriptor */ 01312 data_ed = TRUE; 01313 process_bioz(pfmt, I_ED); 01314 break; 01315 01316 case 'X': /* nX control edit-descriptor */ 01317 01318 if (!found_rep_count) 01319 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, 01320 FALL, 0); 01321 else 01322 if (repeat_count > MAX_FIELD_WIDTH) { 01323 fmterr(pfmt, FIELD_TOO_LARGE, 01324 FALL, num_start); 01325 repeat_count = MAX_FIELD_WIDTH; 01326 } 01327 01328 pfmt->pptr->op_code = TR_ED; 01329 pfmt->pptr->field_width = repeat_count; 01330 pfmt->pptr->rep_count = 1; 01331 pfmt->pptr = pfmt->pptr + 1; 01332 01333 GET(pfmt); 01334 break; 01335 01336 case 'H': /* nHc[c] string edit-descriptor */ 01337 fmterr(pfmt, H_IS_OBSOLETE_IN_F90, F90, 0); 01338 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, F95, 0); 01339 01340 if (found_rep_count) { 01341 register int left; 01342 01343 if (repeat_count > MAX_FIELD_WIDTH) { 01344 fmterr(pfmt, FIELD_TOO_LARGE, 01345 FALL, num_start); 01346 repeat_count = MAX_FIELD_WIDTH; 01347 } 01348 01349 left = pfmt->fmt_len - pfmt->fmt_pos; 01350 01351 if (repeat_count > left) 01352 repeat_count = (int64) left; 01353 01354 pfmt->pptr->op_code = STRING_ED; 01355 pfmt->pptr->field_width = repeat_count; 01356 pfmt->pptr->rep_count = 1; 01357 pfmt->pptr = pfmt->pptr + 1; 01358 01359 (void) strncpy((char *) pfmt->pptr, 01360 pfmt->fmt_ptr + 1, (int) repeat_count); 01361 01362 pfmt->pptr = pfmt->pptr + 1 + 01363 ((repeat_count - 1) / FMT_ENTRY_BYTE_SIZE); 01364 pfmt->fmt_ptr = pfmt->fmt_ptr + repeat_count; 01365 pfmt->fmt_pos = pfmt->fmt_pos + repeat_count; 01366 01367 GET(pfmt); 01368 01369 if (pfmt->fmt_ch == '\0') 01370 fmterr(pfmt, NONTERMINATED_LITERAL, 01371 FALL, 0); 01372 } 01373 else { 01374 fmterr(pfmt, ZERO_OR_NO_HOLLERITH_CNT, 01375 FALL, num_start); 01376 recover(pfmt); 01377 } 01378 break; 01379 01380 case '*': /* *[c]* string edit-descriptor */ 01381 case '"': /* "[c]" string edit-descriptor */ 01382 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, FALL, 0); 01383 01384 /* Break intentionally omitted - should fall through */ 01385 01386 case '\'': /* '[c]' string edit-descriptor */ 01387 process_char_string(pfmt); 01388 break; 01389 01390 case 'G': /* Gw.d[Ee] data edit-descriptor */ 01391 data_ed = TRUE; 01392 process_defg(pfmt, G_ED); 01393 break; 01394 01395 case 'E': /* Ew.d[Ee], ESw.d[Ee] or ENw.d[Ee] 01396 data edit-descriptors */ 01397 data_ed = TRUE; 01398 op_code = E_ED; 01399 old_pos = pfmt->fmt_pos; 01400 old_ptr = pfmt->fmt_ptr; 01401 01402 GET(pfmt); 01403 01404 ch = toupper(pfmt->fmt_ch); 01405 01406 if (ch == 'N' || ch == 'S') { 01407 01408 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, 01409 F77, old_pos); 01410 01411 op_code = (ch == 'N') ? EN_ED : ES_ED; 01412 01413 } 01414 else { /* Back up */ 01415 pfmt->fmt_pos = old_pos; 01416 pfmt->fmt_ptr = old_ptr; 01417 } 01418 01419 process_defg(pfmt, op_code); 01420 break; 01421 01422 case 'B': /* Bw[.m] data edit-descriptor or BN or 01423 BZ control edit-descriptors */ 01424 01425 old_pos = pfmt->fmt_pos; 01426 old_ptr = pfmt->fmt_ptr; 01427 01428 GET(pfmt); 01429 01430 ch = toupper(pfmt->fmt_ch); 01431 01432 if (ch == 'N' || ch == 'Z') { 01433 01434 if (found_rep_count) 01435 fmterr(pfmt, INVALID_REP_COUNT, 01436 FALL, num_start); 01437 01438 pfmt->pptr->op_code = (ch == 'N') ? 01439 BN_ED : BZ_ED; 01440 pfmt->pptr = pfmt->pptr + 1; 01441 01442 GET(pfmt); 01443 } 01444 else { 01445 if (repeat_count == 0) 01446 fmterr(pfmt, ZERO_REP_COUNT, 01447 FALL, num_start); 01448 01449 /* Back up */ 01450 01451 pfmt->fmt_pos = old_pos; 01452 pfmt->fmt_ptr = old_ptr; 01453 01454 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, 01455 F77, 0); 01456 01457 data_ed = TRUE; 01458 process_bioz(pfmt, B_ED); 01459 break; 01460 } 01461 break; 01462 01463 case 'R': /* Rw data edit-descriptor */ 01464 data_ed = TRUE; 01465 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, FALL, 0); 01466 process_arl(pfmt, R_ED); 01467 break; 01468 01469 case 'L': /* Lw data edit-descriptor */ 01470 data_ed = TRUE; 01471 process_arl(pfmt, L_ED); 01472 break; 01473 01474 case 'P': /* nP control edit-descriptor */ 01475 if (!found_rep_count) 01476 fmterr(pfmt, EXPECTING_INTEGER, FALL, 01477 0); 01478 01479 process_p(pfmt, (long) repeat_count); 01480 comma_req_flag = FALSE; 01481 break; 01482 01483 case 'O': /* Ow[.m] data edit-descriptor */ 01484 data_ed = TRUE; 01485 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, F77, 0); 01486 process_bioz(pfmt, O_ED); 01487 break; 01488 01489 case 'Z': /* Zw[.m] data edit-descriptor */ 01490 data_ed = TRUE; 01491 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, F77, 0); 01492 process_bioz(pfmt, Z_ED); 01493 break; 01494 01495 case '/': /* [n]/ control edit-descriptor */ 01496 if (found_rep_count) { 01497 01498 if (repeat_count > MAX_FIELD_WIDTH) { 01499 fmterr(pfmt, FIELD_TOO_LARGE, 01500 FALL, num_start); 01501 repeat_count = MAX_FIELD_WIDTH; 01502 } 01503 01504 fmterr(pfmt, REP_SLASH_NON_ANSI, 01505 F77, num_start); 01506 } 01507 01508 pfmt->pptr->op_code = SLASH_ED; 01509 pfmt->pptr->field_width = repeat_count; 01510 pfmt->pptr->rep_count = 1; 01511 pfmt->pptr = pfmt->pptr + 1; 01512 01513 comma_req_flag = FALSE; 01514 01515 GET(pfmt); 01516 break; 01517 01518 case '+': /* '+' valid only before P edit-descriptor */ 01519 GET(pfmt); 01520 01521 if (IS_DIGIT(pfmt->fmt_ch)) { 01522 register int64 size; 01523 01524 size = 0; 01525 num_start = pfmt->fmt_pos; 01526 01527 GETNUM(pfmt, size); 01528 01529 if (toupper(pfmt->fmt_ch) == 'P') { 01530 01531 pfmt->desc_col = pfmt->fmt_pos; 01532 01533 if (size > MAX_REP_COUNT) { 01534 fmterr(pfmt, FIELD_TOO_LARGE, 01535 FALL, num_start); 01536 size = MAX_REP_COUNT; 01537 } 01538 01539 process_p(pfmt, (long) size); 01540 01541 comma_req_flag = FALSE; 01542 break; /* Good exit */ 01543 } 01544 01545 fmterr(pfmt, EXPECTING_P_OR_X, FALL, 0); 01546 } 01547 else 01548 fmterr(pfmt, EXPECTING_INTEGER, FALL, 0); 01549 01550 recover(pfmt); 01551 break; 01552 01553 case '-': /* '-' valid only before P or X edit- 01554 descriptors */ 01555 comma_req_flag = process_minus(pfmt); 01556 break; 01557 01558 case ':': /* : control edit-descriptor */ 01559 pfmt->pptr->op_code = COLON_ED; 01560 pfmt->pptr = pfmt->pptr + 1; 01561 01562 GET(pfmt); 01563 01564 comma_req_flag = FALSE; 01565 break; 01566 01567 case 'Q': /* Q control edit-descriptor */ 01568 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, FALL, 0); 01569 01570 pfmt->pptr->op_code = Q_ED; 01571 pfmt->pptr = pfmt->pptr + 1; 01572 01573 GET(pfmt); 01574 01575 comma_req_flag = FALSE; 01576 data_ed = TRUE; 01577 break; 01578 01579 case '$': /* $ control edit-descriptor */ 01580 case '\\': /* \ control edit-descriptor */ 01581 fmterr(pfmt, NON_ANSI_EDIT_DESCRIPTOR, FALL, 0); 01582 01583 pfmt->pptr->op_code = DOLLAR_ED; 01584 pfmt->pptr = pfmt->pptr + 1; 01585 01586 GET(pfmt); 01587 01588 comma_req_flag = FALSE; 01589 break; 01590 01591 case 'S': /* S, SP or SS control edit-descriptor */ 01592 GET(pfmt); 01593 01594 ch = toupper(pfmt->fmt_ch); 01595 01596 if (ch == 'S' || ch == 'P') { 01597 op_code = (ch == 'S') ? SS_ED : SP_ED; 01598 GET(pfmt); 01599 } 01600 else 01601 op_code = S_ED; 01602 01603 pfmt->pptr->op_code = op_code; 01604 pfmt->pptr = pfmt->pptr + 1; 01605 break; 01606 01607 case 'T': /* T, TL or TR control edit-descriptor */ 01608 process_t(pfmt); 01609 break; 01610 01611 #ifndef _OLD_ERROR_NUMBERS 01612 case ',': /* No edit descriptor, issue warning */ 01613 fmterr(pfmt, NON_ANSI_NULL_DESCRIPTOR, FALL, 0); 01614 GET(pfmt); 01615 01616 comma_req_flag = FALSE; 01617 break; 01618 #endif 01619 01620 case ')': /* End of parentheses group */ 01621 num_eds = num_eds - 1; 01622 01623 if (num_eds == 0 && !outer_paren) 01624 fmterr(pfmt, ANSI_EMPTY_PAREN_MSG, 01625 FALL, 0); 01626 break; 01627 01628 case '\0': /* Oops, premature end of format */ 01629 fmterr(pfmt, EXPECTING_RIGHT_PAREN, FALL, 0); 01630 return(0); 01631 01632 default: /* Unknown edit-descriptor */ 01633 fmterr(pfmt, UNKNOWN_EDIT_DESCRIPTOR, FALL, 0); 01634 recover(pfmt); 01635 break; 01636 01637 } /* switch */ 01638 01639 if (pfmt->fmt_ch == ',') { 01640 register long col; 01641 01642 col = pfmt->fmt_pos; /* Position of comma */ 01643 01644 GET(pfmt); 01645 01646 if (pfmt->fmt_ch == ')') { 01647 pfmt->desc_col = col; 01648 fmterr(pfmt, COMMA_NON_ANSI, FALL, col); 01649 } 01650 } 01651 else 01652 if (comma_req_flag) 01653 switch (pfmt->fmt_ch) { 01654 01655 case ')': 01656 case ':': 01657 case '/': 01658 case '\0': 01659 break; 01660 01661 default: 01662 fmterr(pfmt, ANSI_COMMA_REQ, 01663 FALL, 0); 01664 break; 01665 } /* switch */ 01666 01667 if (pfmt->fatal_err && pfmt->caller == LIB_CALL) 01668 return(0); 01669 01670 } while (pfmt->fmt_ch != ')'); 01671 01672 if (outer_paren) { /* End of format found */ 01673 pfmt->pptr->op_code = REVERT_OP; 01674 pfmt->pptr->rep_count = pfmt->revert - pfmt->pptr; 01675 pfmt->pptr->offset = pfmt->fmt_pos; 01676 pfmt->pptr->rgcdedf = data_ed; 01677 pfmt->pptr = pfmt->pptr + 1; 01678 } 01679 else { 01680 01681 /* 01682 * End of internal parentheses group. Try to simplify the parsed 01683 * format by attempting to coalesce entries. Entries are coalesced 01684 * if one of the following conditions applies: 01685 * 01686 * 1) Empty or redundant parentheses groups. Constructs of the form: 01687 * '...()...' or '((...))' can be removed or simplified in the 01688 * parsed format. 01689 * 01690 * 2) Singly-repeated parentheses group. Constructs of the form: 01691 * '(...)' or '1(...)' can be simplified to '...'. 01692 * 01693 * 3) Single edit-descriptor parentheses group. Constructs of the 01694 * form: '...n(e)...' or '...n(m(e))...', where 'e' is any single 01695 * edit-descriptor and 'n' and 'm' are repetition counts, can be 01696 * simplified to '...ne...' or '...n*me...', respectively. 01697 * 01698 * a) If the single edit-descriptor is a P, BN, BZ, S, SP, SS, : 01699 * or $ descriptor, the repeat count is ignored. So a format 01700 * of the form: '...15(BZ)...' becomes '...BZ...'. 01701 * 01702 * b) If the single edit-descriptor is a TL, TR, T or X edit- 01703 * descriptor, the repeat count is folded into the count (width) 01704 * field. So a format of the form: '...4(5X)...' becomes 01705 * '...20X...'. 01706 * 01707 * c) For all other edit-descriptors, the repeat count is folded 01708 * into the existing repeat count. So a format of the form: 01709 * '...3(4F9.2)...' becomes '...12F9.2...'. 01710 * 01711 * Entries are NOT coalesced if their combined rep_count fields would 01712 * exceed the maximum possible rep_count. Note that any possible 01713 * reversion point must be marked before a parentheses group is removed. 01714 * 01715 * Note that two adjacent identical edit descriptors which do not span 01716 * a reversion point could be coalesced (e.g., 'I8,I8' to '2I8'); but 01717 * in this case the offset field would be incorrect for some of the 01718 * coalesced edit descriptors. If a run-time error occurred while 01719 * processing one of those edit descriptors the run-time diagnostic 01720 * might point at the wrong edit descriptor. 01721 */ 01722 01723 if (pfmt->depth == 1) 01724 pfmt->revert = ploc; /* Mark possible reversion point */ 01725 01726 if (ploc + 1 == pfmt->pptr && ploc->op_code == REPEAT_OP) { 01727 01728 /* Clear empty parentheses group and remove it */ 01729 01730 pfmt->pptr = pfmt->pptr - 1; 01731 01732 (void) memset((void *) pfmt->pptr, 0, 2 * sizeof(fmt_type)); 01733 01734 } 01735 else { 01736 01737 if ((num_eds == 1 || /* If one edit-descriptor or */ 01738 (ploc->op_code == REPEAT_OP && 01739 ploc->rep_count == 1) ) && /* Unary repeat count */ 01740 ploc->rep_count * (ploc+1)->rep_count < 01741 MAX_REP_COUNT) { 01742 01743 unsigned int size; 01744 fmt_type *ppsp; 01745 01746 /* Coalesce entries */ 01747 01748 pfmt->pptr = pfmt->pptr - 1; 01749 ppsp = ploc + 1; 01750 01751 switch (ppsp->op_code) { 01752 01753 case P_ED: 01754 case BN_ED: 01755 case BZ_ED: 01756 case COLON_ED: 01757 case S_ED: 01758 case SP_ED: 01759 case SS_ED: 01760 case T_ED: 01761 case DOLLAR_ED: 01762 01763 /* Simply ignore rep_count */ 01764 01765 break; 01766 01767 case SLASH_ED: 01768 case TL_ED: 01769 case TR_ED: 01770 01771 /* 01772 * Fold rep_count into width, 01773 * if it'll fit. 01774 */ 01775 01776 size = ploc->rep_count * 01777 ppsp->field_width; 01778 01779 if (size < MAX_FIELD_WIDTH) { 01780 ppsp->field_width = 01781 size; 01782 ppsp->rep_count = 1; 01783 } 01784 else /* Fold into rep_count */ 01785 ppsp->rep_count = 01786 ppsp->rep_count * 01787 ploc->rep_count; 01788 01789 break; 01790 01791 default: 01792 01793 /* Cascade rep_counts */ 01794 01795 ppsp->rep_count = 01796 ppsp->rep_count * 01797 ploc->rep_count; 01798 break; 01799 01800 } /* switch (ppsp->op_code) */ 01801 01802 /* Move entries */ 01803 01804 (void) memmove((void *) ploc, (void *) ppsp, 01805 (pfmt->pptr - ploc) * sizeof(fmt_type)); 01806 01807 /* Clear vacated entries */ 01808 01809 (void) memset((void *) pfmt->pptr, 0, 2 * sizeof(fmt_type)); 01810 01811 } 01812 else { 01813 pfmt->pptr->op_code = ENDREP_OP; 01814 pfmt->pptr->rep_count = ploc - pfmt->pptr; 01815 pfmt->pptr->offset = pfmt->fmt_pos; 01816 pfmt->pptr = pfmt->pptr + 1; 01817 01818 if (pfmt->maxdepth < pfmt->depth) 01819 pfmt->maxdepth = pfmt->depth; 01820 } 01821 } 01822 } 01823 01824 pfmt->depth = pfmt->depth - 1; 01825 01826 GET(pfmt); 01827 01828 if (data_ed) 01829 num_eds = -num_eds; 01830 01831 return(num_eds); 01832 01833 } /* process_paren_group */