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 #pragma ident "@(#) libf/fio/rnl90to77.c 92.3 06/21/99 10:37:55" 00039 00040 #include <stdio.h> 00041 #include <errno.h> 00042 #include <liberrno.h> 00043 #include <fortran.h> 00044 #include <stdlib.h> 00045 #include <cray/fmtconv.h> 00046 #include <cray/nassert.h> 00047 #if !defined(_ABSOFT) 00048 #include <sys/unistd.h> 00049 #endif 00050 #include "fio.h" 00051 #include "namelist.h" 00052 #include "rnl90def.h" 00053 #include "fmt.h" 00054 00055 /* EXTERNAL entry points */ 00056 extern int _s_scan_extensions(void *ptr, ftype_t type, unsigned elsize, 00057 long *field_begin, unsigned rec_chars, int *fwptr, long cmode); 00058 extern int _nicverr(const int _Nicverror); 00059 00060 /* use SUBGTC when the character retrieval cannot hit an end of file until 00061 * the retrieval is complete. This occurs when retrieving the characters of 00062 * a name. CMTSUBGT is the same except a constant is allowed in the scan. 00063 * These two macros are used from functions outside the main namelist FRN 00064 * routine. 00065 */ 00066 00067 #define SUBGTC(x) { \ 00068 while (cup->ulinecnt == 0) { \ 00069 if (errn = _nlrd_fillrec(css, cup, echoptr)) { \ 00070 return(errn); \ 00071 } \ 00072 } \ 00073 x = (char) *cup->ulineptr++; \ 00074 cup->ulinecnt--; \ 00075 } 00076 00077 #define CMTSUBGT(x) { \ 00078 while (cup->ulinecnt == 0) { \ 00079 if (errn = _nlrd_fillrec(css, cup, echoptr)) { \ 00080 return(errn); \ 00081 } \ 00082 } \ 00083 x = (char) *cup->ulineptr++; \ 00084 /* An f90 input comment is now part of RNLCOMM */ \ 00085 if (MATCH(x, _MASKS, MRNLCOMM)) { \ 00086 x = ' '; \ 00087 cup->ulinecnt = 1; \ 00088 } \ 00089 cup->ulinecnt--; \ 00090 } 00091 00092 #define CMTSUBGTNOEOR(x) { \ 00093 if (cup->ulinecnt == 0) { \ 00094 x = ' '; \ 00095 } else { \ 00096 x = (char) *cup->ulineptr++; \ 00097 cup->ulinecnt--; \ 00098 } \ 00099 /* An f90 input comment is now part of RNLCOMM */ \ 00100 if (MATCH(x, _MASKS, MRNLCOMM)) { \ 00101 x = ' '; \ 00102 cup->ulinecnt = 1; \ 00103 } \ 00104 } 00105 00106 /* use MAINGT when the character retrieval can hit an end of file before 00107 * retrieval is complete. This occurs when retrieving '=', delimiters, 00108 * , etc. CMTMAINGT is the same except a comment is allowed in the scan. 00109 * These two macros are used from functions within the main namelist FRN 00110 * routine. 00111 */ 00112 00113 #define MAINGT(x) { \ 00114 while (cup->ulinecnt == 0) { \ 00115 if (errn = _nlrd_fillrec(css, cup, echoptr)) { \ 00116 if (errn < 0) { \ 00117 ENDD(endf, css, FERDPEOF); \ 00118 } \ 00119 else { \ 00120 ERROR0(errf, css, errn); \ 00121 } \ 00122 } \ 00123 } \ 00124 x = (char) *cup->ulineptr++; \ 00125 cup->ulinecnt--; \ 00126 } 00127 00128 #define CMTMAINGT(x) { \ 00129 while (cup->ulinecnt == 0) { \ 00130 if (errn = _nlrd_fillrec(css, cup, echoptr)) { \ 00131 if (errn < 0) { \ 00132 ENDD(endf, css, FERDPEOF); \ 00133 } \ 00134 else { \ 00135 ERROR0(errf, css, errn); \ 00136 } \ 00137 } \ 00138 } \ 00139 x = (char) *cup->ulineptr++; \ 00140 /* An f90 input comment is now part of RNLCOMM */ \ 00141 if (MATCH(x, _MASKS, MRNLCOMM)) { \ 00142 x = ' '; \ 00143 cup->ulinecnt = 1; \ 00144 } \ 00145 cup->ulinecnt--; \ 00146 } 00147 00148 #define GETSECTION(x) { \ 00149 field_begin = cup->ulineptr; \ 00150 field_end = cup->ulineptr; \ 00151 for (j = 0; j < cup->ulinecnt; j++) { \ 00152 x = (char) *field_end; \ 00153 if (x == ')' || x == ',' || x == ':') \ 00154 break; \ 00155 field_end++; \ 00156 } \ 00157 field_width = j; \ 00158 } 00159 00160 /* 00161 * Use GETSTR77 to read a character string surrounded by quotes or 00162 * apostrophes. Comment characters are not recognized as such inside a 00163 * quoted string, so SUBGTC is used. Skip the ending blank. 00164 */ 00165 #define GETSTR77() { \ 00166 if (cup->ulinecnt <= 1) { \ 00167 SUBGTC(ch); \ 00168 } \ 00169 SUBGTC(ch); \ 00170 if (ch == enddelim) { \ 00171 eos = -1; /* end of string */ \ 00172 SUBGTC(ch); /* unless string delimiter is doubled */ \ 00173 if (ch == enddelim) \ 00174 eos = 0; \ 00175 else { \ 00176 cup->ulineptr--; \ 00177 cup->ulinecnt++; \ 00178 } \ 00179 } \ 00180 } 00181 00182 /* 00183 * eunit is unit for echoing inpt. If rnlecho is 1, always echo. 00184 * If rnlecho is 0, echo only if 'E' in first column. 00185 */ 00186 00187 struct Echoinfo { 00188 unum_t eunit; 00189 int rnlecho; 00190 }; 00191 00192 /* 00193 * This table is used to drive the f90 input conversion based on the 00194 * type of the data. 00195 */ 00196 ic_func *ncf_tab77[] = { 00197 NULL, /* DVTYPE_UNUSED */ 00198 NULL, /* DVTYPE_TYPELESS */ 00199 _iu2s, /* DVTYPE_INTEGER */ 00200 _defgu2sd, /* DVTYPE_REAL */ 00201 _defgu2sd, /* DVTYPE_COMPLEX */ 00202 NULL, /* DVTYPE_LOGICAL */ 00203 NULL, /* DVTYPE_ASCII */ 00204 }; 00205 00206 00207 /* MATCH(c,a,b) determines whether the bit for character 'c' is set. 00208 * a[b] and a[b+1] are bit masks for each ASCII character 00209 */ 00210 #define MATCH(c,a,b) (a[(c >= 0x3f) ? b+1 : b] & (1 << (IND(c)))) 00211 00212 /* IND computes the bit index of a character */ 00213 #define IND(c) ((c >= 0x3f) ? 0x7f - (unsigned)c : (unsigned)(0x40 - c - 1)) 00214 00215 static void _nlrdecho(unum_t eunit, long *input_ptr, long nchrs, FIOSPTR css); 00216 00217 static int _nlrd_fillrec(FIOSPTR css, unit *cup, struct Echoinfo *echoptr); 00218 00219 static void _setunit(char *string, void *u); 00220 00221 static int _getname(FIOSPTR css, unit *cup, char *buf, char *lastc, 00222 struct Echoinfo *echoptr); 00223 00224 static void _pr_echomsg(char *string); 00225 00226 static void _cnvrt_toupper(char *bufr); 00227 00228 static int _ishol(long *hlptr, unit *cup); 00229 00230 static nmlist_goli_t *_findname(char *key, nmlist_goli_t *nlvar, 00231 unsigned countitm); 00232 00233 static int _getnlval(FIOSPTR css, nmlist_goli_t *nlvar, char *lastc, 00234 unit *cup, struct Echoinfo *echoptr); 00235 00236 static int _indx_nl(FIOSPTR css, unit *cup, struct Echoinfo *echoptr, 00237 long *begcnt, int *ndim, long strbegend[3], int *encnt, int *icnt, 00238 int arryflag); 00239 00240 static int _nlread(FIOSPTR css, ftype_t type, void *ptr, int cnt, int inc, 00241 char *lastc, unit *cup, struct Echoinfo *echoptr, int elsize); 00242 00243 static int _nexdata(FIOSPTR css, ftype_t type, void *ptr, int cnt, int inc, 00244 char lastc, unit *cup, struct Echoinfo *echoptr, long *lval, 00245 int *lcount, int elsize, int *nullvlu); 00246 00247 static int _g_charstr(FIOSPTR css, unit *cup, void *p, int cnt, char c, 00248 struct Echoinfo *echoptr, int lcount,int elsize, int *nullvlu); 00249 00250 static int _g_complx(FIOSPTR css, unit *cup, ftype_t type, 00251 struct Echoinfo *echoptr, long *lval,int elsize); 00252 00253 static int _g_number(ftype_t type, unit *cup,long *lval, int elsize); 00254 00255 static int _gocthex(FIOSPTR css, unit *cup, ftype_t type, 00256 struct Echoinfo *echoptr, long *lval, int base, int elsize, 00257 int *nullvlu); 00258 00259 static int _get_holl(FIOSPTR css, unit *cup, char holltype, int count, 00260 ftype_t type, struct Echoinfo *echoptr, long *lval, int elsize); 00261 00262 static int _get_quoholl(FIOSPTR css, unit *cup, char cdelim, ftype_t type, 00263 struct Echoinfo *echoptr, long *lval, int elsize); 00264 00265 /* 00266 * _rnl90to77 - called by wnl90.c to process a cf77 namelist input 00267 * file. 00268 * Synopsis 00269 * int _rnl90to77(FIOSPTR css, 00270 * unit *cup, 00271 * nmlist_group *namlist, 00272 * void *stck, 00273 * int errf); 00274 * Where 00275 * css - pointer to css 00276 * cup - pointer to unit information 00277 * namlist - pointer to the namelist table. 00278 * stck - pointer to stack space which is passed 00279 * to each call to _FRU for a particular 00280 * statement. This is used by the library. 00281 * errf - error processing flag. 00282 * endf - end processing flag. 00283 * Return value 00284 * errn 00285 */ 00286 00287 int 00288 _rnl90to77( 00289 FIOSPTR css, 00290 unit *cup, 00291 nmlist_group *namlist, 00292 void *stck, 00293 int errf, 00294 int endf) 00295 { 00296 long stat; 00297 long *hlptr; 00298 int ret; 00299 int ss; 00300 char buf[MAXNAML + 5], c; 00301 char skipmsg[sizeof(SKIPMSG) + sizeof(UNITSTR) + 00302 MAXNAML + 8 + 2]; 00303 char tmpbuf[MXUNITSZ];/* Unit number buffer for warn msgs */ 00304 int errn; /* Error number */ 00305 long flag; /* Error flag */ 00306 unum_t unum; /* Actual unit number */ 00307 unsigned rlen; /* group name length */ 00308 unsigned rcount; /* count of namelist items */ 00309 char *rptr; /* pointer to group name */ 00310 char *varptr; /* ptr to group_obj_list item */ 00311 unsigned varlen; /* len of group_obj_list name */ 00312 nmlist_goli_t *nlvar; /* ptr to next variable entry */ 00313 nmlist_goli_t *fdvar; /* ptr to next variable entry */ 00314 ftype_t type; 00315 struct Echoinfo echoinfo; 00316 struct Echoinfo *echoptr; 00317 type = DVTYPE_UNUSED; 00318 varptr = NULL; 00319 00320 /* ************************************************************************** 00321 * Data Transfer Section 00322 ************************************************************************* */ 00323 00324 unum = cup->uid; 00325 echoptr = &echoinfo; 00326 00327 /* set up extended record. */ 00328 if (cup->ulinecnt == 0) 00329 cup->ulinecnt = 1; 00330 *(cup->ulinebuf + cup->ulinecnt) = (_f_int) BLANK; 00331 (void) strcpy(skipmsg, SKIPMSG); 00332 00333 /* Set up the unit used for echoing input lines */ 00334 if (_OUT_UNIT < 0) { 00335 echoinfo.eunit = 101; /* default = stdout */ 00336 echoinfo.rnlecho = 0; /* no echo til 'E' in col 1 */ 00337 } 00338 else { 00339 echoinfo.eunit = _OUT_UNIT; 00340 echoinfo.rnlecho = 1; /* always echo, ignore col1 */ 00341 } 00342 /* Input record preREAD before this point. Check for echoing. */ 00343 if ((echoptr->rnlecho) || 00344 (MATCH(*cup->ulinebuf, _MASKS, MRNLFLAG))) { 00345 /* Begin echoing input */ 00346 echoptr->rnlecho = 1; 00347 _nlrdecho(echoptr->eunit, cup->ulinebuf, cup->ulinecnt, css); 00348 } 00349 cup->ulineptr = cup->ulinebuf + 1; 00350 fill: 00351 while (cup->ulinecnt == 0) { 00352 errn = _nlrd_fillrec(css, cup, &echoinfo); 00353 if (errn != 0) 00354 goto err_eof; 00355 } 00356 fill1: 00357 do { 00358 CMTMAINGT(c) 00359 } while (ISBLANK(c)); 00360 if (!(MATCH(c, _MASKS, MRNLDELIM))) { 00361 /* irix f77 and cft77 skip the input record when the 00362 * first nonblank character is not a dollar sign or 00363 * an ampersand which delimits a namelist group name. 00364 */ 00365 cup->ulinecnt = 0; 00366 goto fill; /* Comment statement */ 00367 } 00368 00369 /* get first character of namelist group name from input record */ 00370 MAINGT(c); 00371 /* and get namelist group name from input record */ 00372 errn = _getname(css, cup, buf, &c, &echoinfo); 00373 if (errn != 0) 00374 goto err_eof; 00375 /* convert group name to uppercase */ 00376 _cnvrt_toupper(buf); 00377 00378 assert ( (cup != NULL)); 00379 rcount = namlist->icount; /* number of name table entries */ 00380 rptr = _fcdtocp(namlist->group_name);/* ptr to groupname */ 00381 rlen = _fcdlen(namlist->group_name); /* len of groupname */ 00382 nlvar = namlist->goli; /* group object ptr */ 00383 00384 if (strncmp(rptr,buf,rlen)) { 00385 int i; 00386 /* do not put out skipped record message for assign -f 00387 * irixf77 or irixf90 option, or 'assign -Y on' option. 00388 */ 00389 if ((cup->ufnl_skip != 0) || 00390 (cup->ufcompat == AS_IRIX_F77) || 00391 (cup->ufcompat == AS_IRIX_F90)) 00392 goto get_delim; 00393 if (_SKP_MESS > 0) { 00394 /* Skip record and issue a logfile message */ 00395 (void) strcpy(&skipmsg[sizeof(SKIPMSG)-1], buf); 00396 (void) strcat(skipmsg, UNITSTR); 00397 _setunit(tmpbuf, &unum); 00398 /* 00399 * The following truncates the file name/unit number 00400 * to seven characters, which will result in a loss 00401 * of information when the unit number is larger than 00402 * 9,999,999. 00403 */ 00404 (void) strncat(skipmsg, tmpbuf, sizeof(long) - 1); 00405 (void) strcat(skipmsg, "\n"); 00406 _pr_echomsg(skipmsg); 00407 } 00408 else if (_SKP_MESS < 0) { 00409 /* Abort job or go to optional ERR= branch */ 00410 errn = FENLIVGP; 00411 ERROR1(errf, css, errn, buf); 00412 } 00413 get_delim: 00414 /* the name is not the namelist group name needed, 00415 * read until delimiter found. 00416 */ 00417 while (!MATCH(c, _MASKS, MRNLDELIM) && c != '/') { 00418 if (c == '\'' || c == '"') { 00419 char qchar; 00420 qchar = c; 00421 rquote: 00422 do { 00423 MAINGT(c); 00424 } while (c != qchar); 00425 MAINGT(c); 00426 /* check for double quote */ 00427 if (c == qchar) 00428 goto rquote; 00429 } 00430 else { 00431 CMTMAINGT(c); 00432 } 00433 } 00434 /* 00435 * Try to determine whether delimiter is part of a 00436 * Hollerith string by looking back in record. If it 00437 * is part of a Hollerith string, it's not really an 00438 * end delimiter. 00439 */ 00440 hlptr = cup->ulineptr - 2; 00441 /* 00442 * Search for nH, nh, nl, nL, nr, nR where n = digit. 00443 * Only look back the number of characters in a default 00444 * integer or to the beginning of this line of input 00445 */ 00446 for (i = 0; i < (sizeof(_f_int)) && 00447 hlptr > &cup->ulinebuf[2]; i++, hlptr--) { 00448 switch((char) *hlptr) { 00449 case 'h': 00450 case 'H': 00451 case 'l': 00452 case 'L': 00453 case 'r': 00454 case 'R': 00455 if (_ishol(hlptr, cup)) { 00456 CMTMAINGT(c); 00457 goto get_delim; 00458 } 00459 break; 00460 default: 00461 break; 00462 } /* switch */ 00463 } 00464 goto fill1; 00465 } 00466 /* 00467 * This is the correct namelist group name. Process the 00468 * input record. Read until the input record or records 00469 * until the terminating character is found. This is a 00470 * slash or ampersand or MRNLDELIM. 00471 */ 00472 while (c != '/') { 00473 int sepcnt; 00474 if (MATCH(c, _MASKS, MRNLDELIM)) 00475 goto finalization; 00476 /* get group_object_name from input record */ 00477 errn = _getname(css, cup, buf, &c, &echoinfo); 00478 if (errn != 0) 00479 goto err_eof; 00480 _cnvrt_toupper(buf); 00481 /* find matching group_object_name from namelist table */ 00482 if (!(fdvar = _findname(buf, nlvar, rcount))) { 00483 if (strlen(buf) > 0) { 00484 /* An objectlistname in input record */ 00485 errn = FENLNREC; 00486 ERROR1(errf, css, errn, buf); 00487 } 00488 else { 00489 /* No object list name in input record */ 00490 errn = 0; /* empty variable entry */ 00491 goto finalization; 00492 } 00493 } 00494 /* we're positioned just after the object name 00495 * so get following value(s) 00496 */ 00497 errn = _getnlval(css, fdvar, &c, cup, &echoinfo); 00498 if (errn != 0) 00499 goto err_eof; 00500 sepcnt = 0; 00501 for ( ; ; ) { 00502 if (!(ISBLANK(c))) { 00503 if ((MATCH(c, _MASKS, MRNLSEP)) && 00504 (sepcnt == 0)) { 00505 /* skip separator */ 00506 sepcnt++; 00507 } 00508 else 00509 break; 00510 } 00511 CMTMAINGT(c); 00512 } 00513 } 00514 00515 /*************************************************************************** 00516 * Statement Finalization Section 00517 ***************************************************************************/ 00518 finalization: 00519 return(errn); 00520 err_eof: 00521 /* err and eof handling */ 00522 if(errn < 0) { 00523 ENDD(endf, css, FERDPEOF); 00524 } else if (errn == FENLSTRN || errn == FENLSTRG || 00525 errn == FENLSUBD || errn == FENLSUBN || 00526 errn == FENLSUBS || errn == FENLIVIT || 00527 errn == FENLARSC || errn == FENLLGNM || 00528 errn == FENLUNKI || errn == FENLUNKN) { 00529 ERROR1(errf, css, errn, buf); 00530 } else { 00531 ERROR0(errf, css, errn); 00532 } 00533 goto finalization; 00534 } 00535 00536 /* _nlrd_fillrec - namelist read of one record from a file 00537 * returns 0 - successful 00538 * EOF - end of file 00539 * ERR - error was encountered 00540 * cup->uend is set if EOF encountered 00541 */ 00542 00543 static int 00544 _nlrd_fillrec(FIOSPTR css, unit *cup, struct Echoinfo *echoptr) 00545 { 00546 register int errn; 00547 00548 errn = css->u.fmt.endrec(css, cup, 1); 00549 00550 if (errn != 0) { 00551 return(errn); 00552 } else { 00553 if (cup->ulinecnt == 0) 00554 cup->ulinecnt = 1; /* Assume it has 1 blank */ 00555 /* Add a blank character to end of record */ 00556 *(cup->ulinebuf + cup->ulinecnt) = (long) BLANK; 00557 if ((echoptr->rnlecho) || 00558 (MATCH(*cup->ulinebuf, _MASKS, MRNLFLAG))) { 00559 /* Begin echoing input */ 00560 echoptr->rnlecho = 1; 00561 _nlrdecho(echoptr->eunit, cup->ulinebuf, 00562 cup->ulinecnt, css); 00563 } 00564 /* Always skip the first character in a record. 00565 * Don't adjust ulinecnt because blank added at the end. 00566 */ 00567 cup->ulineptr++; 00568 } 00569 return(errn); 00570 } 00571 00572 /* 00573 * _getname - Get variable name or group name 00574 * 00575 * On entry: 00576 * - Positioned to a name possibly preceded by blanks 00577 * On exit: 00578 * - 0 if successful 00579 * EOF if end of file read 00580 * > 0 if other error (errno will be set) 00581 * - *cup->ulineptr is record position after the name. 00582 * - *lastc contains the last character read. 00583 * In looking for the name, we stop when we see a space, '=', or 00584 * '(', or delimiter ('&'), or the replacement character for '='. 00585 */ 00586 00587 static int 00588 _getname(FIOSPTR css, unit *cup, char *s, char *lastc, struct Echoinfo *echoptr) 00589 { 00590 char *p, c; 00591 int n, errn; 00592 errn = 0; 00593 n = MAXNAML + 5; /* real*16 input can be 34 characters long */ 00594 p = s; 00595 c = *lastc; 00596 /* 00597 * Names cannot have embedded blanks. In cf77 compatibility mode, 00598 * a comment can immediately follow the name and will terminate it. 00599 */ 00600 while (ISBLANK(c)) 00601 CMTSUBGT(c); 00602 00603 while (!(ISBLANK(c)) && (c != '(') && !(MATCH(c, _MASKS, MRNLREP)) && 00604 !(MATCH(c, _MASKS, MRNLDELIM)) && (c != '/')) { 00605 *p++ = c; 00606 CMTSUBGTNOEOR(c); 00607 if (n-- == 0) { 00608 errn = FENLLGNM; /* name too long */ 00609 p--; 00610 break; 00611 } 00612 } 00613 *lastc = c; 00614 *p = '\0'; 00615 return (errn); 00616 } 00617 00618 /* 00619 * _findname - find variable name in list of nmlist_goli_t entries 00620 * of namelist table 00621 * On entry: 00622 * - lastc points to character following name in input buffer. 00623 * Returns: 00624 * pointer to matching object list entry 00625 * NULL if variable name was not found. 00626 */ 00627 00628 static nmlist_goli_t 00629 *_findname(char *key, nmlist_goli_t *nlvar, unsigned countitm) 00630 { 00631 char *varptr; 00632 unsigned varlen; 00633 nmlist_goli_t *newitem; 00634 int cnt, lcnt; 00635 00636 newitem = nlvar; 00637 cnt = countitm; 00638 lcnt = strlen(key); 00639 00640 while (cnt--) { 00641 varptr = _fcdtocp(newitem->goli_name); 00642 varlen = _fcdlen(newitem->goli_name); 00643 if ((varlen == lcnt) && (!strncmp(key, varptr, lcnt))) 00644 return (newitem); 00645 else 00646 #if defined(__mips) && (_MIPS_SZLONG == 32) 00647 newitem = (nmlist_goli_t*)((long *)newitem + 00648 3 + (sizeof(_fcd))/(sizeof(long))); 00649 #else 00650 newitem = (nmlist_goli_t*)((long *)newitem + 00651 2 + (sizeof(_fcd))/(sizeof(long))); 00652 #endif 00653 } 00654 return (NULL); 00655 } 00656 00657 /* _getnlval - get values for namelist io 00658 * 00659 * On entry: 00660 * - positioned after variable name 00661 * - lastc contains the character following the name 00662 * On exit: 00663 * - *lastc contains the character following the value 00664 * - cup->ulineptr is pointing to the character following lastc 00665 * - returns: 0 if successful 00666 * -value if EOF detected 00667 * > 0 if error detected 00668 */ 00669 00670 static int 00671 _getnlval(FIOSPTR css, nmlist_goli_t *nlvar, char *lastc, unit *cup, 00672 struct Echoinfo *echoptr) 00673 { 00674 long ss, cntp; 00675 long stat; 00676 int ndim = 0; 00677 int i; 00678 int encnt = 0; 00679 int icnt = 0; 00680 long begcnt[MAXDIM]; 00681 long strbegend[3]; 00682 char *cp; 00683 char c; 00684 long vaddr; 00685 long errn = 0; 00686 /* clear array element and substring information */ 00687 for (i=0; i < MAXDIM; i++) { 00688 begcnt[i] = 0; 00689 } 00690 strbegend[0] = -1; 00691 strbegend[1] = -1; 00692 strbegend[2] = -1; 00693 00694 switch (nlvar->valtype) { 00695 case IO_SCALAR: 00696 { 00697 nmlist_scalar_t *nlscalar; /* nmlist scalar entry */ 00698 unsigned elsize; 00699 unsigned int_len; 00700 void *vaddr; 00701 ftype_t type; /* fortran data type */ 00702 00703 nlscalar = nlvar->goli_addr.ptr; /* ptr to scalar */ 00704 type = nlscalar->tinfo.type; 00705 int_len = nlscalar->tinfo.int_len; 00706 /* Assertions */ 00707 assert (type >= DVTYPE_TYPELESS && type <= DVTYPE_ASCII); 00708 assert(nlscalar->tinfo.int_len > 0 ); 00709 if ((type != DVTYPE_ASCII) && (*lastc == '(')) { 00710 errn = FENLUNKI; 00711 break; 00712 } 00713 if (type == DVTYPE_ASCII) 00714 strbegend[0] = 0; 00715 /* find offset if indexed array */ 00716 if (*lastc == '(') { 00717 errn = _indx_nl(css, cup, echoptr, begcnt, &ndim, 00718 strbegend, &encnt, &icnt, 0); 00719 if (errn != 0) { 00720 if (errn == FENLSUBS) 00721 errn = FENLSTRG; 00722 else if (errn == FENLSUBN) 00723 errn = FENLSTRN; 00724 break; 00725 } 00726 } 00727 else { 00728 while (ISBLANK(*lastc)) { 00729 CMTSUBGT(*lastc); 00730 } 00731 if (MATCH(*lastc, _MASKS, MRNLDELIM) || 00732 (*lastc == '/')) { 00733 errn = 0; 00734 break; 00735 } 00736 /* match '=' or special character */ 00737 if (!(MATCH(*lastc, _MASKS, MRNLREP))) { 00738 errn = FENLNOVL; 00739 break; 00740 } 00741 } 00742 CMTSUBGT(*lastc); 00743 00744 /* Currently positioned after the '=' sign, but lastc is 00745 * pointing at the '=' sign. Update lastc for nlread and 00746 * compute: 00747 * cntp = number of array elements to be read 00748 * (1 if not an array). 00749 * elsize = size of a variable or array element 00750 * (words for nonchar, bytes for char). 00751 * vaddr = target address for the input value. For 00752 * character, a Fortran character descriptor. 00753 */ 00754 if (type == DVTYPE_ASCII) { 00755 char *wptr; 00756 const int bytesperchar = 1; 00757 int begt = strbegend[1]; 00758 int endt = strbegend[2]; 00759 wptr = _fcdtocp(nlscalar->scal_addr.charptr); 00760 elsize = _fcdlen(nlscalar->scal_addr.charptr); 00761 elsize = elsize * bytesperchar; 00762 /* check for character substrings in input record */ 00763 if (strbegend[0] > 0) { 00764 if (begt < 1 ) 00765 begt = 1; 00766 else if (begt > elsize) { 00767 errn = FENLUNKN; 00768 break; 00769 } 00770 if (endt < 1 ) 00771 endt = elsize; 00772 else if ((endt > elsize) || (endt < begt)) { 00773 errn = FENLUNKN; 00774 break; 00775 } 00776 wptr = wptr + (begt - 1); 00777 elsize = (endt - begt) + 1; 00778 } 00779 vaddr = wptr; 00780 } 00781 else { 00782 vaddr = nlscalar->scal_addr.ptr; 00783 elsize = int_len >> 3; 00784 } 00785 c = *lastc; 00786 cntp = 1; 00787 errn = _nlread(css, type, vaddr, cntp, 0, &c, cup, echoptr, 00788 elsize); 00789 *lastc = c; 00790 break; 00791 } 00792 case IO_DOPEVEC: 00793 { 00794 struct DvDimen *dvdimn; 00795 struct DvDimen dimen[MAXDIM]; 00796 DopeVectorType *nldv; 00797 unsigned elsize; 00798 unsigned extent = 1; 00799 unsigned int_len; 00800 void *vaddr; 00801 int nc, mult, offs; 00802 ftype_t type; /* fortran data type */ 00803 nldv = nlvar->goli_addr.dv; /* ptr to dope vector */ 00804 mult = 1; 00805 offs = 0; 00806 00807 /* Assertions */ 00808 assert ( nldv != NULL ); 00809 assert ( nldv->type_lens.int_len > 0 ); 00810 type = nldv->type_lens.type; 00811 if (type == DVTYPE_ASCII) 00812 strbegend[0] = 0; 00813 for (i=0; i < nldv->n_dim; i++) { 00814 begcnt[i] = nldv->dimension[i].low_bound; 00815 } 00816 00817 /* find offset if indexed array */ 00818 if (*lastc == '(') { 00819 errn = _indx_nl(css, cup, echoptr, begcnt, &ndim, 00820 strbegend, &encnt, &icnt, 1); 00821 if (errn != 0) 00822 break; 00823 } 00824 else { 00825 while (ISBLANK(*lastc)) { 00826 CMTSUBGT(*lastc); 00827 } 00828 /* match '=' or special character */ 00829 if (!(MATCH(*lastc, _MASKS, MRNLREP))) { 00830 return(FENLNOVL); 00831 } 00832 } 00833 CMTSUBGT(*lastc); 00834 00835 /* Currently positioned after the '=' sign, but lastc is 00836 * pointing at the '=' sign. Update lastc for nlread and 00837 * compute: 00838 * cntp = number of array elements to be read 00839 * (1 if not an array). 00840 * elsize = size of a variable or array element 00841 * (words for nonchar, bytes for char). 00842 * vaddr = target address for the input value. For 00843 * character, a Fortran character descriptor. 00844 */ 00845 int_len = nldv->type_lens.int_len; 00846 if ((ndim != 0) && (ndim != nldv->n_dim)) { 00847 errn = FENLBNDY; 00848 break; 00849 } 00850 for (nc = 0; nc < nldv->n_dim; nc++) { 00851 extent *= nldv->dimension[nc].extent; 00852 } 00853 if (ndim > 0) { 00854 offs = begcnt[0] - (nldv->dimension[0].low_bound); 00855 for (nc = 1; nc < ndim; nc++) { 00856 mult = mult * (nldv->dimension[nc-1].extent); 00857 offs = offs + ((begcnt[nc] - 00858 nldv->dimension[nc].low_bound) * mult); 00859 } 00860 extent = extent - offs; 00861 } 00862 if (type == DVTYPE_ASCII) { 00863 char *wptr; 00864 const int bytesperchar = 1; 00865 int begt = strbegend[1]; 00866 int endt = strbegend[2]; 00867 wptr = _fcdtocp(nldv->base_addr.charptr); 00868 elsize = _fcdlen(nldv->base_addr.charptr); 00869 elsize = elsize * bytesperchar; 00870 /* check for character substrings in input record */ 00871 wptr += offs * elsize; 00872 if (strbegend[0] > 0) { 00873 if (begt < 1 ) 00874 begt = 1; 00875 else if (begt > elsize) { 00876 errn = FENLUNKN; 00877 return(errn); 00878 } 00879 if (endt < 1 ) 00880 endt = elsize; 00881 else if ((endt > elsize) || (endt < begt)) { 00882 errn = FENLUNKN; 00883 break; 00884 } 00885 wptr = wptr + (begt - 1); 00886 elsize = (endt - begt) + 1; 00887 } 00888 vaddr = wptr; 00889 } 00890 else { 00891 bcont *iwptr; 00892 iwptr = (bcont*)nldv->base_addr.a.ptr; 00893 elsize = int_len >> 3; 00894 iwptr += offs * (elsize / (sizeof(bcont))); 00895 vaddr = iwptr; 00896 } 00897 /* Assertions */ 00898 assert ( elsize > 0 && extent > 0 ); 00899 c = *lastc; 00900 cntp = extent; 00901 errn = _nlread(css, type, vaddr, cntp, 1, &c, cup, echoptr, 00902 elsize); 00903 *lastc = c; 00904 break; 00905 } 00906 case IO_STRUC_A: 00907 case IO_STRUC_S: 00908 { 00909 /* do not allow structures in cf77 files. */ 00910 errn = FENLSTCT; 00911 break; 00912 } 00913 default: 00914 errn = FEINTUNK; 00915 } 00916 return(errn); 00917 } 00918 00919 /* _nlread - calls _nexdata to get the next value and stores the 00920 * result in the namelist object entry. 00921 * On Entry - cup_ulineptr points to the first character following the 00922 * value. 00923 * On Exit - lastc will contain the first nonblank, nonseparator 00924 * character following the value. 00925 */ 00926 00927 static int 00928 _nlread(FIOSPTR css, ftype_t type, void *ptr, int cntp, int incrm, 00929 char *lastc, unit *cup, struct Echoinfo *echoptr, int elsize) 00930 { 00931 long ss, ncntp; 00932 long stat; 00933 char c; 00934 void *vaddr; 00935 long errn = 0; 00936 int lcount; /* repeat count for values */ 00937 long lval[9]; /* convert space */ 00938 bcont *sval; 00939 int nullvlu; 00940 c = *lastc; 00941 ncntp = cntp; 00942 vaddr = ptr; 00943 nullvlu = 0; 00944 00945 while (ncntp > 0) { 00946 errn = _nexdata(css, type, vaddr, ncntp, 1, c, cup, echoptr, 00947 lval, &lcount, elsize, &nullvlu); 00948 if (errn != 0) 00949 return(errn); 00950 else { 00951 if (nullvlu == 2) { 00952 lcount = 0; 00953 ncntp = 0; 00954 } 00955 } 00956 if (lcount > ncntp) { 00957 errn = FENLTOOM; 00958 return(errn); 00959 } 00960 if (type == DVTYPE_ASCII) { 00961 char *wptr; 00962 wptr = vaddr; 00963 /* character data already stored, adjust 00964 * ptr and count only. 00965 */ 00966 ncntp = ncntp - lcount; 00967 wptr = wptr + (lcount * elsize); 00968 vaddr = wptr; 00969 } 00970 else { 00971 int move; 00972 int *iptr; 00973 int ix, lim; 00974 bcont *siptr; 00975 move = MIN(ncntp,lcount); 00976 lim = elsize/(sizeof(bcont)); 00977 siptr = (bcont*) vaddr; 00978 /* move what's needed from data group */ 00979 while (move != 0) { 00980 sval = (bcont*) lval; 00981 /* do not move null values */ 00982 if (!nullvlu) { 00983 for (ix=0; ix < lim; ix++) { 00984 *siptr = *sval; 00985 siptr++; 00986 sval++; 00987 } 00988 } else 00989 siptr = siptr + lim; 00990 vaddr = siptr; 00991 move--; 00992 ncntp--; 00993 lcount--; 00994 } 00995 } 00996 /* get separator following value */ 00997 do { 00998 CMTSUBGT(*lastc); 00999 } while (ISBLANK(*lastc)); 01000 /* if separator, get next nonblank character on the 01001 * same line or on a new line. 01002 */ 01003 01004 if (MATCH(*lastc, _MASKS, MRNLSEP)) { 01005 do { 01006 CMTSUBGT(*lastc); 01007 } while (ISBLANK(*lastc)); 01008 } 01009 c = *lastc; 01010 } 01011 return(0); 01012 } 01013 01014 /* _indx_nl - compute the dimension information of an 01015 * indexed array in the input record. 01016 * On entry: 01017 * _ positioned just after the '(' 01018 * On exit: 01019 * - returns: 0 on success 01020 * -value on eof 01021 * - positioned just after the '=' 01022 * - the lastc argument is not changed 01023 */ 01024 01025 static int 01026 _indx_nl( 01027 FIOSPTR css, unit *cup, struct Echoinfo *echoptr, 01028 long *begcnt, int *ndima, long strbegend[3], 01029 int *encnt, int *icnt, int arryflag) 01030 { 01031 long *oldp, *newp; 01032 long mode, ss; 01033 long offs, mult; 01034 char c; 01035 int i, j, ir1, en1; 01036 long dummy; 01037 int errn = 0; 01038 long stat; 01039 long field_width; 01040 long *field_begin; 01041 long *field_end; 01042 long tempbuf[2]; 01043 en1 = 0; 01044 ir1 = 0; 01045 if (arryflag) { 01046 for (i = 0; i < MAXDIMS; ) { 01047 long dummy; 01048 /* no comments in namelist input here and 01049 * skip leading blanks here only. 01050 */ 01051 do { 01052 SUBGTC(c); 01053 } while (ISBLANK(c)); 01054 01055 /* Was end of subscripts reached in input record */ 01056 if (c == ')') 01057 break; 01058 cup->ulinecnt++; 01059 cup->ulineptr--; 01060 01061 /* Get the low_bound subscript information first */ 01062 GETSECTION(c); 01063 if (field_width == 0) 01064 goto indxgetext; 01065 /* pass field_end + 1 */ 01066 field_end++; 01067 tempbuf[0] = 0; 01068 tempbuf[1] = 0; 01069 mode = 0; 01070 (void) _iu2s(field_begin, &field_width, 01071 &field_end, &mode, tempbuf, &stat, 01072 &dummy, &dummy); 01073 if(stat < 0) { 01074 errn = FENLSUBS; 01075 return(errn); 01076 } 01077 begcnt[i] = *((_f_int8 *)tempbuf); 01078 indxgetext: 01079 /* point beyond subscript. */ 01080 cup->ulineptr = field_begin + field_width; 01081 cup->ulinecnt = cup->ulinecnt - field_width; 01082 01083 /* Get the extent subscript information */ 01084 if (c == ':') 01085 return(FENLARSC); 01086 01087 /* increment the number of subscripts */ 01088 i++; 01089 do { 01090 SUBGTC(c); /* get to ',' or ')' */ 01091 } while (ISBLANK(c)); /* NO EOR here */ 01092 /* check for end of subscripts */ 01093 if (c == ')') 01094 break; 01095 if (c != ',') { 01096 errn = FENLSUBD; /* not a comma */ 01097 return(errn); 01098 } 01099 } 01100 *ndima = i; 01101 *encnt = en1; 01102 *icnt = ir1; 01103 if (i == 0) { 01104 errn = FENLSUBN; /* null index */ 01105 return(errn); 01106 } 01107 } 01108 if (strbegend[0] == 0) { 01109 j = 0; 01110 if (arryflag) { 01111 SUBGTC(c); 01112 } else 01113 c = '('; 01114 /* Check for substring information after array element */ 01115 if (c == '(') { 01116 #if defined(__mips) || defined(_LITTLE_ENDIAN) 01117 /* skip leading blanks in input here */ 01118 do { 01119 SUBGTC(c); 01120 } while (ISBLANK(c)); 01121 if (c == ')') { 01122 errn = FENLSTRN; /* null index */ 01123 return(errn); 01124 } 01125 cup->ulinecnt++; 01126 cup->ulineptr--; 01127 #endif 01128 GETSECTION(c); 01129 if (field_width == 0) 01130 goto indxstrend; 01131 /* pass field_end + 1 */ 01132 field_end++; 01133 tempbuf[0] = 0; 01134 tempbuf[1] = 0; 01135 mode = 0; 01136 (void) _iu2s(field_begin, &field_width, &field_end, 01137 &mode, tempbuf, &stat, &dummy, &dummy); 01138 if(stat < 0) { 01139 errn = FENLSTRG; 01140 return(errn); 01141 } 01142 strbegend[1] = *((_f_int8 *)tempbuf); 01143 j++; 01144 indxstrend: 01145 /* point beyond colon. */ 01146 cup->ulineptr = field_begin + field_width; 01147 cup->ulinecnt = cup->ulinecnt - field_width; 01148 if (c == ':') { 01149 /* update ulineptr */ 01150 SUBGTC(c); 01151 #if defined(__mips) || defined(_LITTLE_ENDIAN) 01152 /* skip leading blanks in input here */ 01153 do { 01154 SUBGTC(c); 01155 } while (ISBLANK(c) || (c == ':')); 01156 if (c == ')') 01157 goto indxstrout; 01158 cup->ulinecnt++; 01159 cup->ulineptr--; 01160 #endif 01161 GETSECTION(c); 01162 if (field_width == 0) 01163 goto indxstrdon; 01164 /* pass field_end + 1 */ 01165 field_end++; 01166 tempbuf[0] = 0; 01167 tempbuf[1] = 0; 01168 mode = 0; 01169 (void) _iu2s(field_begin, &field_width, 01170 &field_end, &mode, tempbuf, 01171 &stat, &dummy, &dummy); 01172 if(stat < 0) { 01173 errn = FENLSTRG; 01174 return(errn); 01175 } 01176 strbegend[2] = *((_f_int8 *)tempbuf); 01177 j++; 01178 indxstrdon: 01179 /* point to right paren? */ 01180 cup->ulineptr = field_begin + field_width; 01181 cup->ulinecnt = cup->ulinecnt - field_width; 01182 } 01183 #if !defined(__mips) && !defined(_LITTLE_ENDIAN) 01184 else { 01185 errn = FENLSTRN; /* null index */ 01186 return(errn); 01187 } 01188 #endif 01189 indxstrout: 01190 strbegend[0] = j; 01191 } 01192 } 01193 /* 01194 * Look for the equal sign or the replacement character for that 01195 * character 01196 */ 01197 while (!(MATCH(c, _MASKS, MRNLREP))) { 01198 SUBGTC(c); 01199 } 01200 return(errn); 01201 } 01202 01203 /* 01204 * Set echo unit and Echo the line in input_ptr of length ncrs for cft77 01205 * with RNLECHO. 01206 */ 01207 01208 static void 01209 _nlrdecho( 01210 unum_t eunit, 01211 long *input_ptr, 01212 long ncrs, 01213 FIOSPTR css) 01214 { 01215 long stat; 01216 unit *echoup; 01217 long blk = BLANK; 01218 echoup = _get_cup(eunit); /* lock the unit */ 01219 if (echoup == NULL) { 01220 unit *cupsave; 01221 cupsave = css->f_cu; /* Save for _imp_open() */ 01222 echoup = _imp_open77(css, SEQ, FMT, eunit, 1, NULL); 01223 css->f_cu = cupsave; 01224 if (echoup == NULL) /* If OPEN failed */ 01225 return; 01226 } 01227 else { 01228 if (echoup->ufmt == 0) /* If unformatted file */ 01229 _ferr(css, FEFMTTIV); 01230 if (echoup->useq == 0) /* If direct access file */ 01231 _ferr(css, FESEQTIV); 01232 } 01233 /* 01234 * Output the blank that precedes the buffer for carriage control 01235 * Add one to cup->ulinecnt, so that the preceding blank is counted. 01236 */ 01237 (void) _fwch(echoup, &blk, 1, PARTIAL); 01238 (void) _fwch(echoup, input_ptr, ncrs, FULL); 01239 (void) _release_cup(echoup); /* unlock the unit */ 01240 return; 01241 } 01242 01243 /* _setunit - setup 01244 * Format the unit number or file name and copies to 'string' 01245 * for warning messages and echo of input lines for RNLECHO for cf77 01246 * compatibility. 01247 */ 01248 01249 static void 01250 _setunit( 01251 char *string, 01252 void *u) 01253 { 01254 register unum_t unum; 01255 01256 if (_is_file_name(*((long *)u))) 01257 (void) strncpy(string, (char *)u, sizeof(long) - 1); 01258 else { 01259 unum = *((unum_t *)u); 01260 (void) sprintf(string, "%lld", unum); 01261 } 01262 01263 return; 01264 } 01265 01266 static void 01267 _pr_echomsg(char *string) 01268 { 01269 (void) write(fileno(errfile), string, strlen(string)); 01270 01271 return; 01272 } 01273 01274 /* Converts the string in buf to upper case letters */ 01275 01276 static void 01277 _cnvrt_toupper(char *buf) 01278 { 01279 register char c; 01280 01281 while ((c = *buf) != '\0') 01282 *buf++ = toupper(c); 01283 01284 return; 01285 } 01286 01287 /* 01288 * ishol is only called by cf77 compatible entry 01289 * ENTRY: hlptr is a pointer to a possible Hollerith character 01290 * Returns: 0 if delimiter is not part of hollerith string 01291 * 1 if delimiter is part of hollerith string 01292 */ 01293 01294 static int 01295 _ishol(long *hlptr, unit *cup) 01296 { 01297 char hlval; 01298 01299 hlval = (char) *(hlptr - 1); 01300 if (isdigit(hlval) && ((hlval - '0') <= (sizeof(_f_int))) && ((hlval - '0') > 0)) { 01301 /* 01302 * We have digit followed by Hollerith designator, check 01303 * the preceding character. 01304 */ 01305 if (((hlval - '0') + hlptr) >= ((cup->ulineptr) - 1)) { 01306 /* Column 1 of ulinebuf[1] and is ignored */ 01307 if (hlptr > &cup->ulinebuf[3]) { 01308 hlval = (char) *(hlptr - 2); 01309 if (!ISBLANK(hlval) && hlval != '*' && 01310 !MATCH(hlval, _MASKS, MRNLREP) && 01311 !MATCH(hlval, _MASKS, MRNLSEP) ) 01312 return(0); 01313 } 01314 return(1); 01315 } 01316 return(0); /* Delimiter is beyond Hollerith string */ 01317 } 01318 return(0); 01319 } 01320 01321 /* _nexdata - get the next data group - position at the first character 01322 * following the value or values. 01323 * On return, lval will contain the value and lcount the repeat count 01324 * Outptr will point to character immediately following value 01325 * 01326 * The return value is: -value for EOF 01327 * 0 for ok 01328 * >0 if an error 01329 * nullvlu = 1 for null value read 01330 * 2 for null value, followed by possible 01331 * variable name 01332 */ 01333 static int 01334 _nexdata( 01335 FIOSPTR css, 01336 ftype_t type, /* Type of data item */ 01337 void *ptr, /* Address of data item */ 01338 int cnt, /* Number of values to look for */ 01339 int inc, 01340 char lastc, /* First character of value, may be blank */ 01341 unit *cup, /* Input unit */ 01342 struct Echoinfo *echoptr, 01343 long *lval, /* Value is placed here */ 01344 int *lcount, /* Repeat count is returned here */ 01345 int elsize, 01346 int *nullvlu) /* indicate if any nulls returned */ 01347 { 01348 char c, oc; 01349 int ocnt, ss; 01350 long *optr; 01351 int holcnt; /* Length of hollerith string */ 01352 long stat; 01353 char newc; 01354 int errn; 01355 *nullvlu = 0; 01356 c = lastc; 01357 while (ISBLANK(c)) { 01358 CMTSUBGT(c); 01359 } 01360 *lcount = 1; /* set repeat count */ 01361 if (isdigit((int) c)) { 01362 /* Look for repeat count. We can have a repeat count 01363 * for any type of data, including character. 01364 */ 01365 *lcount = c - '0'; 01366 ocnt = cup->ulinecnt; /* save count and pointer, in case */ 01367 optr = cup->ulineptr; /* this isn't repeat count */ 01368 oc = c; 01369 for (;;) { 01370 if (cup->ulinecnt > 0) { 01371 SUBGTC(c); /* Ignore comments */ 01372 } else 01373 break; 01374 if (isdigit((int) c)) 01375 *lcount = (*lcount * 10) + c - '0'; 01376 else 01377 break; 01378 } 01379 /* 01380 * Could have r*c, rH, rL, or rR, where r is the number just 01381 * read. No embedded blanks allowed in r*c, rH, rL, or rR. 01382 */ 01383 switch (c) { 01384 case '*': 01385 /* get next character with comment */ 01386 CMTSUBGT(c); 01387 if (isdigit((int) c)) { 01388 /* See if we have a repeat count followed 01389 * by hollerith, like 3*4Habcd 01390 */ 01391 holcnt = c - '0'; 01392 ocnt = cup->ulinecnt; 01393 optr = cup->ulineptr; 01394 oc = c; 01395 for (;;) { 01396 SUBGTC(c); 01397 if (isdigit((int) c)) 01398 holcnt = (holcnt * 10) + 01399 c - '0'; 01400 else 01401 break; 01402 } 01403 switch (c) { 01404 case 'H': 01405 case 'h': 01406 case 'R': 01407 case 'r': 01408 case 'L': 01409 case 'l': 01410 return(_get_holl(css, cup, c, holcnt, 01411 type, echoptr, lval, elsize)); 01412 default: 01413 /* backup restore */ 01414 cup->ulineptr = optr; 01415 /* cnt and ptr */ 01416 cup->ulinecnt = ocnt; 01417 c = oc; 01418 ocnt = 1; 01419 break; 01420 } /* switch */ 01421 } 01422 break; /* Ordinary repeat count */ 01423 case 'H': 01424 case 'h': 01425 case 'R': 01426 case 'r': 01427 case 'L': 01428 case 'l': 01429 /* Assume it is a Hollerith string, like 3Habc */ 01430 holcnt = *lcount; 01431 *lcount = 1; /* No repeats */ 01432 return(_get_holl(css, cup, c, holcnt, type, echoptr, 01433 lval, elsize)); 01434 default: 01435 /* No repeat count, backup restore, cnt & ptr */ 01436 cup->ulineptr = optr; 01437 cup->ulinecnt = ocnt; 01438 c = oc; 01439 ocnt = 1; 01440 *lcount = 1; 01441 break; 01442 } /* switch */ 01443 } 01444 /* END of isdigit() 01445 * Looking for a value. When we get here we are at a nonblank 01446 * character, unless we had the form r*, in which case it may 01447 * be followed by a blank (NULL). 01448 */ 01449 if (MATCH(c, _MASKS, MRNLSEP)) { 01450 cup->ulineptr--; /* reset cnt and ptr so */ 01451 cup->ulinecnt++; /* we can read separator again */ 01452 *nullvlu = 1; 01453 return(0); /* return null value */ 01454 } 01455 else if (ISBLANK(c)) { 01456 *nullvlu = 1; 01457 return(0); /* return null value */ 01458 } 01459 else { 01460 if (MATCH(c, _MASKS, MRNLCOMM)) { 01461 /* Use this path with input like: 01462 * A = 5*; 01463 */ 01464 *lval = *(lval+1) = 0; 01465 /* reset cnt and ptr so rest in record is read as 01466 * as null values 01467 */ 01468 cup->ulinecnt++; 01469 cup->ulineptr--; 01470 *nullvlu = 1; 01471 return(0); /* return null value */ 01472 } 01473 else 01474 if (MATCH(c, _MASKS, MRNLDELIM) || (c == '/')) { 01475 /* treated terminating slash or ampersand 01476 * the same for f90 to allow simpler 01477 * non-f90 compatibility. 01478 */ 01479 cup->ulineptr--; /* reset cnt and ptr so */ 01480 cup->ulinecnt++; /* read delimiter again */ 01481 *nullvlu = 2; 01482 return(0); /* Return null value */ 01483 } 01484 } 01485 /* 01486 * It is important that we handle the special cases of types logical 01487 * and character first, because the format of their data is treated 01488 * differently. 01489 */ 01490 if (type == DVTYPE_LOGICAL) { 01491 bcont *slval; 01492 slval = (bcont*)lval; 01493 /* Looking for a logical value. Logical values must be of 01494 * the form: optional decimal point, followed by a 'T' for 01495 * true or an 'F' for false, optionally followed by one 01496 * or more additional characters. Those additional 01497 * characters cannot include '=', ',', ':', ';', '(', '$' 01498 * or '&'. 01499 */ 01500 if (c == '.') { 01501 SUBGTC(c); 01502 /* .T or .t assumed to be a logical value */ 01503 if ((c == 'T') || (c == 't')) { 01504 switch (elsize) { 01505 #ifdef _F_REAL4 01506 case 4: 01507 *(_f_log4 *)slval = _btol(1); 01508 break; 01509 #endif 01510 case 8: 01511 *(_f_log8 *)slval = _btol(1); 01512 break; 01513 default: 01514 return(FEKNTSUP); /* kind not supported */ 01515 } 01516 01517 /* F and .f are assumed to be a logical value */ 01518 } else if ((c == 'F') || (c == 'f')) { 01519 switch (elsize) { 01520 #ifdef _F_REAL4 01521 case 4: 01522 *(_f_log4 *)slval = _btol(0); 01523 break; 01524 #endif 01525 case 8: 01526 *(_f_log8 *)slval = _btol(0); 01527 break; 01528 default: 01529 return(FEKNTSUP); /* kind not supported */ 01530 } 01531 } else { 01532 errn = FENLIVLG; /* Invalid logical */ 01533 return(errn); 01534 } 01535 } 01536 else { 01537 /* If the string does not start with a '.', it could 01538 * be a logical value or a variable name. Try to 01539 * determine which by seeing if it is followed by a 01540 * replacement character or '('. Save count and 01541 * pointer in case this isn't a value. 01542 */ 01543 ocnt = cup->ulinecnt; 01544 optr = cup->ulineptr; 01545 newc = *optr++; 01546 ocnt--; 01547 while (!(ISBLANK(newc))) { 01548 if (MATCH(newc, _MASKS, MRNLSEP) || 01549 MATCH(newc, _MASKS, MRNLDELIM) || 01550 (newc == '/')) 01551 break; /* Assume value */ 01552 if (MATCH(newc, _MASKS, MRNLREP) || 01553 (newc == '(')) { 01554 /* Reset, this MAY be the first 01555 * letter of a variable name 01556 */ 01557 cup->ulineptr--; 01558 cup->ulinecnt++; 01559 *nullvlu = 2; 01560 return(0); /* Null value */ 01561 } 01562 newc = *optr++; 01563 ocnt--; 01564 } 01565 while ((ISBLANK(newc)) && ocnt-- > 0) 01566 newc = *optr++; 01567 if (MATCH(newc, _MASKS, MRNLREP)) { 01568 /* 01569 * Reset, because this MAY have been 01570 * the first letter of a variable name 01571 */ 01572 cup->ulineptr--; 01573 cup->ulinecnt++; 01574 *nullvlu = 2; 01575 return(0); /* Null value */ 01576 } 01577 if ((c == 'T') || (c == 't')) { 01578 switch (elsize) { 01579 #ifdef _F_REAL4 01580 case 4: 01581 *(_f_log4 *)slval = _btol(1); 01582 break; 01583 #endif 01584 case 8: 01585 *(_f_log8 *)slval = _btol(1); 01586 break; 01587 default: 01588 return(FEKNTSUP); /* kind not supported */ 01589 } 01590 } 01591 else if ((c == 'F') || (c == 'f')) { 01592 switch (elsize) { 01593 #ifdef _F_REAL4 01594 case 4: 01595 *(_f_log4 *)slval = _btol(0); 01596 break; 01597 #endif 01598 case 8: 01599 *(_f_log8 *)slval = _btol(0); 01600 break; 01601 default: 01602 return(FEKNTSUP); /* kind not supported */ 01603 } 01604 } 01605 else if (MATCH(c, _MASKS, MRNLSEP) || 01606 ISBLANK(c) || (c == ',')) { 01607 *nullvlu = 1; 01608 return(0); /* Indicate null value */ 01609 } 01610 else { 01611 errn = FENLIVLG; /* Invalid logical */ 01612 return(errn); 01613 } 01614 } 01615 /* We assume we're reading a logical value. 01616 * Skip to the end of this value. 01617 */ 01618 while ( !(ISBLANK(c))) { 01619 CMTSUBGT(c); 01620 /* check for separator or terminating character */ 01621 if (MATCH(c, _MASKS, MRNLDELIM) || c == '/' || 01622 MATCH(c, _MASKS, MRNLSEP)) { 01623 /* Reset cnt and ptr for conversion routine */ 01624 cup->ulineptr--; 01625 cup->ulinecnt++; 01626 return(0); /* return logical value */ 01627 } 01628 } 01629 return(0); /* return logical value */ 01630 } /* End of type logical */ 01631 /* if type character, read character data */ 01632 if (type == DVTYPE_ASCII) 01633 return (_g_charstr(css, cup, ptr, cnt, c, echoptr, *lcount, 01634 elsize, nullvlu)); 01635 /* Get value for variable that is not type LOGICAL or CHARACTER */ 01636 if (isdigit((int) c) || c == '+' || c == '-' || c == '.') { 01637 if (type == DVTYPE_COMPLEX) { 01638 errn = FENLIVCX; 01639 return(errn); 01640 } 01641 return(_g_number(type, cup, lval, elsize)); 01642 } 01643 /* When we get here we are looking for a VALUE. We are at a 01644 * nonblank character which is not a digit, +, or -, separator, 01645 * comment or delimiter. 01646 * A left parenthesis indicates complex data 01647 * An apostrophe or quote indicates hollerith data 01648 * A letter o indicates octal data 01649 * A letter z indicates hexadecimal data 01650 */ 01651 if (c == '(') { 01652 return(_g_complx(css, cup, type, echoptr, lval, elsize)); 01653 } 01654 else if ((c == '\'') || (c == '"')) { 01655 return(_get_quoholl(css, cup, c, type, echoptr, lval, elsize)); 01656 } 01657 else if (c == 'O' || c == 'o') { 01658 return(_gocthex(css, cup, type, echoptr, lval, OCTAL, elsize, 01659 nullvlu)); 01660 } 01661 else if (c == 'Z' || c == 'z') { 01662 return(_gocthex(css, cup, type, echoptr, lval, HEX, elsize, 01663 nullvlu)); 01664 } 01665 else { 01666 /* No valid value. 01667 * Reset cup->ulineptr, because this MAY have been the first 01668 * character of a variable name. For example, if we have: 01669 * integer var1(3),var2, with input: var1=2, var2 = 5 01670 * then when we try to read the value for var1(2), we will 01671 * see 'var2' 01672 */ 01673 cup->ulineptr--; 01674 cup->ulinecnt++; 01675 *nullvlu = 2; 01676 return(0); /* Return null value */ 01677 } 01678 } 01679 01680 /* _g_complx - get the value for a complex number. 01681 * On entry: 01682 * positioned at '(' for a complex number. 01683 * Returns: 0 if OK, 01684 * -value if EOF 01685 * > 0 with valid error number if an error 01686 */ 01687 01688 static int 01689 _g_complx( 01690 FIOSPTR css, unit*cup, ftype_t type, struct Echoinfo *echoptr, 01691 long *lval, int elsize) 01692 { 01693 char c; 01694 long *oldp; 01695 long mode, stat; 01696 long zero = 0; 01697 long field_width; 01698 long *field_begin; 01699 long *field_end; 01700 int ss, i, errn; 01701 int nc; 01702 long *lptr; 01703 ic_func *ngcf; 01704 int inc; 01705 int ptrfw; 01706 bcont *slval; 01707 /* 01708 * IN reading the complex number, assume 01709 * intervening EOR is OK 01710 */ 01711 if (type != DVTYPE_COMPLEX) { 01712 errn = FENLIVCX; /* type not complex */ 01713 return(errn); 01714 } 01715 /* 01716 * Call the function from the ncf_tab77 table. 01717 */ 01718 01719 ngcf = ncf_tab77[type]; 01720 mode = 0; 01721 01722 switch (elsize) { 01723 #ifdef _F_REAL4 01724 case 8: 01725 mode = MODEHP; 01726 break; 01727 #endif 01728 case 16: 01729 break; 01730 case 32: 01731 mode = MODEDP; 01732 break; 01733 default: 01734 return(FEKNTSUP); /* kind not supported */ 01735 } 01736 inc = (elsize / 2) / (sizeof(bcont)); 01737 slval = (bcont*)lval; 01738 /* 01739 * If the user had turned off blanks as separator, tell 01740 * conversion to ignore them. Otherwise, blanks are significant. 01741 */ 01742 if (_BLNKSEP == 0) 01743 mode |= MODEBN; 01744 /* loop and get both real and imaginary */ 01745 for (i = 0; i < 2; i++) { 01746 do { 01747 SUBGTC(c); /* skip the '(' */ 01748 } while (ISBLANK(c)); /* skip blanks */ 01749 cup->ulinecnt++; /* backup 1 character */ 01750 cup->ulineptr--; /* backup 1 character */ 01751 field_begin = cup->ulineptr; 01752 field_end = cup->ulineptr; 01753 field_width = cup->ulinecnt; 01754 nc = 0; 01755 /* while not MRNLSEP (comma), 01756 * MRNLDELM (ampersand, dollarsign, or slash), 01757 * blank if a separator, or left parenthesis 01758 */ 01759 while (nc < cup->ulinecnt && !(*field_end == ')' || 01760 MATCH(*field_end, _MASKS, MRNLSEP) || 01761 MATCH(*field_end, _MASKS, MRNLDELIM) || 01762 (*field_end == '/') || 01763 (isspace(*field_end) && (_BLNKSEP != 0)) ) ) { 01764 field_end++; 01765 nc++; 01766 } 01767 /* pass field_end + 1 */ 01768 field_end++; 01769 field_width = nc; 01770 /* convert both the real and imaginary parts */ 01771 errn = ngcf(field_begin, &field_width, &field_end, 01772 &mode, slval + (i * inc), &stat, &zero, &zero); 01773 01774 /* If the scan failed, the input data might be 01775 * Hollerith or hex or octal. Allow _s_scan_extensions 01776 * _s_scan_extensions to rescan the input and 01777 * recompute the field width. 01778 */ 01779 if (errn < 0) { 01780 errn = _nicverr(stat); 01781 } else 01782 errn = 0; 01783 01784 /* if (errn == EX_ILLCHAR) */ 01785 if (errn == FENICVIC) { 01786 int errn2; 01787 int new_elsize; 01788 ftype_t new_type; 01789 new_type = DVTYPE_INTEGER; 01790 /* complex(kind=16) not allowed in cft77 */ 01791 if (elsize == 32) { 01792 return(errn); 01793 } 01794 new_elsize = elsize >> 1; 01795 /* store into float without conversion. */ 01796 errn2 = _s_scan_extensions((slval + (i * inc)), 01797 new_type, new_elsize, field_begin, 01798 field_width, &ptrfw, mode); 01799 01800 cup->ulineptr += ptrfw; 01801 cup->ulinecnt -= ptrfw; 01802 if (errn2 <= 0) 01803 errn = 0; 01804 else 01805 /* errors FELDUNKI and FELDSTRL 01806 * are currently returned. 01807 */ 01808 return(FENLIVCX); 01809 } else { 01810 cup->ulineptr = field_begin + field_width; 01811 cup->ulinecnt -= cup->ulineptr - field_begin; 01812 if (errn != 0) 01813 return(errn); 01814 } 01815 do { 01816 SUBGTC(c); 01817 } while (ISBLANK(c)); 01818 if ((c != ',') && (i == 0)) 01819 return(FENLIVCX); /* err in complex number format */ 01820 } 01821 if ( c != ')') 01822 return(FENLIVCX); /* err in complex number format */ 01823 return(0); 01824 } 01825 01826 /* 01827 * _g_number - Read a number. 01828 * Returns: 0 if ok 01829 * -value if EOF 01830 * > 0 if error 01831 */ 01832 01833 static int 01834 _g_number( 01835 ftype_t type, 01836 unit *cup, 01837 long *lval, 01838 int elsize) 01839 { 01840 long *oldp; 01841 long mode, stat; 01842 long zero = 0; 01843 long field_width; 01844 long *field_begin; 01845 long *field_end; 01846 long *s_field_end; 01847 int ss; 01848 int errn = 0; 01849 int nc; 01850 long *lptr; 01851 ic_func *ngcf; 01852 int ptrfw; 01853 bcont *slval; 01854 01855 mode = 0; 01856 01857 switch (type) { 01858 case DVTYPE_REAL: 01859 switch (elsize) { 01860 #ifdef _F_REAL4 01861 case 4: 01862 mode = MODEHP; 01863 break; 01864 #endif 01865 case 8: 01866 break; 01867 case 16: 01868 mode = MODEDP; 01869 break; 01870 default: 01871 return(FEKNTSUP); 01872 } 01873 break; 01874 case DVTYPE_INTEGER: 01875 switch (elsize) { 01876 #ifdef _F_INT4 01877 case 4: 01878 mode = MODEHP; 01879 break; 01880 #endif 01881 case 8: 01882 break; 01883 default: 01884 return(FEKNTSUP); 01885 } 01886 break; 01887 } 01888 /* 01889 * Call the function from the ncf_tab77 table. 01890 */ 01891 01892 ngcf = ncf_tab77[type]; 01893 01894 /* 01895 * If the user had turned off blanks as separator, tell NICONV 01896 * to ignore them. Otherwise, blanks are significant. 01897 */ 01898 if (_BLNKSEP == 0) 01899 mode |= MODEBN; 01900 cup->ulinecnt++; /* backup 1 character */ 01901 cup->ulineptr--; /* backup 1 character */ 01902 field_begin = cup->ulineptr; 01903 field_end = cup->ulineptr; 01904 field_width = cup->ulinecnt; 01905 slval = (bcont*)lval; 01906 nc = 0; 01907 /* while not MRNLSEP (comma) 01908 * MRNLDELM (ampersand, dollarsign, or slash) 01909 * or blank if a separator 01910 */ 01911 while (nc < cup->ulinecnt && 01912 !(MATCH(*field_end, _MASKS, MRNLSEP) || 01913 MATCH(*field_end, _MASKS, MRNLDELIM) || (*field_end == '/') || 01914 (isspace(*field_end) && (_BLNKSEP != 0)) ) ) { 01915 field_end++; 01916 nc++; 01917 } 01918 /* pass field_end + 1 */ 01919 field_end++; 01920 field_width = nc; 01921 s_field_end = field_end; 01922 errn = ngcf(field_begin, &field_width, &field_end, 01923 &mode, slval, &stat, &zero, &zero); 01924 01925 /* If the scan failed, the input data might be 01926 * Hollerith or hex or octal. Allow _s_scan_extensions 01927 * _s_scan_extensions to rescan the input and 01928 * recompute the field width. 01929 */ 01930 if (errn < 0) { 01931 errn = _nicverr(stat); 01932 } else 01933 errn = 0; 01934 01935 /* if (errn == EX_ILLCHAR) */ 01936 if (errn == FENICVIC) { 01937 int errn2; 01938 switch (type) { 01939 case DVTYPE_REAL: 01940 { 01941 long cmode; 01942 int new_elsize; 01943 int new_inc = 0; 01944 ftype_t new_type; 01945 new_type = DVTYPE_INTEGER; 01946 cmode = mode; 01947 new_elsize = elsize; 01948 if (elsize == 16) { 01949 new_elsize = 8; 01950 cmode = 0; 01951 new_inc = new_elsize / (sizeof(bcont)); 01952 } 01953 /* store into float without conversion. */ 01954 errn2 = _s_scan_extensions((slval + new_inc), 01955 new_type, new_elsize, field_begin, 01956 field_width, &ptrfw, cmode); 01957 01958 /* store zero in first part of real 16 */ 01959 if ((elsize == 16) && (errn2 == 0)) 01960 *(_f_int8 *)slval = 0; 01961 if (errn2 >= 0) 01962 errn = 0; 01963 else 01964 errn = FENLUNKI; 01965 break; 01966 } 01967 case DVTYPE_INTEGER: 01968 errn2 = _s_scan_extensions(slval, type, elsize, 01969 field_begin, field_width, &ptrfw, mode); 01970 01971 /* errors FELDUNKI and FELDSTRL are 01972 * currently returned. 01973 */ 01974 if (errn2 >= 0) { 01975 errn = 0; 01976 } else if (errn == FENICVIC) { 01977 errn2 = 0; 01978 ngcf = ncf_tab77[DVTYPE_REAL]; 01979 field_end = s_field_end; 01980 errn2 = ngcf(field_begin, &field_width, 01981 &field_end, &mode, slval, &stat, 01982 &zero, &zero); 01983 if (errn2 < 0) 01984 errn = FENLUNKI; 01985 else { 01986 errn = 0; 01987 switch (errn2) { 01988 #ifdef _F_REAL4 01989 case EX_REAL32: 01990 { 01991 _f_real4 val4; 01992 union { 01993 _f_int4 n; 01994 _f_real4 f; 01995 } uval32; 01996 if (!_TYP_CONV) { 01997 errn = FENLIVIT; 01998 break; 01999 } 02000 uval32.n = *(_f_int4 *)slval; 02001 val4 = uval32.f; 02002 *(_f_int4 *)slval = (_f_int4) val4; 02003 break; 02004 } 02005 #endif 02006 case EX_REAL64: 02007 { 02008 _f_real8 val8; 02009 union { 02010 _f_int8 n; 02011 _f_real8 f; 02012 } uval64; 02013 if (!_TYP_CONV) { 02014 errn = FENLIVIT; 02015 break; 02016 } 02017 uval64.n = *(_f_int8 *)slval; 02018 val8 = uval64.f; 02019 *(_f_int8 *)slval = 02020 (_f_int8) val8; 02021 break; 02022 } 02023 #if _F_REAL16 == 1 02024 case EX_REAL128: 02025 { 02026 _f_real16 val16; 02027 _f_int8 *int8ptr; 02028 union { 02029 _f_int8 n[2]; 02030 _f_real16 f; 02031 } uval128; 02032 if (!_TYP_CONV) { 02033 errn = FENLIVIT; 02034 break; 02035 } 02036 int8ptr = (_f_int8 *)slval; 02037 uval128.n[0] = int8ptr[0]; 02038 uval128.n[1] = int8ptr[1]; 02039 val16 = uval128.f; 02040 *(_f_int8 *)slval = (_f_int8) val16; 02041 break; 02042 } 02043 #endif 02044 default: 02045 errn = FENLUNKI; 02046 } 02047 } 02048 02049 } else 02050 errn = FENLUNKI; 02051 break; 02052 } 02053 } 02054 cup->ulineptr = field_begin + field_width; 02055 cup->ulinecnt -= cup->ulineptr - field_begin; 02056 return(errn); 02057 } 02058 02059 /* _g_charstr - read a character string 02060 * 02061 * Input: cup_ulineptr will point one past the first character of the string. 02062 * "c" will contain the first character of the string. 02063 * Returns: 0 if ok, 02064 * -value if EOF 02065 * > 0 if error 02066 */ 02067 02068 static int 02069 _g_charstr( 02070 FIOSPTR css, 02071 unit *cup, 02072 void *p, /* Address of variable being read */ 02073 int cnt, /* Number of strings we expect to read */ 02074 char c, /* First character of string. */ 02075 struct Echoinfo *echoptr, 02076 int lcount, /* Repeat count */ 02077 int elsize, 02078 int *nullvlu) 02079 { 02080 int eos; /* eos == -1 if end or beginning of string */ 02081 int i, ch; 02082 unsigned int len77; 02083 char *cp; 02084 long stat; 02085 char enddelim; 02086 char c1; 02087 int repcount; 02088 char *cpold; 02089 int ss; 02090 int errn = 0; 02091 long *optr; 02092 int ocnt; 02093 void *fchp; 02094 *nullvlu = 0; 02095 /* 02096 * Character data may be enclosed in apostrophes or quotation marks. 02097 * Each apostrophe within a character constant delimited by 02098 * apostrophes must be represented by 2 consecutive apostrophes 02099 * without an intervening blank or end of record. The same holds 02100 * true for quotation marks. Character constants may be continued 02101 * from the end of one record to the beginning of the next record. 02102 * The end of the record does not cause a blank or any other 02103 * character to become part of the constant. 02104 * Blank characters, separator characters, comment characters, and 02105 * delimiter characters may appear in character constants. 02106 * 02107 * For cf77 only (F90 does not allow undelimited character on input): 02108 * If the character constant has the following properties: 02109 * 1. It does not contain blank characters, 02110 * separator characters, comment characters, left parenthesis 02111 * or delimiter characters. 02112 * 2. It does not cross a record boundary, 02113 * 3. the first nonblank character is not a quotation mark or 02114 * apostrophe, 02115 * 4. the leading characters are not numeric followed by asterisk, 02116 * 5. the leading characters are not numeric followed by R, H, or L 02117 * then the enclosing apostrophes or quotation marks are not required 02118 * and apostrophes or quotation marks within the character constant 02119 * are not to be doubled. 02120 * 02121 * Let len be the length of the list item, and let w be the length 02122 * of the character constant. If len is less than or equal to w, 02123 * the leftmost len characters of the constant are transmitted to the 02124 * variable. If len is greater than w, the constant is transmitted to 02125 * the leftmost w characters of the variable and the remaining len-w 02126 * characters of the list item are filled with blanks. 02127 * 02128 * f90 allows zero-length character and it uses one input data item 02129 * from the input record. It does not store the value to the 02130 * the zero-sized character entity. cf77 does not allow this feature. 02131 */ 02132 eos = 0; 02133 fchp = p; 02134 len77 = elsize; /* Get character length */ 02135 /* cf77 does not allow zero-length character entities */ 02136 if (len77 != 0) { 02137 cp = fchp; 02138 repcount = MIN(lcount,cnt); 02139 /* 02140 * If the first character is a quote or apostrophe, we expect 02141 * that character to delimit the end of the string. 02142 */ 02143 if ((c == '\'') || (c == '"')) { 02144 enddelim = c; 02145 /* find characters in string */ 02146 for (i = 0; i < len77 && eos == 0; i++) { 02147 GETSTR77(); 02148 if (eos == 0) 02149 *cp++ = ch; 02150 } 02151 if (eos == -1) 02152 i--; 02153 i = len77 - i; /* If declared len > read len */ 02154 if ( i > 0 ) 02155 (void) memset(cp, BLANK, i); /* blank fill */ 02156 cp = cp + i; 02157 while (eos != -1) { 02158 /* 02159 * We didn't hit the end of the string yet. 02160 * Search for it. 02161 */ 02162 GETSTR77(); 02163 } 02164 while (--repcount) { 02165 /* We have a repeat count. 02166 * cp will point to the next element. 02167 * Copy len77 characters to the next 02168 * element. 02169 */ 02170 cpold = fchp; 02171 (void) memcpy(cp, cpold, len77); 02172 cp = cp + len77; /* Next element */ 02173 } 02174 } 02175 else { 02176 /* 02177 * We have a character string that's not surrounded 02178 * by quotes (or apostrophes). Read until we see a 02179 * blank, separator, comment, or EOR (which looks 02180 * like a blank to us). Store as many of them as 02181 * we have room for. We cannot have a repeat count 02182 * unless we're surrounded by quotes or apostrophes. 02183 */ 02184 if (lcount > 1) { 02185 return(FENLNOVL); /* invalid char data */ 02186 } 02187 /* 02188 * Determine if this is a value or a variable name. 02189 * Save count and pointer in case this isn't a value. 02190 */ 02191 ocnt = cup->ulinecnt; 02192 optr = cup->ulineptr; 02193 c1 = *optr++; 02194 ocnt--; 02195 02196 while (!(ISBLANK(c1))) { 02197 /* check for separator or 02198 * terminating character 02199 */ 02200 if (MATCH(c1, _MASKS, MRNLSEP) || 02201 MATCH(c1, _MASKS, MRNLDELIM)) 02202 break; /* Assume value */ 02203 if (MATCH(c1, _MASKS, MRNLREP) || 02204 c1 == '(') { 02205 /* Reset, this MAY be the first 02206 * letter of a variable name. 02207 */ 02208 cup->ulineptr--; 02209 cup->ulinecnt++; 02210 *nullvlu = 2; 02211 return(0); /* Null value */ 02212 } 02213 c1 = *optr++; 02214 ocnt--; 02215 } 02216 while ((ISBLANK(c1)) && ocnt-- > 0) 02217 c1 = *optr++; 02218 if (MATCH(c1, _MASKS, MRNLREP) || c1 == '(') { 02219 /* 02220 * Reset, this MAY be the first letter 02221 * of a variable name. 02222 */ 02223 cup->ulineptr--; 02224 cup->ulinecnt++; 02225 *nullvlu = 2; 02226 return(0); /* Null value */ 02227 } 02228 i = 0; 02229 c1 = c; 02230 while (!(ISBLANK(c1))) { 02231 if (i < len77) { 02232 *cp++ = c1; 02233 i++; 02234 } 02235 SUBGTC(c1); 02236 if (MATCH(c1, _MASKS, MRNLSEP) || 02237 MATCH(c1, _MASKS, MRNLCOMM)) { 02238 /* reset to handle next time */ 02239 cup->ulineptr--; 02240 cup->ulinecnt++; 02241 break; 02242 } 02243 } 02244 /* If declared length > amount read, blank fill */ 02245 i = len77 - i; 02246 (void) memset(cp, BLANK, i); 02247 cp = cp + i; 02248 } 02249 } 02250 else { 02251 /* cf77 does not have zero-length character entities */ 02252 return(FENLIOER); 02253 } 02254 return(errn); 02255 } 02256 02257 /* _get_holl - Read a hollerith string. 02258 * 02259 * Returns: 0 if a value was found, 02260 * -value if EOF 02261 * > 0 if an error occurred 02262 */ 02263 02264 static int 02265 _get_holl( 02266 FIOSPTR css, 02267 unit *cup, 02268 char holltype, 02269 int count, /* Number of characters in string */ 02270 ftype_t type, /* Type of data item */ 02271 struct Echoinfo *echoptr, 02272 long *lval, 02273 int elsize) 02274 { 02275 int i; 02276 char *holbufptr; 02277 char c; 02278 long stat; 02279 int ss; 02280 int errn = 0; 02281 int fill; 02282 /* 02283 * Read 'count' characters from the current word, packing them 02284 * left justified into lval[0]. 02285 * 02286 * Can't have hollerith input for DOUBLE, COMPLEX or CHARACTER data. 02287 * Hollerith input is supported for compatibility with 02288 * old versions of namelist. 02289 * 02290 * Because we don't allow CHARACTER data, we can make the 02291 * simplifying assumption that we start on a word boundary. 02292 * Also, we are going to assume that whatever we read in will 02293 * need to fit in a word the size of a default integer. Repeat 02294 * counts are allowed. If it becomes necessary to allow hollerith 02295 * strings of > the sizeof the number of characters in a default 02296 * integer, some thought will need to be given as to how to 02297 * handle repeat counts. 02298 */ 02299 if (type == DVTYPE_COMPLEX || type == DVTYPE_ASCII || 02300 ((type == DVTYPE_REAL) && elsize == sizeof(_f_real16))) { 02301 return(FENLUNKI); 02302 } 02303 if (count > elsize) { 02304 return(FENLIOER); 02305 } 02306 fill = BLANK; 02307 holbufptr = (char *)lval; 02308 if (holltype == 'R' || holltype == 'r') { 02309 /* right justified */ 02310 fill = NULLC; 02311 holbufptr = holbufptr + (elsize - count); 02312 } 02313 else 02314 if (holltype == 'L' || holltype == 'l') 02315 fill = NULLC; 02316 /* Last character in buffer is the EOR character, 02317 * that's why we check for cup->ulinecnt > 1 02318 */ 02319 for (i = 0; i < count && (cup->ulinecnt > 1) ; i++) { 02320 SUBGTC(c); /* comment characters are not special 02321 * within hollerith string */ 02322 *holbufptr++ = c; 02323 } 02324 if (i == count) { 02325 /* Do we need to fill the last word? */ 02326 if (holltype == 'R' || holltype == 'r') /* right justified? */ 02327 holbufptr = (char *)lval; 02328 (void) memset(holbufptr, fill, elsize - count); 02329 } 02330 else { 02331 /* 02332 * We hit EOR before we read enough characters _or_ we had 02333 * too many characters. 02334 */ 02335 return(FENLIOER); 02336 } 02337 return(errn); 02338 } 02339 02340 /* _get_quoholl 02341 * Get a hollerith string that is surrounded by quotes or apostrophes 02342 * Legal syntax is '----'L, '----'R, or '----'H 02343 * 02344 * Returns: 0 if a value was found, 02345 * -value if EOF 02346 * > 0 if an error occurred 02347 */ 02348 02349 static int 02350 _get_quoholl( 02351 FIOSPTR css, 02352 unit *cup, 02353 char cdelim, /* Quote or apostrophe (to end hollerith) */ 02354 ftype_t type, /* Type of data */ 02355 struct Echoinfo *echoptr, 02356 long *lval, /* Value is placed here */ 02357 int elsize) /* size */ 02358 { 02359 int numchar; /* character counter */ 02360 int j; 02361 int fill; /* Fill character is either ' ' or '\0' */ 02362 long holbuf; /* Data is stored here until we know whether 02363 it is right or left justified. */ 02364 char *holbufptr; /* pointer into holbuf */ 02365 char c; /* Character read */ 02366 long stat; 02367 char *lvalcharptr; /* Pointer to value */ 02368 int ss; 02369 int errn = 0; 02370 /* 02371 * Can't have hollerith input for DOUBLE, COMPLEX or CHARACTER data. 02372 * Hollerith input is supported for compatibility with 02373 * old versions of namelist. 02374 * 02375 * Because we don't allow CHARACTER data, we can make the 02376 * simplifying assumption that we start on a word boundary. 02377 * Also, we are going to assume that whatever we read in will 02378 * need to fit in one word. Repeat counts are allowed. If it 02379 * becomes necessary to allow hollerith strings of greater than 02380 * the number of characters in a default integer, some thought 02381 * will need to be given as to how to handle repeat counts. 02382 */ 02383 if (type == DVTYPE_COMPLEX || type == DVTYPE_ASCII || 02384 (type == DVTYPE_REAL && elsize == sizeof(_f_real16))) { 02385 return(FENLUNKI); 02386 } 02387 lvalcharptr = (char *)lval; 02388 holbufptr = (char *) &holbuf; 02389 /* Do not allow quoted strings to be continued on another record. */ 02390 numchar = 0; 02391 for (;;) { 02392 SUBGTC(c); 02393 if (c == cdelim) { 02394 /* Allow Comment characters within quoted string */ 02395 SUBGTC(c); 02396 if (c != cdelim) 02397 break; /* That was the end of the quoted 02398 * string. Otherwise, we saw two 02399 * quotes in a row, which means 02400 * we store one. 02401 */ 02402 } 02403 if (++numchar > elsize) { 02404 return(FENLIOER); 02405 } 02406 *holbufptr++ = c; /* Save the character */ 02407 /* 02408 * Last character in the input buffer is the EOR character, 02409 * that's why we check for cup->ulinecnt <= 1 02410 */ 02411 if (cup->ulinecnt <= 1) { 02412 return(FENLIOER); 02413 } 02414 } /* On exit from this loop, numchar = number of chars. stored */ 02415 if (c == 'L' || c == 'l') 02416 fill = NULLC; 02417 else if (c == 'R' || c == 'r') { 02418 /* Right justify and store the value just read */ 02419 holbufptr = holbufptr - 1; /* Last character */ 02420 lvalcharptr = lvalcharptr + (elsize - 1); 02421 j = elsize - numchar; 02422 while (numchar-- > 0) 02423 *lvalcharptr-- = *holbufptr--; 02424 02425 /* Fill word with 0's if necessary */ 02426 while (j-- > 0) 02427 *lvalcharptr-- = '\0'; 02428 return(0); 02429 } 02430 else { 02431 /* H format */ 02432 fill = BLANK; 02433 if (c != 'H' && c != 'h') { 02434 /* Reset pointers since the character does */ 02435 /* not belong to this value */ 02436 cup->ulineptr--; 02437 cup->ulinecnt++; 02438 } 02439 } 02440 /* Do we need to fill the last word? */ 02441 (void) memset(holbufptr, fill, elsize - numchar); 02442 *lval = holbuf; 02443 return(errn); 02444 } 02445 02446 /* _gocthex - provides octal or hex editing for compatibility with old 02447 * versions of namelist. 02448 * Legal formats: O'123 or O'123'. Octal number may not contain blanks, 02449 * and this is a difference with the old version of namelist. 02450 * Legal formats: Z'1a3 or Z'1a3'. 02451 * 02452 * On input: 02453 * cup_ulineptr should point to the character immediately following the O 02454 * Returns: 0 if a value was found, 02455 * -value if EOF 02456 * > 0 if an error occurred 02457 * nullvlu = 1 if a null value was found 02458 * 2 if a null value was found, and it is not followed 02459 * by another value 02460 */ 02461 02462 static int 02463 _gocthex( 02464 FIOSPTR css, 02465 unit *cup, 02466 ftype_t type, 02467 struct Echoinfo *echoptr, 02468 long *lval, 02469 int base, 02470 int elsize, 02471 int *nullvlu) 02472 { 02473 char c; 02474 long stat; 02475 char strbuf[2]; 02476 int ss; 02477 int errn = 0; 02478 int octshift = OCTSHFT; 02479 int hexshift = HEXSHFT; 02480 /* check size in bytes of incoming variable. */ 02481 #if defined(_F_REAL4) && defined(_F_INT4) 02482 if (elsize <= 4) { 02483 octshift = OCTSHFT4; 02484 hexshift = HEXSHFT4; 02485 } 02486 #endif 02487 *nullvlu = 0; 02488 if (*cup->ulineptr != '\'') { 02489 /* Can't be a value, might be a variable name */ 02490 cup->ulineptr--; 02491 cup->ulinecnt++; 02492 *nullvlu = 2; 02493 return(0); /* NULL value */ 02494 } 02495 /* This type of format won't work for complex or double precision */ 02496 if (type == DVTYPE_COMPLEX || (type == DVTYPE_REAL && 02497 elsize == sizeof(_f_real16))) { 02498 return(FENLUNKI); /* type mismatch */ 02499 } 02500 SUBGTC(c); /* Skip the apostrophe */ 02501 SUBGTC(c); /* and get the next character */ 02502 *lval = 0; 02503 strbuf[1] = '\0'; 02504 while (!(ISBLANK(c)) && c != '\'') { 02505 if (base == OCTAL) { 02506 if ((!isdigit((int) c)) || (c == '9') || 02507 (*lval >> octshift)) { 02508 return(FENICVIC); /* NICV type err */ 02509 } 02510 *lval = (*lval * (sizeof(_f_int))) + c - '0'; 02511 } 02512 else { /* Check for hex digit or overflow */ 02513 if ((!isxdigit(c)) || (*lval >> hexshift)) { 02514 return(FENICVIC); /* NICV type err */ 02515 } 02516 strbuf[0] = c; 02517 *lval = (*lval * 16) + 02518 (int) strtol(strbuf, (char **)NULL, 16); 02519 } 02520 CMTSUBGT(c); /* Check for comment after value */ 02521 if (MATCH(c, _MASKS, MRNLSEP)) { 02522 cup->ulineptr--; 02523 cup->ulinecnt++; /* to read separator after */ 02524 break; /* return from this routine */ 02525 } 02526 } 02527 return(errn); /* indicate value */ 02528 }