Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
cifopen.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 static char USMID[] = "@(#) libcif/cifopen.c    30.6    05/22/97 11:49:31";
00038 
00039 
00040 /*
00041  * Cif_Open opens a compiler input input file, either the original ASCII
00042  * format or the compressed binary format.  For input files if the "rtypes"
00043  * argument is not NULL, it represents a zero terminated array of record type
00044  * values.  Only records of the types selected will be returned by cifgetrec.
00045  * If "rtypes" is NULL, all record types will be returned.
00046  *
00047  * tabs are set to be read with tab spacing = 3
00048  */
00049 
00050 #define CIF_VERSION 3
00051 
00052 #ifdef _ABSOFT
00053 #include "cif.h"
00054 #else
00055 #include <cif.h>
00056 #endif
00057 
00058 #include <stdlib.h>
00059 #include <stdio.h>    /* for fileno() */
00060 #include <string.h>   /* for strdup() */
00061 #include <sys/types.h>
00062 #include <sys/stat.h>
00063 
00064 #define DEFGLOBAL
00065 #include "cif_int.h"
00066 
00067 /* fileno() and strdup() are in the Unix standard but not C */
00068 #if !(defined(__sgi) || defined(__sun) || defined(__alpha))
00069   extern int fileno(FILE *stream);
00070   /* On other systems this is a macro */
00071 #endif
00072 extern char *strdup(const char *s);
00073 
00074 
00075 #define HDRBUF_SIZE     128     /* size of buffer used to read the file header */
00076 #define HDRTOKENS               10              /* number of tokens in header before tools field */
00077 
00078 
00079 
00080 /* The cif version number == value of CIF_VERSION
00081  * picked up by Cif_Open function through the use of
00082  * alternative entries to it depending on the value of
00083  * CIF_VERSION. Used in cifdup.c to allow Cif_Duplicate
00084  * to know what version cif to create and copy, and in
00085  * ciffree.c for Cif_Free to know what storage to free.
00086  */
00087 
00088 int _cif_version = 0;
00089 
00090 
00091 #undef Cif_Open  /* ensure that we don't try to map this to Cif_Open_Vx */
00092 
00093 
00094 /* Special case of cif_open for applications compiled with CIF_VERSION == 1,
00095    which is the default. A check is made that they are not trying to open
00096    a cif with a version greater than (ie, > 1) the library that they
00097    were compiled with. Probably just catches applications that want to read
00098    a version 2 cif, but haven't set CIF_VERSION 2 before including cif.h */
00099 
00100 int Cif_Open_V1
00101 #ifdef __STDC__
00102 (char *filename, char *optype, int *rtypes, int version)
00103 #else
00104 (filename, optype, rtypes, version)
00105 char *filename;                 /* file name */
00106 char *optype;                           /* open type */
00107 int *rtypes;                            /* ptr to array of selected record types */
00108 int version;                            /* CIF version expected by tools */
00109 #endif
00110 {
00111 
00112   /* We can only enter this function if CIF_VERSION used by the application
00113      is set to 1, so if the same application is trying to read a cif version > 1,
00114      the data structures wont match, so better to issue the error now than later */
00115 
00116   if (version > 1)
00117     return (CIF_EXP_VERS);
00118 
00119   _cif_version = 1;  /* record the CIF_VERSION in use */
00120 
00121   /* call the real cif open */
00122 
00123   return( Cif_Open(filename, optype, rtypes, version) );
00124 
00125 }
00126 
00127 /* Special case of cif_open for applications compiled with CIF_VERSION == 2.
00128    A check is made that they are not trying to open
00129    a cif with a version less than (ie, < 2) the library that they
00130    were compiled with. If they compile with version 2, they have to read version 2 */
00131 
00132 int Cif_Open_V2
00133 #ifdef __STDC__
00134 (char *filename, char *optype, int *rtypes, int version)
00135 #else
00136 (filename, optype, rtypes, version)
00137 char *filename;                 /* file name */
00138 char *optype;                           /* open type */
00139 int *rtypes;                            /* ptr to array of selected record types */
00140 int version;                            /* CIF version expected by tools */
00141 #endif
00142 {
00143 
00144   /* We can only enter this function if CIF_VERSION used by the application
00145      is set to 2, so if the same application is trying to read a cif version < 2,
00146      the data structures wont match, so better to issue the error now than later */
00147 
00148   if (version < 2)
00149     return (CIF_EXP_VERS2);
00150 
00151   _cif_version = 2;  /* record the CIF_VERSION in use */
00152 
00153   /* call the real cif open */
00154 
00155   return( Cif_Open(filename, optype, rtypes, version) );
00156 
00157 }
00158 
00159 
00160 /*
00161  * As above + added a check to see of the cif.h in use matches what this
00162  * library was compiled with...looks at CIF_SUB_VERSION_2 which must match
00163  * the sub_version passed. See cif_open macros in cif.h for more details.
00164  */
00165 
00166 int Cif_Open_V2_1
00167 #ifdef __STDC__
00168 (char *filename, char *optype, int *rtypes, int version, int sub_version)
00169 #else
00170 (filename, optype, rtypes, version, sub_version)
00171 char *filename;                 /* file name */
00172 char *optype;                           /* open type */
00173 int *rtypes;                            /* ptr to array of selected record types */
00174 int version;                            /* CIF version expected by tools */
00175 int sub_version;
00176 #endif
00177 {
00178 
00179   /* We can only enter this function if CIF_VERSION used by the application
00180      is set to 2, so if the same application is trying to read a cif version < 2,
00181      the data structures wont match, so better to issue the error now than later */
00182 
00183   if (version < 2)
00184     return (CIF_EXP_VERS2);
00185 
00186   if (sub_version != CIF_SUB_VERSION_2)
00187       return(CIF_SUBVER);
00188 
00189   _cif_version = 2;  /* record the CIF_VERSION in use */
00190 
00191   /* call the real cif open */
00192 
00193   return( Cif_Open(filename, optype, rtypes, version) );
00194 
00195 }
00196 /*
00197  * As above for version 3
00198  */
00199 
00200 int Cif_Open_V3_1
00201 #ifdef __STDC__
00202 (char *filename, char *optype, int *rtypes, int version, int sub_version)
00203 #else
00204 (filename, optype, rtypes, version, sub_version)
00205 char *filename;                 /* file name */
00206 char *optype;                           /* open type */
00207 int *rtypes;                            /* ptr to array of selected record types */
00208 int version;                            /* CIF version expected by tools */
00209 int sub_version;
00210 #endif
00211 {
00212 
00213   /* We can only enter this function if CIF_VERSION used by the application
00214      is set to 3, so if the same application is trying to read a cif
00215      version < 3, the data structures wont match, so better to issue the
00216      error now than later */
00217 
00218   if (version < 3)
00219     return (CIF_EXP_VERS2);
00220 
00221   if (sub_version != CIF_SUB_VERSION_3)
00222       return(CIF_SUBVER);
00223 
00224   _cif_version = 3;  /* record the CIF_VERSION in use */
00225 
00226   /* call the real cif open */
00227 
00228   return( Cif_Open(filename, optype, rtypes, version) );
00229 
00230 }
00231 
00232 
00233 /*
00234  * Cif_Open can only be called directly by a v1 application which
00235  * has been re-linked, but not recompiled. If it had been re-compiled.
00236  * either Cif_Open_V1, or Cif_Open_V2 would be used. If called directly,
00237  * _cif_version will still be 0, so set it to 1 (you can't get v2 records
00238  * without recompiling) and validate against the cif_open version request
00239  */
00240 
00241 int Cif_Open
00242 #ifdef __STDC__
00243 (char *filename, char *optype, int *rtypes, int version)
00244 #else
00245 (filename, optype, rtypes, version)
00246 char *filename;                 /* file name */
00247 char *optype;                           /* open type */
00248 int *rtypes;                            /* ptr to array of selected record types */
00249 int version;                            /* CIF version expected by tools */
00250 #endif
00251 {
00252         int i;
00253         int cx;                                 /* _Cif_filetbl index */
00254         int *rt;                                        /* pointer to record type selectors */
00255         FILE *fd;                               /* file descriptor for file to open */
00256         char hdrbuf[HDRBUF_SIZE];       /* buffer to contain header record */
00257         struct stat statbuf;    /* file status structure */
00258 
00259         static char ascii_hdrkey[6] = { '2',SEPARATOR,'c','i','f',SEPARATOR };
00260         static char binary_hdrkey[6] = { SEPARATOR,'c','i','f','b',SEPARATOR };
00261         static char binary_version = _CIF_INT_VERSION;
00262 
00263         int rtype;
00264         struct Cif_generic *rptr;
00265 
00266         if (_cif_version == 0) {
00267 
00268           /*
00269            * Cif_open must have been called directly by a version 1 application
00270            * (see comment above). Validate the requested version.
00271            */
00272 
00273           if (version > 1)
00274             return (CIF_EXP_VERS);
00275 
00276           _cif_version = 1;  /* record the CIF_VERSION in use */
00277 
00278         }
00279 
00280 
00281 
00282         /* search for open slot in CIF file table */
00283 
00284         if (version > _CIF_INT_VERSION)
00285                 return (CIF_EXP_VERS);
00286         for (cx=0; cx < CIF_FT_SIZE; cx++)
00287                 if (_Cif_filetbl[cx].form == NOT_A_CIF) break;
00288         if (cx >= CIF_FT_SIZE)
00289                 return (CIF_MAXOPENS);
00290         _Cif_filetbl[cx].ifull = NO;
00291         _Cif_filetbl[cx].seek = NO;
00292         _Cif_filetbl[cx].version = 0;
00293         _Cif_filetbl[cx].return_version = 0;
00294         _Cif_filetbl[cx].ip = NULL;
00295         _Cif_filetbl[cx].mode = CIF_MEM_DEFAULT;
00296 
00297         /* open the file */
00298 
00299         if (strcmp (optype, "r") == 0 || strcmp (optype, "w") == 0)
00300                 _Cif_filetbl[cx].optype = *optype;
00301         else
00302                 return (CIF_BADREQ);
00303         if (strcmp(filename, "-") == 0) {
00304                 if (*optype == 'r')
00305                         fd = stdin;
00306                 else
00307                         fd = stdout;
00308         }
00309         else if ((fd = fopen(filename, optype)) == NULL)
00310                 return (CIF_SYSERR);
00311 
00312 
00313         /* if input file, allocate buffer and verify file format then process
00314          * the record selection mask */
00315 
00316         if (*optype == 'r') {
00317 
00318                 if (fread (hdrbuf, sizeof(char), 6, fd) != 6) {
00319                         (void) fclose (fd);
00320                         return (CIF_NOTCIF);
00321                 }
00322 
00323                 else if (strncmp (hdrbuf, ascii_hdrkey, 6) == 0) {
00324 
00325                         /* ASCII file, set file format and reset file position to beginning */
00326 
00327                         _Cif_filetbl[cx].form = ASCII_CIF;
00328                         if ((_Cif_filetbl[cx].ip = malloc (CIF_BUFSIZE)) == NULL)
00329                                 return (CIF_NOMEM);
00330                         (void) strncpy (_Cif_filetbl[cx].ip, hdrbuf, 6);
00331                         if (fgets (_Cif_filetbl[cx].ip+6, CIF_BUFSIZE-6, fd) == NULL) 
00332                                 IO_ERROR;
00333                         i = atoi(_Cif_filetbl[cx].ip+7);
00334                         if (i > _CIF_INT_VERSION)
00335                                 return (CIF_FILE_VERS);
00336 
00337                         _Cif_filetbl[cx].version = i;                   /* version of cif on disk */
00338                         _Cif_filetbl[cx].return_version = version;      /* version that the user wants */
00339 
00340                         _Cif_filetbl[cx].ifull = YES;
00341                 }
00342 
00343                 else if (strncmp (hdrbuf, binary_hdrkey, 6) == 0) {
00344 
00345                         /* Binary file, set file format.  Read CIF version and validate. */
00346 
00347                         _Cif_filetbl[cx].form = BINARY_CIF;
00348                         if (fread (hdrbuf, sizeof(char), 1, fd) != 1)
00349                                 IO_ERROR;
00350                         if (hdrbuf[0] > _CIF_INT_VERSION)
00351                                 return (CIF_FILE_VERS);
00352 
00353                         _Cif_filetbl[cx].version = hdrbuf[0];           /* version of cif on disk */
00354                         _Cif_filetbl[cx].return_version = version;      /* version that the user wants */
00355 
00356                 }
00357 
00358                 else
00359                         return (CIF_NOTCIF);
00360 
00361                 if (rtypes == NULL)
00362                         for (i = 0; i < CIF_MAXRECORD; i++) _Cif_filetbl[cx].rmask[i] = '\1';
00363                 else {
00364                         for (i = 0; i < CIF_MAXRECORD; i++) _Cif_filetbl[cx].rmask[i] = '\0';
00365                         for (rt = rtypes; *rt != 0; rt++)
00366                                 _Cif_filetbl[cx].rmask[*rt] = '\1';
00367                 }
00368 
00369                 /* Take out records that the requested cif version doesn't know about */
00370 
00371                 if (version == 1) {
00372                   _Cif_filetbl[cx].rmask[CIF_C_LINT_DIRECTIVE] = '\0';
00373                   _Cif_filetbl[cx].rmask[CIF_C_MACRO_DEF] = '\0';
00374                   _Cif_filetbl[cx].rmask[CIF_C_MACRO_UNDEF] = '\0';
00375                   _Cif_filetbl[cx].rmask[CIF_C_MACRO_USAGE] = '\0';
00376                   _Cif_filetbl[cx].rmask[CIF_C_ENTRY_END] = '\0';
00377 
00378                   _Cif_filetbl[cx].rmask[CIF_CDIR] = '\0';
00379                   _Cif_filetbl[cx].rmask[CIF_CDIR_DOSHARED] = '\0';
00380                   _Cif_filetbl[cx].rmask[CIF_GEOMETRY] = '\0';
00381                   _Cif_filetbl[cx].rmask[CIF_CONTINUATION] = '\0';
00382                   _Cif_filetbl[cx].rmask[CIF_TRANSFORM] = '\0';
00383 
00384                   _Cif_filetbl[cx].rmask[CIF_F90_CALLSITE] = '\0';
00385                   _Cif_filetbl[cx].rmask[CIF_F90_COMBLK] = '\0';
00386                   _Cif_filetbl[cx].rmask[CIF_F90_CONST] = '\0';
00387                   _Cif_filetbl[cx].rmask[CIF_F90_ENTRY] = '\0';
00388                   _Cif_filetbl[cx].rmask[CIF_F90_LOOP] = '\0';
00389                   _Cif_filetbl[cx].rmask[CIF_F90_DERIVED_TYPE] = '\0';
00390                   _Cif_filetbl[cx].rmask[CIF_F90_LABEL] = '\0';
00391                   _Cif_filetbl[cx].rmask[CIF_F90_NAMELIST] = '\0';
00392                   _Cif_filetbl[cx].rmask[CIF_F90_OBJECT] = '\0';
00393                   _Cif_filetbl[cx].rmask[CIF_F90_MISC_OPTS] = '\0';
00394                   _Cif_filetbl[cx].rmask[CIF_F90_OPT_OPTS] = '\0';
00395                   _Cif_filetbl[cx].rmask[CIF_F90_BEGIN_SCOPE] = '\0';
00396                   _Cif_filetbl[cx].rmask[CIF_F90_END_SCOPE] = '\0';
00397                   _Cif_filetbl[cx].rmask[CIF_F90_SCOPE_INFO] = '\0';
00398                   _Cif_filetbl[cx].rmask[CIF_F90_USE_MODULE] = '\0';
00399                   _Cif_filetbl[cx].rmask[CIF_F90_RENAME] = '\0';
00400                   _Cif_filetbl[cx].rmask[CIF_F90_INT_BLOCK] = '\0';
00401                   _Cif_filetbl[cx].rmask[CIF_F90_VECTORIZATION] = '\0';
00402 
00403                   _Cif_filetbl[cx].rmask[CIF_BE_NODE] = '\0';
00404                   _Cif_filetbl[cx].rmask[CIF_BE_FID] = '\0';
00405 
00406                 }
00407 
00408                 if (version < 3) {
00409 
00410                   _Cif_filetbl[cx].rmask[CIF_CC_TYPE] = '\0';
00411                   _Cif_filetbl[cx].rmask[CIF_CC_ENTRY] = '\0';
00412                   _Cif_filetbl[cx].rmask[CIF_CC_OBJ] = '\0';
00413                   _Cif_filetbl[cx].rmask[CIF_CC_SUBTYPE] = '\0';
00414                   _Cif_filetbl[cx].rmask[CIF_CC_ENUM] = '\0';
00415                   _Cif_filetbl[cx].rmask[CIF_CC_EXPR] = '\0';
00416 
00417                   _Cif_filetbl[cx].rmask[CIF_SRC_POS] = '\0';
00418                   _Cif_filetbl[cx].rmask[CIF_ORIG_CMD] = '\0';
00419 
00420                 }
00421         }
00422 
00423         else {  /* output file so */
00424                 _Cif_filetbl[cx].form = BINARY_CIF;
00425                 if (fwrite (binary_hdrkey, sizeof(char), 6, fd) != 6)
00426                         return (CIF_SYSERR);
00427                 if (fwrite (&binary_version, sizeof(char), 1, fd) != 1)
00428                         return (CIF_SYSERR);
00429 
00430                 /* Set both of the cif versions to the cif_open version; it is
00431                    not possible to open a cif as one version and then write
00432                    records from another version into it; ie if the users
00433                    compiled with v1 then that's what they get for all opens;
00434                    likewise for v2 */
00435 
00436                 _Cif_filetbl[cx].version = version;         /* version of cif on disk */
00437                 _Cif_filetbl[cx].return_version = version;  /* version that the user wants */
00438               }
00439 
00440         /* determine if seeks are allowed on file */
00441 
00442         /*
00443          * Note. To get fileno to work on 6.1, use (fileno(fd) & 0xffff)
00444          * as the fileno structure changed slightly and the top however
00445          * many bits need to be masked out. I haven't put this in by
00446          * default as libcif should never be put onto a 6.1 system and
00447          * it seems like a kludge with unknown side effects, so it's best
00448          * to leave out
00449          *
00450          * Okay, so I changed my mind...I'm told that this is a safe
00451          * fix, but I'll leave in the warning above
00452          */
00453 
00454         (void) fstat ((int) (fileno(fd) & 0xffffffff), &statbuf);
00455         _Cif_filetbl[cx].seek = (S_ISREG(statbuf.st_mode) ? YES : NO);
00456 
00457         _Cif_filetbl[cx].fd = fd;
00458 
00459         /* Make a note of the cif being opened */
00460         _Cif_filetbl[cx].filename = strdup(filename);
00461 
00462         /*
00463          * Assume cif not created specially, cif_lines and cif_conv will
00464          * alter this if they are invoking cif_open indirectly for the user
00465          * and a temporary cif has been opened
00466          */
00467         _Cif_filetbl[cx].tmp_cif = 0;
00468 
00469 
00470         if (*optype == 'r' &&  /* reading from the file */
00471             _Cif_filetbl[cx].seek == YES &&  /* Otherwise, we can't backup */
00472             _Cif_filetbl[cx].return_version > 1) {  /* v2 cif or greater */
00473 
00474             /*
00475              * This is really messy, but we want to read ahead until
00476              * the srcfile record is read so that the src file id can
00477              * be put into the cifhdr record.
00478              */
00479 
00480             /* ensure that the file is at the beginning */
00481             (void) Cif_Setpos(cx, CIF_FIRST_RECORD);
00482 
00483             do {
00484                 rtype =  Cif_Getrecord(cx, &rptr);
00485             }
00486             while (rtype > 0 && rtype != CIF_SRCFILE &&
00487                    rtype != CIF_UNIT);
00488 
00489             if (rtype == CIF_SRCFILE) {
00490                 _Cif_filetbl[cx].srcfid = CIFSRC(rptr)->fid;
00491             }
00492 
00493             /* Reset, so that it looks like we haven't read anything yet */
00494             _Cif_filetbl[cx].mode = CIF_MEM_DEFAULT;
00495         }
00496 
00497         /* ensure that the file is at the beginning */
00498         if (_Cif_filetbl[cx].seek == YES)
00499             (void) Cif_Setpos(cx, CIF_FIRST_RECORD);
00500 
00501         return (cx);
00502         
00503 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines