Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
rnl90to77.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001, Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2.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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines