LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/avc - avc_e00read.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 704 381 54.1 %
Date: 2012-12-26 Functions: 20 14 70.0 %

       1                 : /**********************************************************************
       2                 :  * $Id: avc_e00read.c,v 1.28 2008/07/30 19:22:18 dmorissette Exp $
       3                 :  *
       4                 :  * Name:     avc_e00read.c
       5                 :  * Project:  Arc/Info vector coverage (AVC)  BIN->E00 conversion library
       6                 :  * Language: ANSI C
       7                 :  * Purpose:  Functions to open a binary coverage and read it as if it
       8                 :  *           was an ASCII E00 file.  This file is the main entry point
       9                 :  *           for the library.
      10                 :  * Author:   Daniel Morissette, dmorissette@dmsolutions.ca
      11                 :  *
      12                 :  **********************************************************************
      13                 :  * Copyright (c) 1999-2005, Daniel Morissette
      14                 :  *
      15                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      16                 :  * copy of this software and associated documentation files (the "Software"),
      17                 :  * to deal in the Software without restriction, including without limitation
      18                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      19                 :  * and/or sell copies of the Software, and to permit persons to whom the
      20                 :  * Software is furnished to do so, subject to the following conditions:
      21                 :  * 
      22                 :  * The above copyright notice and this permission notice shall be included
      23                 :  * in all copies or substantial portions of the Software.
      24                 :  * 
      25                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      26                 :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      27                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      28                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      29                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      30                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
      31                 :  * DEALINGS IN THE SOFTWARE.
      32                 :  **********************************************************************
      33                 :  *
      34                 :  * $Log: avc_e00read.c,v $
      35                 :  * Revision 1.28  2008/07/30 19:22:18  dmorissette
      36                 :  * Move detection of EXP header directly in AVCE00ReadOpenE00() and use
      37                 :  * VSIFGets() instead of CPLReadLine() to avoid problem with huge one line
      38                 :  * files (GDAL/OGR ticket #1989)
      39                 :  *
      40                 :  * Revision 1.27  2008/07/30 18:35:53  dmorissette
      41                 :  * Avoid scanning the whole E00 input file in AVCE00ReadOpenE00() if the
      42                 :  * file does not start with an EXP line (GDAL/OGR ticket 1989)
      43                 :  *
      44                 :  * Revision 1.26  2008/07/30 16:17:46  dmorissette
      45                 :  * Detect compressed E00 input files and refuse to open them instead of
      46                 :  * crashing (bug 1928, GDAL/OGR ticket 2513)
      47                 :  *
      48                 :  * Revision 1.25  2008/07/24 20:34:12  dmorissette
      49                 :  * Fixed VC++ WIN32 build problems in GDAL/OGR environment
      50                 :  * (GDAL/OGR ticket http://trac.osgeo.org/gdal/ticket/2500)
      51                 :  *
      52                 :  * Revision 1.24  2008/07/24 13:49:20  dmorissette
      53                 :  * Fixed GCC compiler warning (GDAL ticket #2495)
      54                 :  *
      55                 :  * Revision 1.23  2006/08/17 19:51:01  dmorissette
      56                 :  * #include <unistd.h> to solve warning on 64 bit platforms (bug 1461)
      57                 :  *
      58                 :  * Revision 1.22  2006/08/17 18:56:42  dmorissette
      59                 :  * Support for reading standalone info tables (just tables, no coverage
      60                 :  * data) by pointing AVCE00ReadOpen() to the info directory (bug 1549).
      61                 :  *
      62                 :  * Revision 1.21  2006/06/27 18:38:43  dmorissette
      63                 :  * Cleaned up E00 reading (bug 1497, patch from James F.)
      64                 :  *
      65                 :  * Revision 1.20  2006/06/27 18:06:34  dmorissette
      66                 :  * Applied patch for EOP processing from James F. (bug 1497)
      67                 :  *
      68                 :  * Revision 1.19  2006/06/16 11:48:11  daniel
      69                 :  * New functions to read E00 files directly as opposed to translating to
      70                 :  * binary coverage. Used in the implementation of E00 read support in OGR.
      71                 :  * Contributed by James E. Flemer. (bug 1497)
      72                 :  *
      73                 :  * Revision 1.18  2006/06/14 16:31:28  daniel
      74                 :  * Added support for AVCCoverPC2 type (bug 1491)
      75                 :  *
      76                 :  * Revision 1.17  2005/06/03 03:49:58  daniel
      77                 :  * Update email address, website url, and copyright dates
      78                 :  *
      79                 :  * Revision 1.16  2004/07/14 18:49:50  daniel
      80                 :  * Fixed leak when trying to open something that's not a coverage (bug513)
      81                 :  *
      82                 :  * Revision 1.15  2002/08/27 15:46:15  daniel
      83                 :  * Applied fix made in GDAL/OGR by 'aubin' (moved include ctype.h after avc.h)
      84                 :  *
      85                 :  * Revision 1.14  2000/09/22 19:45:21  daniel
      86                 :  * Switch to MIT-style license
      87                 :  *
      88                 :  * Revision 1.13  2000/05/29 15:31:31  daniel
      89                 :  * Added Japanese DBCS support
      90                 :  *
      91                 :  * Revision 1.12  2000/02/14 17:21:01  daniel
      92                 :  * Made more robust for corrupted or invalid files in cover directory
      93                 :  *
      94                 :  * Revision 1.11  2000/02/02 04:26:04  daniel
      95                 :  * Support reading TX6/TX7/RXP/RPL files in weird coverages
      96                 :  *
      97                 :  * Revision 1.10  2000/01/10 02:56:30  daniel
      98                 :  * Added read support for "weird" coverages
      99                 :  *
     100                 :  * Revision 1.9  2000/01/07 07:12:49  daniel
     101                 :  * Added support for reading PC Coverage TXT files
     102                 :  *
     103                 :  * Revision 1.8  1999/12/24 07:41:08  daniel
     104                 :  * Check fname length before testing for extension in AVCE00ReadFindCoverType()
     105                 :  *
     106                 :  * Revision 1.7  1999/12/24 07:18:34  daniel
     107                 :  * Added PC Arc/Info coverages support
     108                 :  *
     109                 :  * Revision 1.6  1999/08/26 17:22:18  daniel
     110                 :  * Use VSIFopen() instead of fopen() directly
     111                 :  *
     112                 :  * Revision 1.5  1999/08/23 18:21:41  daniel
     113                 :  * New syntax for AVCBinReadListTables()
     114                 :  *
     115                 :  * Revision 1.4  1999/05/11 02:10:01  daniel
     116                 :  * Free psInfo struct inside AVCE00ReadClose()
     117                 :  *
     118                 :  * Revision 1.3  1999/04/06 19:43:26  daniel
     119                 :  * Added E00 coverage path in EXP 0  header line
     120                 :  *
     121                 :  * Revision 1.2  1999/02/25 04:19:01  daniel
     122                 :  * Added TXT, TX6/TX7, RXP and RPL support + other minor changes
     123                 :  *
     124                 :  * Revision 1.1  1999/01/29 16:28:52  daniel
     125                 :  * Initial revision
     126                 :  *
     127                 :  **********************************************************************/
     128                 : 
     129                 : #include "avc.h"
     130                 : 
     131                 : #ifdef WIN32
     132                 : #  include <direct.h>   /* getcwd() */
     133                 : #else
     134                 : #  include <unistd.h>   /* getcwd() */
     135                 : #endif
     136                 : 
     137                 : #include <ctype.h>      /* toupper() */
     138                 : 
     139                 : static void _AVCE00ReadScanE00(AVCE00ReadE00Ptr psRead);
     140                 : static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo,
     141                 :                                      char **papszCoverDir);
     142                 : static AVCCoverType _AVCE00ReadFindCoverType(char **papszCoverDir);
     143                 : 
     144                 : 
     145                 : /**********************************************************************
     146                 :  *                          AVCE00ReadOpen()
     147                 :  *
     148                 :  * Open a Arc/Info coverage to read it as if it was an E00 file.
     149                 :  *
     150                 :  * You can either pass the name of the coverage directory, or the path
     151                 :  * to one of the files in the coverage directory.  The name of the
     152                 :  * coverage MUST be included in pszCoverPath... this means that
     153                 :  * passing "." is invalid.
     154                 :  * The following are all valid values for pszCoverPath:
     155                 :  *               /home/data/country
     156                 :  *               /home/data/country/
     157                 :  *               /home/data/country/arc.adf
     158                 :  * (Of course you should replace the '/' with '\\' on DOS systems!)
     159                 :  *
     160                 :  * Returns a new AVCE00ReadPtr handle or NULL if the coverage could 
     161                 :  * not be opened or if it does not appear to be a valid Arc/Info coverage.
     162                 :  *
     163                 :  * The handle will eventually have to be released with AVCE00ReadClose().
     164                 :  **********************************************************************/
     165             177 : AVCE00ReadPtr  AVCE00ReadOpen(const char *pszCoverPath)
     166                 : {
     167                 :     AVCE00ReadPtr   psInfo;
     168                 :     int             i, nLen, nCoverPrecision;
     169                 :     VSIStatBuf      sStatBuf;
     170             177 :     char            **papszCoverDir = NULL;
     171                 : 
     172             177 :     CPLErrorReset();
     173                 : 
     174                 :     /*-----------------------------------------------------------------
     175                 :      * pszCoverPath must be either a valid directory name or a valid
     176                 :      * file name.
     177                 :      *----------------------------------------------------------------*/
     178             353 :     if (pszCoverPath == NULL || strlen(pszCoverPath) == 0 ||
     179             176 :         VSIStat(pszCoverPath, &sStatBuf) == -1)
     180                 :     {
     181              55 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     182                 :                  "Invalid coverage path: %s.", 
     183                 :                  pszCoverPath?pszCoverPath:"(NULL)");
     184              55 :         return NULL;
     185                 :     }
     186                 : 
     187                 :     /*-----------------------------------------------------------------
     188                 :      * Alloc the AVCE00ReadPtr handle
     189                 :      *----------------------------------------------------------------*/
     190             122 :     psInfo = (AVCE00ReadPtr)CPLCalloc(1, sizeof(struct AVCE00ReadInfo_t));
     191                 : 
     192                 :     /*-----------------------------------------------------------------
     193                 :      * 2 possibilities about the value passed in pszCoverPath:
     194                 :      * - It can be the directory name of the coverage
     195                 :      * - or it can be the path to one of the files in the coverage
     196                 :      *
     197                 :      * If the name passed in pszCoverPath is not a directory, then we
     198                 :      * need to strip the last part of the filename to keep only the
     199                 :      * path, terminated by a '/' (or a '\\').
     200                 :      *----------------------------------------------------------------*/
     201             122 :     if (VSI_ISDIR(sStatBuf.st_mode))
     202                 :     {
     203                 :         /*-------------------------------------------------------------
     204                 :          * OK, we have a valid directory name... make sure it is 
     205                 :          * terminated with a '/' (or '\\')
     206                 :          *------------------------------------------------------------*/
     207               1 :         nLen = strlen(pszCoverPath);
     208                 : 
     209               1 :         if (pszCoverPath[nLen-1] == '/' || pszCoverPath[nLen-1] == '\\')
     210               0 :             psInfo->pszCoverPath = CPLStrdup(pszCoverPath);
     211                 :         else
     212                 :         {
     213                 : #ifdef WIN32
     214                 :             psInfo->pszCoverPath = CPLStrdup(CPLSPrintf("%s\\",pszCoverPath));
     215                 : #else
     216               1 :             psInfo->pszCoverPath = CPLStrdup(CPLSPrintf("%s/",pszCoverPath));
     217                 : #endif
     218                 :         }
     219                 :     }
     220                 :     else
     221                 :     {
     222                 :         /*-------------------------------------------------------------
     223                 :          * We are dealing with a filename.
     224                 :          * Extract the coverage path component and store it.
     225                 :          * The coverage path will remain terminated by a '/' or '\\' char.
     226                 :          *------------------------------------------------------------*/
     227             121 :         psInfo->pszCoverPath = CPLStrdup(pszCoverPath);
     228                 : 
     229            4845 :         for( i = strlen(psInfo->pszCoverPath)-1; 
     230            1615 :              i > 0 && psInfo->pszCoverPath[i] != '/' &&
     231            1494 :                  psInfo->pszCoverPath[i] != '\\';
     232            1494 :              i-- ) {}
     233                 : 
     234             121 :         psInfo->pszCoverPath[i+1] = '\0';
     235                 :     }
     236                 : 
     237                 : 
     238                 :     /*-----------------------------------------------------------------
     239                 :      * Extract the coverage name from the coverage path.  Note that
     240                 :      * for this the coverage path must be in the form:
     241                 :      * "dir1/dir2/dir3/covername/" ... if it is not the case, then
     242                 :      * we would have to use getcwd() to find the current directory name...
     243                 :      * but for now we'll just produce an error if this happens.
     244                 :      *----------------------------------------------------------------*/
     245             122 :     nLen = 0;
     246            2106 :     for( i = strlen(psInfo->pszCoverPath)-1; 
     247             470 :    i > 0 && psInfo->pszCoverPath[i-1] != '/' &&
     248             464 :             psInfo->pszCoverPath[i-1] != '\\'&&
     249             464 :             psInfo->pszCoverPath[i-1] != ':';
     250             464 :    i-- ) 
     251                 :     {
     252             464 :         nLen++;
     253                 :     }
     254                 : 
     255             122 :     if (nLen > 0)
     256                 :     {
     257             122 :         psInfo->pszCoverName = CPLStrdup(psInfo->pszCoverPath+i);
     258             122 :         psInfo->pszCoverName[nLen] = '\0';
     259                 :     }
     260                 :     else
     261                 :     {
     262               0 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     263                 :                  "Invalid coverage path (%s): "
     264                 :                  "coverage name must be included in path.", pszCoverPath);
     265                 : 
     266               0 :         CPLFree(psInfo->pszCoverPath);
     267               0 :         CPLFree(psInfo);
     268               0 :         return NULL;
     269                 :     }
     270                 : 
     271                 :     /*-----------------------------------------------------------------
     272                 :      * Read the coverage directory listing and try to establish the cover type
     273                 :      *----------------------------------------------------------------*/
     274             122 :     papszCoverDir = CPLReadDir(psInfo->pszCoverPath);
     275                 : 
     276             122 :     psInfo->eCoverType = _AVCE00ReadFindCoverType(papszCoverDir);
     277                 : 
     278             122 :     if (psInfo->eCoverType == AVCCoverTypeUnknown  )
     279                 :     {
     280             121 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     281                 :                  "Invalid coverage (%s): directory does not appear to "
     282                 :                  "contain any supported vector coverage file.",  pszCoverPath);
     283             121 :         CPLFree(psInfo->pszCoverName);
     284             121 :         CPLFree(psInfo->pszCoverPath);
     285             121 :         CPLFree(psInfo->pszInfoPath);
     286             121 :         CPLFree(psInfo);
     287             121 :         CSLDestroy(papszCoverDir);
     288             121 :         return NULL;
     289                 :     }
     290                 : 
     291                 :    
     292                 :     /*-----------------------------------------------------------------
     293                 :      * INFO path: PC Coverages have all files in the same dir, and unix
     294                 :      * covers have the INFO files in ../info
     295                 :      *----------------------------------------------------------------*/
     296               1 :     if (psInfo->eCoverType == AVCCoverPC || psInfo->eCoverType == AVCCoverPC2)
     297                 :     {
     298               0 :         psInfo->pszInfoPath = CPLStrdup(psInfo->pszCoverPath);
     299                 :     }
     300                 :     else
     301                 :     {
     302                 :         /*-------------------------------------------------------------
     303                 :          * Lazy way to build the INFO path: simply add "../info/"...
     304                 :          * this could probably be improved!
     305                 :          *------------------------------------------------------------*/
     306               1 :         psInfo->pszInfoPath =(char*)CPLMalloc((strlen(psInfo->pszCoverPath)+9)*
     307                 :                                            sizeof(char));
     308                 : #ifdef WIN32
     309                 : #  define AVC_INFOPATH "..\\info\\"
     310                 : #else
     311                 : #  define AVC_INFOPATH "../info/"
     312                 : #endif
     313               1 :         sprintf(psInfo->pszInfoPath, "%s%s", psInfo->pszCoverPath, 
     314                 :                                              AVC_INFOPATH);
     315                 : 
     316               1 :         AVCAdjustCaseSensitiveFilename(psInfo->pszInfoPath);
     317                 :     }
     318                 : 
     319                 :     /*-----------------------------------------------------------------
     320                 :      * For Unix coverages, check that the info directory exists and 
     321                 :      * contains the "arc.dir".  In AVCCoverWeird, the arc.dir is 
     322                 :      * called "../INFO/ARCDR9".
     323                 :      * PC Coverages have their info tables in the same direcotry as 
     324                 :      * the coverage files.
     325                 :      *----------------------------------------------------------------*/
     326               3 :     if (((psInfo->eCoverType == AVCCoverV7 || 
     327               0 :           psInfo->eCoverType == AVCCoverV7Tables) &&
     328               1 :          ! AVCFileExists(psInfo->pszInfoPath, "arc.dir") ) ||
     329               1 :          (psInfo->eCoverType == AVCCoverWeird &&
     330               0 :          ! AVCFileExists(psInfo->pszInfoPath, "arcdr9") ) )
     331                 :     {
     332               0 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     333                 :              "Invalid coverage (%s): 'info' directory not found or invalid.", 
     334                 :                                               pszCoverPath);
     335               0 :         CPLFree(psInfo->pszCoverName);
     336               0 :         CPLFree(psInfo->pszCoverPath);
     337               0 :         CPLFree(psInfo->pszInfoPath);
     338               0 :         CPLFree(psInfo);
     339               0 :         CSLDestroy(papszCoverDir);
     340               0 :         return NULL;
     341                 :     }
     342                 : 
     343                 :     /*-----------------------------------------------------------------
     344                 :      * Make sure there was no error until now before we build squeleton.
     345                 :      *----------------------------------------------------------------*/
     346               1 :     if (CPLGetLastErrorNo() != 0)
     347                 :     {
     348               0 :         CPLFree(psInfo->pszCoverName);
     349               0 :         CPLFree(psInfo->pszCoverPath);
     350               0 :         CPLFree(psInfo->pszInfoPath);
     351               0 :         CPLFree(psInfo);
     352               0 :         CSLDestroy(papszCoverDir);
     353               0 :         return NULL;
     354                 :     }
     355                 : 
     356                 :     /*-----------------------------------------------------------------
     357                 :      * Build the E00 file squeleton and be ready to return a E00 header...
     358                 :      * We'll also read the coverage precision by the same way.
     359                 :      *----------------------------------------------------------------*/
     360               1 :     nCoverPrecision = _AVCE00ReadBuildSqueleton(psInfo, papszCoverDir);
     361                 : 
     362                 :     /* Ignore warnings produced while building squeleton */
     363               1 :     CPLErrorReset();
     364                 : 
     365               1 :     CSLDestroy(papszCoverDir);
     366               1 :     papszCoverDir = NULL;
     367                 : 
     368               1 :     psInfo->iCurSection = 0;
     369               1 :     psInfo->iCurStep = AVC_GEN_NOTSTARTED;
     370               1 :     psInfo->bReadAllSections = TRUE;
     371                 : 
     372                 :     /*-----------------------------------------------------------------
     373                 :      * Init the E00 generator.
     374                 :      *----------------------------------------------------------------*/
     375               1 :     psInfo->hGenInfo = AVCE00GenInfoAlloc(nCoverPrecision);
     376                 : 
     377                 :     /*-----------------------------------------------------------------
     378                 :      * Init multibyte encoding info
     379                 :      *----------------------------------------------------------------*/
     380               1 :     psInfo->psDBCSInfo = AVCAllocDBCSInfo();
     381                 : 
     382                 :     /*-----------------------------------------------------------------
     383                 :      * If an error happened during the open call, cleanup and return NULL.
     384                 :      *----------------------------------------------------------------*/
     385               1 :     if (CPLGetLastErrorNo() != 0)
     386                 :     {
     387               0 :         AVCE00ReadClose(psInfo);
     388               0 :         psInfo = NULL;
     389                 :     }
     390                 : 
     391               1 :     return psInfo;
     392                 : }
     393                 : 
     394                 : /**********************************************************************
     395                 :  *                          AVCE00ReadOpenE00()
     396                 :  *
     397                 :  * Open a E00 file for reading.
     398                 :  *
     399                 :  * Returns a new AVCE00ReadE00Ptr handle or NULL if the file could
     400                 :  * not be opened or if it does not appear to be a valid E00 file.
     401                 :  *
     402                 :  * The handle will eventually have to be released with
     403                 :  * AVCE00ReadCloseE00().
     404                 :  **********************************************************************/
     405             351 : AVCE00ReadE00Ptr AVCE00ReadOpenE00(const char *pszE00FileName)
     406                 : {
     407                 :     AVCE00ReadE00Ptr psRead;
     408                 :     VSIStatBuf       sStatBuf;
     409                 :     FILE             *fp;
     410                 :     char             *p;
     411                 :     char             szHeader[10];
     412                 : 
     413             351 :     CPLErrorReset();
     414                 : 
     415                 :     /*-----------------------------------------------------------------
     416                 :      * pszE00FileName must be a valid file that can be opened for
     417                 :      * reading
     418                 :      *----------------------------------------------------------------*/
     419             941 :     if (pszE00FileName == NULL || strlen(pszE00FileName) == 0 ||
     420             349 :         VSIStat(pszE00FileName, &sStatBuf) == -1 ||
     421             241 :         VSI_ISDIR(sStatBuf.st_mode))
     422                 :     {
     423             110 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     424                 :                  "Invalid E00 file path: %s.", 
     425                 :                  pszE00FileName?pszE00FileName:"(NULL)");
     426             110 :         return NULL;
     427                 :     }
     428                 : 
     429             241 :     if (NULL == (fp = VSIFOpen(pszE00FileName, "r")))
     430               0 :         return NULL;
     431                 : 
     432                 :     /*-----------------------------------------------------------------
     433                 :      * Make sure the file starts with a "EXP  0" or "EXP  1" header
     434                 :      *----------------------------------------------------------------*/
     435             241 :     if (VSIFGets(szHeader, 5, fp) == NULL || !EQUALN("EXP ", szHeader, 4) )
     436                 :     {
     437             238 :         CPLError(CE_Failure, CPLE_OpenFailed, 
     438                 :                  "This does not look like a E00 file: does not start with "
     439                 :                  "a EXP header." );
     440             238 :         VSIFClose(fp);
     441             238 :         return NULL;
     442                 :     }
     443               3 :     VSIRewind(fp);
     444                 : 
     445                 :     /*-----------------------------------------------------------------
     446                 :      * Alloc the AVCE00ReadE00Ptr handle
     447                 :      *----------------------------------------------------------------*/
     448               3 :     psRead = (AVCE00ReadE00Ptr)CPLCalloc(1,
     449                 :             sizeof(struct AVCE00ReadInfoE00_t));
     450                 : 
     451               3 :     psRead->hFile = fp;
     452               3 :     psRead->pszCoverPath = CPLStrdup(pszE00FileName);
     453               3 :     psRead->eCurFileType = AVCFileUnknown;
     454                 : 
     455                 :     /*-----------------------------------------------------------------
     456                 :      * Extract the coverage name from the coverage path.
     457                 :      *----------------------------------------------------------------*/
     458               6 :     if (NULL != (p = strrchr(psRead->pszCoverPath, '/')) ||
     459               0 :         NULL != (p = strrchr(psRead->pszCoverPath, '\\')) ||
     460               0 :         NULL != (p = strrchr(psRead->pszCoverPath, ':')))
     461                 :     {
     462               3 :         psRead->pszCoverName = CPLStrdup(p + 1);
     463                 :     }
     464                 :     else
     465                 :     {
     466               0 :         psRead->pszCoverName = CPLStrdup(psRead->pszCoverPath);
     467                 :     }
     468               3 :     if (NULL != (p = strrchr(psRead->pszCoverName, '.')))
     469                 :     {
     470               3 :         *p = '\0';
     471                 :     }
     472                 : 
     473                 :     /*-----------------------------------------------------------------
     474                 :      * Make sure there was no error until now before we scan file.
     475                 :      *----------------------------------------------------------------*/
     476               3 :     if (CPLGetLastErrorNo() != 0)
     477                 :     {
     478               0 :         AVCE00ReadCloseE00(psRead);
     479               0 :         return NULL;
     480                 :     }
     481                 : 
     482               3 :     psRead->hParseInfo = AVCE00ParseInfoAlloc();
     483                 : 
     484                 :     /*-----------------------------------------------------------------
     485                 :      * Scan the E00 file for sections
     486                 :      *----------------------------------------------------------------*/
     487               3 :     _AVCE00ReadScanE00(psRead);
     488               3 :     if (CPLGetLastErrorNo() != 0)
     489                 :     {
     490               1 :         AVCE00ReadCloseE00(psRead);
     491               1 :         return NULL;
     492                 :     }
     493                 : 
     494               2 :     AVCE00ReadRewindE00(psRead);
     495               2 :     CPLErrorReset();
     496                 : 
     497               2 :     if (psRead->numSections < 1)
     498                 :     {
     499               0 :         AVCE00ReadCloseE00(psRead);
     500               0 :         return NULL;
     501                 :     }
     502                 : 
     503               2 :     psRead->bReadAllSections = TRUE;
     504                 : 
     505                 :     /*-----------------------------------------------------------------
     506                 :      * If an error happened during the open call, cleanup and return NULL.
     507                 :      *----------------------------------------------------------------*/
     508               2 :     if (CPLGetLastErrorNo() != 0)
     509                 :     {
     510               0 :         AVCE00ReadCloseE00(psRead);
     511               0 :         psRead = NULL;
     512                 :     }
     513                 : 
     514               2 :     return psRead;
     515                 : }
     516                 : 
     517                 : /**********************************************************************
     518                 :  *                          AVCE00ReadClose()
     519                 :  *
     520                 :  * Close a coverage and release all memory used by the AVCE00ReadPtr
     521                 :  * handle.
     522                 :  **********************************************************************/
     523               1 : void AVCE00ReadClose(AVCE00ReadPtr psInfo)
     524                 : {
     525               1 :     CPLErrorReset();
     526                 : 
     527               1 :     if (psInfo == NULL)
     528               0 :         return;
     529                 : 
     530               1 :     CPLFree(psInfo->pszCoverPath);
     531               1 :     CPLFree(psInfo->pszInfoPath);
     532               1 :     CPLFree(psInfo->pszCoverName);
     533                 : 
     534               1 :     if (psInfo->hFile)
     535               0 :         AVCBinReadClose(psInfo->hFile);
     536                 : 
     537               1 :     if (psInfo->hGenInfo)
     538               1 :         AVCE00GenInfoFree(psInfo->hGenInfo);
     539                 : 
     540               1 :     if (psInfo->pasSections)
     541                 :     {
     542                 :         int i;
     543              13 :         for(i=0; i<psInfo->numSections; i++)
     544                 :         {
     545              12 :             CPLFree(psInfo->pasSections[i].pszName);
     546              12 :             CPLFree(psInfo->pasSections[i].pszFilename);
     547                 :         }
     548               1 :         CPLFree(psInfo->pasSections);
     549                 :     }
     550                 : 
     551               1 :     AVCFreeDBCSInfo(psInfo->psDBCSInfo);
     552                 : 
     553               1 :     CPLFree(psInfo);
     554                 : }
     555                 : 
     556                 : /**********************************************************************
     557                 :  *                          AVCE00ReadCloseE00()
     558                 :  *
     559                 :  * Close a coverage and release all memory used by the AVCE00ReadE00Ptr
     560                 :  * handle.
     561                 :  **********************************************************************/
     562               3 : void AVCE00ReadCloseE00(AVCE00ReadE00Ptr psRead)
     563                 : {
     564               3 :     if (psRead == NULL)
     565               0 :         return;
     566                 : 
     567               3 :     CPLFree(psRead->pszCoverPath);
     568               3 :     CPLFree(psRead->pszCoverName);
     569                 : 
     570               3 :     if (psRead->hFile)
     571                 :     {
     572               3 :         VSIFClose(psRead->hFile);
     573               3 :         psRead->hFile = 0;
     574                 :     }
     575                 : 
     576               3 :     if (psRead->pasSections)
     577                 :     {
     578                 :         int i;
     579              16 :         for(i=0; i<psRead->numSections; i++)
     580                 :         {
     581              14 :             CPLFree(psRead->pasSections[i].pszName);
     582              14 :             CPLFree(psRead->pasSections[i].pszFilename);
     583                 :         }
     584               2 :         CPLFree(psRead->pasSections);
     585                 :     }
     586                 : 
     587                 :     /* These Free calls handle NULL's */
     588               3 :     AVCE00ParseInfoFree(psRead->hParseInfo);
     589               3 :     psRead->hParseInfo = NULL;
     590                 : 
     591               3 :     CPLFree(psRead);
     592                 : }
     593                 : 
     594                 : 
     595                 : /**********************************************************************
     596                 :  *                          _AVCIncreaseSectionsArray()
     597                 :  *
     598                 :  * Add a number of structures to the Sections array and return the
     599                 :  * index of the first one that was added.  Note that the address of the
     600                 :  * original array (*pasArray) is quite likely to change!
     601                 :  *
     602                 :  * The value of *pnumItems will be updated to reflect the new array size.
     603                 :  **********************************************************************/
     604              22 : static int _AVCIncreaseSectionsArray(AVCE00Section **pasArray, int *pnumItems,
     605                 :                                     int numToAdd)
     606                 : {
     607                 :     int i;
     608                 : 
     609              22 :     *pasArray = (AVCE00Section*)CPLRealloc(*pasArray, 
     610              22 :                                            (*pnumItems+numToAdd)*
     611                 :                                                     sizeof(AVCE00Section));
     612                 : 
     613              48 :     for(i=0; i<numToAdd; i++)
     614                 :     {
     615              26 :         (*pasArray)[*pnumItems+i].eType = AVCFileUnknown;
     616              26 :         (*pasArray)[*pnumItems+i].pszName = NULL;
     617              26 :         (*pasArray)[*pnumItems+i].pszFilename = NULL;
     618              26 :         (*pasArray)[*pnumItems+i].nLineNum = 0;
     619              26 :         (*pasArray)[*pnumItems+i].nFeatureCount = -1;
     620                 :     }
     621                 : 
     622              22 :     i = *pnumItems;
     623              22 :     (*pnumItems) += numToAdd;
     624                 : 
     625              22 :     return i;
     626                 : }
     627                 : 
     628                 : /**********************************************************************
     629                 :  *                         _AVCE00ReadFindCoverType()
     630                 :  *
     631                 :  * This functions tries to establish the coverage type by looking
     632                 :  * at the coverage directory listing passed as argument.
     633                 :  *
     634                 :  * Returns one of AVCCoverV7 for Arc/Info V7 (Unix) coverages, or
     635                 :  *                AVCCoverPC for PC Arc/Info coverages.
     636                 :  *                AVCCoverWeird for an hybrid between V7 and PC
     637                 :  *
     638                 :  * If coverage type cannot be established then AVCCoverTypeUnknown is 
     639                 :  * returned.
     640                 :  **********************************************************************/
     641             122 : static AVCCoverType _AVCE00ReadFindCoverType(char **papszCoverDir)
     642                 : {
     643                 :     int         i, nLen;
     644             122 :     GBool       bFoundAdfFile=FALSE, bFoundArcFile=FALSE, 
     645             122 :                 bFoundTableFile=FALSE, bFoundDbfFile=FALSE,
     646             122 :                 bFoundArcDirFile=FALSE;
     647                 : 
     648                 :     /*-----------------------------------------------------------------
     649                 :      * Scan the list of files, looking for well known filenames.
     650                 :      * Start with the funky types first...
     651                 :      *----------------------------------------------------------------*/
     652           24466 :     for(i=0; papszCoverDir && papszCoverDir[i]; i++)
     653                 :     {
     654           24344 :         nLen = strlen(papszCoverDir[i]);
     655           24351 :         if (nLen > 4 && EQUAL(papszCoverDir[i]+nLen-4, ".adf") )
     656                 :         {
     657               7 :             bFoundAdfFile = TRUE;
     658                 :         }
     659           26315 :         else if (nLen > 4 && EQUAL(papszCoverDir[i]+nLen-4, ".dbf") )
     660                 :         {
     661            1978 :             bFoundDbfFile = TRUE;
     662                 :         }
     663          134154 :         else if (EQUAL(papszCoverDir[i], "arc") ||
     664           22359 :                  EQUAL(papszCoverDir[i], "cnt") ||
     665           22359 :                  EQUAL(papszCoverDir[i], "pal") ||
     666           22359 :                  EQUAL(papszCoverDir[i], "lab") ||
     667           22359 :                  EQUAL(papszCoverDir[i], "prj") ||
     668           22359 :                  EQUAL(papszCoverDir[i], "tol") )
     669                 :         {
     670               0 :             bFoundArcFile = TRUE;
     671                 :         }
     672           89436 :         else if (EQUAL(papszCoverDir[i], "aat") ||
     673           22359 :                  EQUAL(papszCoverDir[i], "pat") ||
     674           22359 :                  EQUAL(papszCoverDir[i], "bnd") ||
     675           22359 :                  EQUAL(papszCoverDir[i], "tic") )
     676                 :         {
     677               0 :             bFoundTableFile = TRUE;
     678                 :         }
     679           22359 :         else if (EQUAL(papszCoverDir[i], "arc.dir") )
     680                 :         {
     681               0 :             bFoundArcDirFile = TRUE;
     682                 :         }
     683                 : 
     684                 :     }
     685                 : 
     686                 :     /*-----------------------------------------------------------------
     687                 :      * Check for PC Arc/Info coverage - variant 1.
     688                 :      * These PC coverages have files with no extension (e.g. "ARC","PAL",...)
     689                 :      * and their tables filenames are in the form "???.dbf"
     690                 :      *----------------------------------------------------------------*/
     691             122 :     if (bFoundArcFile && bFoundDbfFile)
     692               0 :         return AVCCoverPC;
     693                 : 
     694                 :     /*-----------------------------------------------------------------
     695                 :      * Check for PC Arc/Info coverage - variant 2.
     696                 :      * looks like a hybrid between AVCCoverPC and AVCCoverV7
     697                 :      * These PC coverages have files with .adf extension (e.g."ARC.ADF"),
     698                 :      * and their tables filenames are in the form "???.dbf"
     699                 :      *----------------------------------------------------------------*/
     700             122 :     if (bFoundAdfFile && bFoundDbfFile)
     701               0 :         return AVCCoverPC2;
     702                 : 
     703                 :     /*-----------------------------------------------------------------
     704                 :      * Check for the weird coverages.
     705                 :      * Their coverage files have no extension just like PC Coverages, 
     706                 :      * and their tables have 3 letters filenames with no extension
     707                 :      * either (e.g. "AAT", "PAT", etc.)
     708                 :      * They also have a ../info directory, but we don't really need
     709                 :      * to check that (not yet!).
     710                 :      *----------------------------------------------------------------*/
     711             122 :     if (bFoundArcFile && bFoundTableFile)
     712               0 :         return AVCCoverWeird;
     713                 : 
     714                 :     /*-----------------------------------------------------------------
     715                 :      * V7 Coverages... they are the easiest to recognize
     716                 :      * because of the ".adf" file extension
     717                 :      *----------------------------------------------------------------*/
     718             122 :     if (bFoundAdfFile)
     719               1 :         return AVCCoverV7;
     720                 : 
     721                 :     /*-----------------------------------------------------------------
     722                 :      * Standalone info tables.
     723                 :      * We were pointed at the "info" directory. We'll treat this as
     724                 :      * a coverage with just info tables.
     725                 :      *----------------------------------------------------------------*/
     726             121 :     if (bFoundArcDirFile)
     727               0 :         return AVCCoverV7Tables;
     728                 : 
     729             121 :     return AVCCoverTypeUnknown;
     730                 : }
     731                 : 
     732                 : 
     733                 : /**********************************************************************
     734                 :  *                         _AVCE00ReadAddJabberwockySection()
     735                 :  *
     736                 :  * Add to the squeleton a section that contains subsections 
     737                 :  * for all the files with a given extension.
     738                 :  *
     739                 :  * Returns Updated Coverage precision
     740                 :  **********************************************************************/
     741               3 : static int _AVCE00ReadAddJabberwockySection(AVCE00ReadPtr psInfo,
     742                 :                                             AVCFileType   eFileType,
     743                 :                                             const char   *pszSectionName,
     744                 :                                             int           nCoverPrecision,
     745                 :                                             const char   *pszFileExtension,
     746                 :                                             char        **papszCoverDir )
     747                 : {
     748                 :     int         iSect, iDirEntry, nLen, nExtLen;
     749               3 :     GBool       bFoundFiles = FALSE;
     750               3 :     AVCBinFile *psFile=NULL;
     751                 : 
     752               3 :     nExtLen = strlen(pszFileExtension);
     753                 : 
     754                 :     /*-----------------------------------------------------------------
     755                 :      * Scan the directory for files with a ".txt" extension.
     756                 :      *----------------------------------------------------------------*/
     757                 : 
     758              33 :     for (iDirEntry=0; papszCoverDir && papszCoverDir[iDirEntry]; iDirEntry++)
     759                 :     {
     760              30 :         nLen = strlen(papszCoverDir[iDirEntry]);
     761                 : 
     762              30 :         if (nLen > nExtLen && EQUAL(papszCoverDir[iDirEntry] + nLen-nExtLen, 
     763                 :                                     pszFileExtension) &&
     764               0 :             (psFile = AVCBinReadOpen(psInfo->pszCoverPath, 
     765               0 :                                      papszCoverDir[iDirEntry],
     766                 :                                      psInfo->eCoverType, eFileType,
     767                 :                                      psInfo->psDBCSInfo)) != NULL)
     768                 :         {
     769               0 :             if (nCoverPrecision == AVC_DEFAULT_PREC)
     770               0 :                 nCoverPrecision = psFile->nPrecision;
     771               0 :             AVCBinReadClose(psFile);
     772                 : 
     773               0 :             if (bFoundFiles == FALSE)
     774                 :             {
     775                 :                 /* Insert a "TX6 #" header before the first TX6 file
     776                 :                  */
     777               0 :                 iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
     778                 :                                                   &(psInfo->numSections), 1);
     779               0 :                 psInfo->pasSections[iSect].eType = AVCFileUnknown;
     780                 : 
     781               0 :                 psInfo->pasSections[iSect].pszName = 
     782               0 :                             CPLStrdup(CPLSPrintf("%s  %c", pszSectionName,
     783                 :                                   (nCoverPrecision==AVC_DOUBLE_PREC)?'3':'2'));
     784                 : 
     785               0 :                 bFoundFiles = TRUE;
     786                 :             }
     787                 : 
     788                 :             /* Add this file to the squeleton 
     789                 :              */
     790               0 :             iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
     791                 :                                               &(psInfo->numSections), 1);
     792                 : 
     793               0 :             psInfo->pasSections[iSect].eType = eFileType;
     794               0 :             psInfo->pasSections[iSect].pszFilename= 
     795               0 :                                    CPLStrdup(papszCoverDir[iDirEntry]);
     796                 : 
     797                 :             /* pszName will contain only the classname without the file 
     798                 :              * extension */
     799               0 :             psInfo->pasSections[iSect].pszName =
     800               0 :                                    CPLStrdup(papszCoverDir[iDirEntry]);
     801               0 :             psInfo->pasSections[iSect].pszName[nLen-nExtLen] = '\0';
     802                 :         }
     803                 :     }
     804                 : 
     805               3 :     if (bFoundFiles)
     806                 :     {
     807                 :         /* Add a line to close the TX6 section.
     808                 :          */
     809               0 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
     810                 :                                           &(psInfo->numSections), 1);
     811               0 :         psInfo->pasSections[iSect].eType = AVCFileUnknown;
     812               0 :         psInfo->pasSections[iSect].pszName = CPLStrdup("JABBERWOCKY");
     813                 :     }
     814                 : 
     815               3 :     return nCoverPrecision;
     816                 : }
     817                 : 
     818                 : /**********************************************************************
     819                 :  *                     _AVCE00ReadNextLineE00()
     820                 :  *
     821                 :  * Processes the next line of input from the E00 file.
     822                 :  * (See AVCE00WriteNextLine() for similar processing.)
     823                 :  *
     824                 :  * Returns the next object from the E00 file, or NULL.
     825                 :  **********************************************************************/
     826             250 : static void *_AVCE00ReadNextLineE00(AVCE00ReadE00Ptr psRead,
     827                 :         const char *pszLine)
     828                 : {
     829             250 :     int nStatus = 0;
     830             250 :     void *psObj = 0;
     831                 : 
     832             250 :     AVCE00ParseInfo *psInfo = psRead->hParseInfo;
     833                 : 
     834             250 :     CPLErrorReset();
     835                 : 
     836             250 :     ++psInfo->nCurLineNum;
     837                 : 
     838             250 :     if (psInfo->bForceEndOfSection)
     839                 :     {
     840                 :         /*-------------------------------------------------------------
     841                 :          * The last call encountered an implicit end of section, so
     842                 :          * we close the section now without waiting for an end-of-section
     843                 :          * line (there won't be any!)... and get ready to proceed with
     844                 :          * the next section.
     845                 :          * This is used for TABLEs.
     846                 :          *------------------------------------------------------------*/
     847              10 :         AVCE00ParseSectionEnd(psInfo, pszLine, TRUE);
     848              10 :         psRead->eCurFileType = AVCFileUnknown;
     849                 :     }
     850                 : 
     851                 :     /*-----------------------------------------------------------------
     852                 :      * If we're at the top level inside a supersection... check if this
     853                 :      * supersection ends here.
     854                 :      *----------------------------------------------------------------*/
     855             250 :     if (AVCE00ParseSuperSectionEnd(psInfo, pszLine) == TRUE)
     856                 :     {
     857                 :         /* Nothing to do... it's all been done by the call to 
     858                 :          * AVCE00ParseSuperSectionEnd()
     859                 :          */
     860                 :     }
     861             248 :     else if (psRead->eCurFileType == AVCFileUnknown)
     862                 :     {
     863                 :         /*-------------------------------------------------------------
     864                 :          * We're at the top level or inside a supersection... waiting 
     865                 :          * to encounter a valid section or supersection header 
     866                 :          * (i.e. "ARC  2", etc...)
     867                 :          *------------------------------------------------------------*/
     868                 : 
     869                 :         /*-------------------------------------------------------------
     870                 :          * First check for a supersection header (TX6, RXP, IFO, ...)
     871                 :          *------------------------------------------------------------*/
     872              29 :         if ( AVCE00ParseSuperSectionHeader(psInfo,
     873                 :                                            pszLine) == AVCFileUnknown )
     874                 :         {
     875                 :             /*---------------------------------------------------------
     876                 :              * This was not a supersection header... check if it's a simple
     877                 :              * section header
     878                 :              *--------------------------------------------------------*/
     879              27 :             psRead->eCurFileType = AVCE00ParseSectionHeader(psInfo,
     880                 :                     pszLine);
     881                 :         }
     882                 :         else
     883                 :         {
     884                 :             /* got supersection */
     885                 :         }
     886                 : 
     887              29 :         if (psRead->eCurFileType == AVCFileTABLE)
     888                 :         {
     889                 :             /*---------------------------------------------------------
     890                 :              * send the first header line to the parser and wait until
     891                 :              * the whole header has been read.
     892                 :              *--------------------------------------------------------*/
     893               8 :             AVCE00ParseNextLine(psInfo, pszLine); 
     894                 :         }
     895              21 :         else if (psRead->eCurFileType != AVCFileUnknown)
     896                 :         {
     897                 :             /*---------------------------------------------------------
     898                 :              * found a valid section header
     899                 :              *--------------------------------------------------------*/
     900                 :         }
     901                 :     }
     902             357 :     else if (psRead->eCurFileType == AVCFileTABLE &&
     903              92 :              ! psInfo->bTableHdrComplete )
     904                 :     {
     905                 :         /*-------------------------------------------------------------
     906                 :          * We're reading a TABLE header... continue reading lines
     907                 :          * from the header
     908                 :          *
     909                 :          * Note: When parsing a TABLE, the first object returned will 
     910                 :          * be the AVCTableDef, then data records will follow.
     911                 :          *------------------------------------------------------------*/
     912              46 :         psObj = AVCE00ParseNextLine(psInfo, pszLine); 
     913              46 :         if (psObj)
     914                 :         {
     915                 :       /* got table header */
     916                 :             /* TODO: Enable return of table definition? */
     917               8 :             psObj = NULL;
     918                 :         }
     919                 :     }
     920                 :     else
     921                 :     {
     922                 :         /*-------------------------------------------------------------
     923                 :          * We're are in the middle of a section... first check if we
     924                 :          * have reached the end.
     925                 :          *
     926                 :          * note: The first call to AVCE00ParseSectionEnd() with FALSE will 
     927                 :          *       not reset the parser until we close the file... and then
     928                 :          *       we call the function again to reset the parser.
     929                 :          *------------------------------------------------------------*/
     930             173 :         if (AVCE00ParseSectionEnd(psInfo, pszLine, FALSE))
     931                 :         {
     932               7 :             psRead->eCurFileType = AVCFileUnknown;
     933               7 :             AVCE00ParseSectionEnd(psInfo, pszLine, TRUE);
     934                 :         }
     935                 :         else
     936                 :         /*-------------------------------------------------------------
     937                 :          * ... not at the end yet, so continue reading objects.
     938                 :          *------------------------------------------------------------*/
     939                 :         {
     940             166 :             psObj = AVCE00ParseNextLine(psInfo, pszLine);
     941                 : 
     942                 :             if (psObj)
     943                 :             {
     944                 :         /* got object */
     945                 :             }
     946                 :         }
     947                 :     }
     948                 : 
     949             250 :     if (CPLGetLastErrorNo() != 0)
     950               0 :         nStatus = -1;
     951                 : 
     952             250 :     return psObj;
     953                 : }
     954                 : 
     955                 : /**********************************************************************
     956                 :  *                         _AVCE00ReadBuildSqueleton()
     957                 :  *
     958                 :  * Build the squeleton of the E00 file corresponding to the specified
     959                 :  * coverage and set the appropriate fields in the AVCE00ReadPtr struct.
     960                 :  *
     961                 :  * Note that the order of the sections in the squeleton is important
     962                 :  * since some software may rely on this ordering when they read E00 files.
     963                 :  *
     964                 :  * The function returns the coverage precision that it will read from one
     965                 :  * of the file headers.  
     966                 :  **********************************************************************/
     967               1 : static int _AVCE00ReadBuildSqueleton(AVCE00ReadPtr psInfo, 
     968                 :                                      char **papszCoverDir)
     969                 : {
     970                 :     int         iSect, iTable, numTables, iFile, nLen;
     971               1 :     char      **papszTables, **papszFiles, szCWD[75]="", *pcTmp;
     972               1 :     char       *pszEXPPath=NULL;
     973               1 :     int         nCoverPrecision = AVC_DEFAULT_PREC;
     974               1 :     char        cPrecisionCode = '2';
     975               1 :     const char *szFname = NULL;
     976               1 :     AVCBinFile *psFile=NULL;
     977                 : 
     978               1 :     psInfo->numSections = 0;
     979               1 :     psInfo->pasSections = NULL;
     980                 : 
     981                 :     /*-----------------------------------------------------------------
     982                 :      * Build the absolute coverage path to include in the EXP  0 line
     983                 :      * This line usually contains the full path of the E00 file that
     984                 :      * is being created, but since the lib does not write the output
     985                 :      * file directly, there is no simple way to get that value.  Instead,
     986                 :      * we will use the absolute coverage path to which we add a .E00
     987                 :      * extension.
     988                 :      * We need also make sure cover path is all in uppercase.
     989                 :      *----------------------------------------------------------------*/
     990                 : #ifdef WIN32
     991                 :     if (psInfo->pszCoverPath[0] != '\\' &&
     992                 :         !(isalpha(psInfo->pszCoverPath[0]) && psInfo->pszCoverPath[1] == ':'))
     993                 : #else
     994               1 :     if (psInfo->pszCoverPath[0] != '/')
     995                 : #endif
     996                 :     {
     997               1 :         if (getcwd(szCWD, 74) == NULL)
     998               0 :             szCWD[0] = '\0';    /* Failed: buffer may be too small */
     999                 : 
    1000               1 :         nLen = strlen(szCWD);
    1001                 : 
    1002                 : #ifdef WIN32
    1003                 :         if (nLen > 0 && szCWD[nLen -1] != '\\')
    1004                 :             strcat(szCWD, "\\");
    1005                 : #else
    1006               1 :         if (nLen > 0 && szCWD[nLen -1] != '/')
    1007               1 :             strcat(szCWD, "/");
    1008                 : #endif
    1009                 :     }
    1010                 : 
    1011               2 :     pszEXPPath = CPLStrdup(CPLSPrintf("EXP  0 %s%-.*s.E00", szCWD,
    1012               1 :                                       (int)strlen(psInfo->pszCoverPath)-1,
    1013                 :                                       psInfo->pszCoverPath));
    1014               1 :     pcTmp = pszEXPPath;
    1015              68 :     for( ; *pcTmp != '\0'; pcTmp++)
    1016              67 :         *pcTmp = toupper(*pcTmp);
    1017                 : 
    1018                 :     /*-----------------------------------------------------------------
    1019                 :      * EXP Header
    1020                 :      *----------------------------------------------------------------*/
    1021               1 :     iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1022                 :                                   &(psInfo->numSections), 1);
    1023               1 :     psInfo->pasSections[iSect].eType = AVCFileUnknown;
    1024               1 :     psInfo->pasSections[iSect].pszName = pszEXPPath;
    1025                 : 
    1026                 :     /*-----------------------------------------------------------------
    1027                 :      * We have to try to open each file as we go for 2 reasons:
    1028                 :      * - To validate the file's signature in order to detect cases like a user
    1029                 :      *   that places files such as "mystuff.txt" in the cover directory...
    1030                 :      *   this has already happened and obviously lead to problems!)
    1031                 :      * - We also need to find the coverage's precision from the headers
    1032                 :      *----------------------------------------------------------------*/
    1033                 : 
    1034                 :     /*-----------------------------------------------------------------
    1035                 :      * ARC section (arc.adf)
    1036                 :      *----------------------------------------------------------------*/
    1037               1 :     szFname = (psInfo->eCoverType==AVCCoverV7 || 
    1038               0 :                psInfo->eCoverType==AVCCoverPC2 ) ? "arc.adf": "arc";
    1039               2 :     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
    1040               1 :          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
    1041                 :                                   psInfo->eCoverType, AVCFileARC,
    1042                 :                                   psInfo->psDBCSInfo)) != NULL)
    1043                 :     {
    1044               1 :         if (nCoverPrecision == AVC_DEFAULT_PREC)
    1045               1 :             nCoverPrecision = psFile->nPrecision;
    1046               1 :         AVCBinReadClose(psFile);
    1047               1 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1048                 :                                       &(psInfo->numSections), 1);
    1049                 : 
    1050               1 :         psInfo->pasSections[iSect].eType = AVCFileARC;
    1051               1 :         psInfo->pasSections[iSect].pszName = CPLStrdup("ARC");
    1052               1 :         psInfo->pasSections[iSect].pszFilename=CPLStrdup(papszCoverDir[iFile]);
    1053                 :     }
    1054                 : 
    1055                 :     /*-----------------------------------------------------------------
    1056                 :      * CNT section (cnt.adf)
    1057                 :      *----------------------------------------------------------------*/
    1058               1 :     szFname = (psInfo->eCoverType==AVCCoverV7 || 
    1059               0 :                psInfo->eCoverType==AVCCoverPC2 ) ? "cnt.adf": "cnt";
    1060               1 :     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
    1061               0 :          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
    1062                 :                                   psInfo->eCoverType, AVCFileCNT,
    1063                 :                                   psInfo->psDBCSInfo)) != NULL)
    1064                 :     {
    1065               0 :         if (nCoverPrecision == AVC_DEFAULT_PREC)
    1066               0 :             nCoverPrecision = psFile->nPrecision;
    1067               0 :         AVCBinReadClose(psFile);
    1068               0 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1069                 :                                       &(psInfo->numSections), 1);
    1070                 : 
    1071               0 :         psInfo->pasSections[iSect].eType = AVCFileCNT;
    1072               0 :         psInfo->pasSections[iSect].pszName = CPLStrdup("CNT");
    1073               0 :         psInfo->pasSections[iSect].pszFilename=CPLStrdup(papszCoverDir[iFile]);
    1074                 :     }
    1075                 : 
    1076                 :     /*-----------------------------------------------------------------
    1077                 :      * LAB section (lab.adf)
    1078                 :      *----------------------------------------------------------------*/
    1079               1 :     szFname = (psInfo->eCoverType==AVCCoverV7 || 
    1080               0 :                psInfo->eCoverType==AVCCoverPC2 ) ? "lab.adf": "lab";
    1081               2 :     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
    1082               1 :          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
    1083                 :                                   psInfo->eCoverType, AVCFileLAB,
    1084                 :                                   psInfo->psDBCSInfo)) != NULL)
    1085                 :     {
    1086               1 :         if (nCoverPrecision == AVC_DEFAULT_PREC)
    1087               0 :             nCoverPrecision = psFile->nPrecision;
    1088               1 :         AVCBinReadClose(psFile);
    1089               1 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1090                 :                                       &(psInfo->numSections), 1);
    1091                 : 
    1092               1 :         psInfo->pasSections[iSect].eType = AVCFileLAB;
    1093               1 :         psInfo->pasSections[iSect].pszName = CPLStrdup("LAB");
    1094               1 :         psInfo->pasSections[iSect].pszFilename=CPLStrdup(papszCoverDir[iFile]);
    1095                 :     }
    1096                 : 
    1097                 :     /*-----------------------------------------------------------------
    1098                 :      * PAL section (pal.adf)
    1099                 :      *----------------------------------------------------------------*/
    1100               1 :     szFname = (psInfo->eCoverType==AVCCoverV7 || 
    1101               0 :                psInfo->eCoverType==AVCCoverPC2 ) ? "pal.adf": "pal";
    1102               1 :     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
    1103               0 :          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
    1104                 :                                   psInfo->eCoverType, AVCFilePAL,
    1105                 :                                   psInfo->psDBCSInfo)) != NULL)
    1106                 :     {
    1107               0 :         if (nCoverPrecision == AVC_DEFAULT_PREC)
    1108               0 :             nCoverPrecision = psFile->nPrecision;
    1109               0 :         AVCBinReadClose(psFile);
    1110               0 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1111                 :                                       &(psInfo->numSections), 1);
    1112                 : 
    1113               0 :         psInfo->pasSections[iSect].eType = AVCFilePAL;
    1114               0 :         psInfo->pasSections[iSect].pszName = CPLStrdup("PAL");
    1115               0 :         psInfo->pasSections[iSect].pszFilename=CPLStrdup(papszCoverDir[iFile]);
    1116                 :     }
    1117                 : 
    1118                 :     /*-----------------------------------------------------------------
    1119                 :      * TOL section (tol.adf for single precision, par.adf for double)
    1120                 :      *----------------------------------------------------------------*/
    1121               1 :     szFname = (psInfo->eCoverType==AVCCoverV7 || 
    1122               0 :                psInfo->eCoverType==AVCCoverPC2 ) ? "tol.adf": "tol";
    1123               2 :     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
    1124               1 :          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
    1125                 :                                   psInfo->eCoverType, AVCFileTOL,
    1126                 :                                   psInfo->psDBCSInfo)) != NULL)
    1127                 :     {
    1128               1 :         if (nCoverPrecision == AVC_DEFAULT_PREC)
    1129               0 :             nCoverPrecision = psFile->nPrecision;
    1130               1 :         AVCBinReadClose(psFile);
    1131               1 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1132                 :                                       &(psInfo->numSections), 1);
    1133                 : 
    1134               1 :         psInfo->pasSections[iSect].eType = AVCFileTOL;
    1135               1 :         psInfo->pasSections[iSect].pszName = CPLStrdup("TOL");
    1136               1 :         psInfo->pasSections[iSect].pszFilename=CPLStrdup(papszCoverDir[iFile]);
    1137                 :     }
    1138                 : 
    1139               1 :     szFname = (psInfo->eCoverType==AVCCoverV7 || 
    1140               0 :                psInfo->eCoverType==AVCCoverPC2 ) ? "par.adf": "par";
    1141               1 :     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
    1142               0 :          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
    1143                 :                                   psInfo->eCoverType, AVCFileTOL,
    1144                 :                                   psInfo->psDBCSInfo)) != NULL)
    1145                 :     {
    1146               0 :         if (nCoverPrecision == AVC_DEFAULT_PREC)
    1147               0 :             nCoverPrecision = psFile->nPrecision;
    1148               0 :         AVCBinReadClose(psFile);
    1149               0 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1150                 :                                       &(psInfo->numSections), 1);
    1151                 : 
    1152               0 :         psInfo->pasSections[iSect].eType = AVCFileTOL;
    1153               0 :         psInfo->pasSections[iSect].pszName = CPLStrdup("TOL");
    1154               0 :         psInfo->pasSections[iSect].pszFilename=CPLStrdup(papszCoverDir[iFile]);
    1155                 :     }
    1156                 : 
    1157                 :     /*-----------------------------------------------------------------
    1158                 :      * TXT section (txt.adf)
    1159                 :      *----------------------------------------------------------------*/
    1160               1 :     szFname = (psInfo->eCoverType==AVCCoverV7 || 
    1161               0 :                psInfo->eCoverType==AVCCoverPC2 ) ? "txt.adf": "txt";
    1162               1 :     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 &&
    1163               0 :          (psFile = AVCBinReadOpen(psInfo->pszCoverPath, szFname,
    1164                 :                                   psInfo->eCoverType, AVCFileTXT,
    1165                 :                                   psInfo->psDBCSInfo)) != NULL)
    1166                 :     {
    1167               0 :         if (nCoverPrecision == AVC_DEFAULT_PREC)
    1168               0 :             nCoverPrecision = psFile->nPrecision;
    1169               0 :         AVCBinReadClose(psFile);
    1170               0 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1171                 :                                       &(psInfo->numSections), 1);
    1172                 : 
    1173               0 :         psInfo->pasSections[iSect].eType = AVCFileTXT;
    1174               0 :         psInfo->pasSections[iSect].pszName = CPLStrdup("TXT");
    1175               0 :         psInfo->pasSections[iSect].pszFilename=CPLStrdup(papszCoverDir[iFile]);
    1176                 :     }
    1177                 : 
    1178                 :     /*-----------------------------------------------------------------
    1179                 :      * TX6 section (*.txt)
    1180                 :      * Scan the directory for files with a ".txt" extension.
    1181                 :      * Note: Never seen those in a PC Arc/Info coverage!
    1182                 :      * In weird coverages, the filename ends with "txt" but there is no "."
    1183                 :      *----------------------------------------------------------------*/
    1184               1 :     if (psInfo->eCoverType == AVCCoverV7)
    1185               1 :         nCoverPrecision = _AVCE00ReadAddJabberwockySection(psInfo, AVCFileTX6,
    1186                 :                                                            "TX6", 
    1187                 :                                                            nCoverPrecision,
    1188                 :                                                            ".txt",
    1189                 :                                                            papszCoverDir);
    1190               0 :     else if (psInfo->eCoverType == AVCCoverWeird)
    1191               0 :         nCoverPrecision = _AVCE00ReadAddJabberwockySection(psInfo, AVCFileTX6,
    1192                 :                                                            "TX6", 
    1193                 :                                                            nCoverPrecision,
    1194                 :                                                            "txt",
    1195                 :                                                            papszCoverDir);
    1196                 : 
    1197                 :     /*-----------------------------------------------------------------
    1198                 :      * At this point, we should have read the coverage precsion... and if
    1199                 :      * we haven't yet then we'll just use single by default.
    1200                 :      * We'll need cPrecisionCode for some of the sections that follow.
    1201                 :      *----------------------------------------------------------------*/
    1202               1 :     if (nCoverPrecision == AVC_DOUBLE_PREC)
    1203               0 :         cPrecisionCode = '3';
    1204                 :     else
    1205               1 :         cPrecisionCode = '2';
    1206                 : 
    1207                 :     /*-----------------------------------------------------------------
    1208                 :      * SIN  2/3 and EOX lines ... ???
    1209                 :      *----------------------------------------------------------------*/
    1210               1 :     iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1211                 :                                   &(psInfo->numSections), 2);
    1212               1 :     psInfo->pasSections[iSect].eType = AVCFileUnknown;
    1213               1 :     psInfo->pasSections[iSect].pszName = CPLStrdup("SIN  X");
    1214               1 :     psInfo->pasSections[iSect].pszName[5] = cPrecisionCode;
    1215               1 :     iSect++;
    1216               1 :     psInfo->pasSections[iSect].eType = AVCFileUnknown;
    1217               1 :     psInfo->pasSections[iSect].pszName = CPLStrdup("EOX");
    1218               1 :     iSect++;
    1219                 : 
    1220                 :     /*-----------------------------------------------------------------
    1221                 :      * LOG section (log.adf) (ends with EOL)
    1222                 :      *----------------------------------------------------------------*/
    1223                 : 
    1224                 :     /*-----------------------------------------------------------------
    1225                 :      * PRJ section (prj.adf) (ends with EOP)
    1226                 :      *----------------------------------------------------------------*/
    1227               1 :     szFname = (psInfo->eCoverType==AVCCoverV7 || 
    1228               0 :                psInfo->eCoverType==AVCCoverPC2 ) ? "prj.adf": "prj";
    1229               1 :     if ( (iFile=CSLFindString(papszCoverDir, szFname)) != -1 )
    1230                 :     {
    1231               1 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1232                 :                                       &(psInfo->numSections), 1);
    1233                 : 
    1234               1 :         psInfo->pasSections[iSect].eType = AVCFilePRJ;
    1235               1 :         psInfo->pasSections[iSect].pszName = CPLStrdup("PRJ");
    1236               1 :         psInfo->pasSections[iSect].pszFilename=CPLStrdup(papszCoverDir[iFile]);
    1237                 :     }
    1238                 : 
    1239                 :     /*-----------------------------------------------------------------
    1240                 :      * RXP section (*.rxp)
    1241                 :      * Scan the directory for files with a ".rxp" extension.
    1242                 :      *----------------------------------------------------------------*/
    1243               1 :     if (psInfo->eCoverType == AVCCoverV7)
    1244               1 :         _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRXP, "RXP", 
    1245                 :                                          nCoverPrecision,".rxp",papszCoverDir);
    1246               0 :     else if (psInfo->eCoverType == AVCCoverWeird)
    1247               0 :         _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRXP, "RXP", 
    1248                 :                                          nCoverPrecision,"rxp",papszCoverDir);
    1249                 : 
    1250                 : 
    1251                 :     /*-----------------------------------------------------------------
    1252                 :      * RPL section (*.pal)
    1253                 :      * Scan the directory for files with a ".rpl" extension.
    1254                 :      *----------------------------------------------------------------*/
    1255               1 :     if (psInfo->eCoverType == AVCCoverV7)
    1256               1 :         _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRPL, "RPL", 
    1257                 :                                          nCoverPrecision,".pal",papszCoverDir);
    1258               0 :     else if (psInfo->eCoverType == AVCCoverWeird)
    1259               0 :         _AVCE00ReadAddJabberwockySection(psInfo, AVCFileRPL, "RPL", 
    1260                 :                                          nCoverPrecision,"rpl",papszCoverDir);
    1261                 : 
    1262                 :     /*-----------------------------------------------------------------
    1263                 :      * IFO section (tables)
    1264                 :      *----------------------------------------------------------------*/
    1265               1 :     papszTables = papszFiles = NULL;
    1266               2 :     if (psInfo->eCoverType == AVCCoverV7 || 
    1267               0 :         psInfo->eCoverType == AVCCoverV7Tables || 
    1268               0 :         psInfo->eCoverType == AVCCoverWeird)
    1269                 :     {
    1270                 :         /*-------------------------------------------------------------
    1271                 :          * Unix coverages: get tables from the ../info/arc.dir
    1272                 :          * Weird coverages: the arc.dir is similar but called "arcdr9"
    1273                 :          *------------------------------------------------------------*/
    1274               2 :         papszTables = AVCBinReadListTables(psInfo->pszInfoPath, 
    1275               1 :                                            psInfo->pszCoverName,
    1276                 :                                            &papszFiles, psInfo->eCoverType,
    1277                 :                                            psInfo->psDBCSInfo);
    1278                 :     }
    1279               0 :     else if (psInfo->eCoverType == AVCCoverPC ||
    1280               0 :              psInfo->eCoverType == AVCCoverPC2)
    1281                 :     {
    1282                 :         /*-------------------------------------------------------------
    1283                 :          * PC coverages: look for "???.dbf" in the coverage directory
    1284                 :          *               and build the table name using the coverage name
    1285                 :          *               as the table basename, and the dbf file basename
    1286                 :          *               as the table extension.
    1287                 :          *------------------------------------------------------------*/
    1288               0 :         for(iFile=0; papszCoverDir && papszCoverDir[iFile]; iFile++)
    1289                 :         {
    1290               0 :             if ((nLen = strlen(papszCoverDir[iFile])) == 7 &&
    1291               0 :                 EQUAL(papszCoverDir[iFile] + nLen -4, ".dbf"))
    1292                 :             {
    1293               0 :                 papszCoverDir[iFile][nLen - 4] = '\0';
    1294               0 :                 szFname = CPLSPrintf("%s.%s", psInfo->pszCoverName,
    1295               0 :                                               papszCoverDir[iFile]);
    1296               0 :                 pcTmp = (char*)szFname;
    1297               0 :                 for( ; *pcTmp != '\0'; pcTmp++)
    1298               0 :                     *pcTmp = toupper(*pcTmp);
    1299               0 :                 papszCoverDir[iFile][nLen - 4] = '.';
    1300                 : 
    1301               0 :                 papszTables = CSLAddString(papszTables, szFname);
    1302               0 :                 papszFiles = CSLAddString(papszFiles, papszCoverDir[iFile]);
    1303                 :             }
    1304                 :         }
    1305                 :     }
    1306                 : 
    1307               1 :     if ((numTables = CSLCount(papszTables)) > 0)
    1308                 :     {
    1309               1 :         iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1310                 :                                       &(psInfo->numSections), numTables+2);
    1311                 : 
    1312               1 :         psInfo->pasSections[iSect].eType = AVCFileUnknown;
    1313               1 :         psInfo->pasSections[iSect].pszName = CPLStrdup("IFO  X");
    1314               1 :         psInfo->pasSections[iSect].pszName[5] = cPrecisionCode;
    1315               1 :         iSect++;
    1316                 : 
    1317               3 :         for(iTable=0; iTable<numTables; iTable++)
    1318                 :         {
    1319               2 :             psInfo->pasSections[iSect].eType = AVCFileTABLE;
    1320               2 :             psInfo->pasSections[iSect].pszName=CPLStrdup(papszTables[iTable]);
    1321               2 :             if (papszFiles)
    1322                 :             {
    1323               4 :                 psInfo->pasSections[iSect].pszFilename=
    1324               2 :                                               CPLStrdup(papszFiles[iTable]);
    1325                 :             }
    1326               2 :             iSect++;
    1327                 :         }
    1328                 : 
    1329               1 :         psInfo->pasSections[iSect].eType = AVCFileUnknown;
    1330               1 :         psInfo->pasSections[iSect].pszName = CPLStrdup("EOI");
    1331               1 :         iSect++;
    1332                 : 
    1333                 :     }
    1334               1 :     CSLDestroy(papszTables);
    1335               1 :     CSLDestroy(papszFiles);
    1336                 : 
    1337                 :     /*-----------------------------------------------------------------
    1338                 :      * File ends with EOS
    1339                 :      *----------------------------------------------------------------*/
    1340               1 :     iSect = _AVCIncreaseSectionsArray(&(psInfo->pasSections), 
    1341                 :                                   &(psInfo->numSections), 1);
    1342               1 :     psInfo->pasSections[iSect].eType = AVCFileUnknown;
    1343               1 :     psInfo->pasSections[iSect].pszName = CPLStrdup("EOS");
    1344                 : 
    1345                 : 
    1346               1 :     return nCoverPrecision;
    1347                 : }
    1348                 : 
    1349                 : 
    1350                 : /**********************************************************************
    1351                 :  *                     _AVCE00ReadScanE00()
    1352                 :  *
    1353                 :  * Processes an entire E00 file to find all the interesting sections.
    1354                 :  **********************************************************************/
    1355               3 : static void _AVCE00ReadScanE00(AVCE00ReadE00Ptr psRead)
    1356                 : {
    1357               3 :     AVCE00ParseInfo *psInfo = psRead->hParseInfo;
    1358                 : 
    1359                 :     const char *pszLine;
    1360               3 :     const char *pszName = 0;
    1361                 :     void       *obj;
    1362               3 :     int        iSect = 0;
    1363               3 :     GBool      bFirstLine = TRUE;
    1364                 : 
    1365             463 :     while (CPLGetLastErrorNo() == 0 &&
    1366             230 :             (pszLine = CPLReadLine(psRead->hFile) ) != NULL )
    1367                 :     {
    1368             228 :         if (bFirstLine)
    1369                 :         {
    1370                 :             /* Look for the first non-empty line, after the EXP header,
    1371                 :              * trying to detect compressed E00 files. If the file is 
    1372                 :              * compressed, the first line of data should be 79 or 80 chars
    1373                 :              * long and contain several '~' characters.
    1374                 :              */
    1375               6 :             int nLen = strlen(pszLine);
    1376               6 :             if (nLen == 0 || EQUALN("EXP ", pszLine, 4))
    1377               3 :                 continue;  /* Skip empty and EXP header lines */
    1378               4 :             else if ( (nLen == 79 || nLen == 80) &&
    1379               1 :                       strchr(pszLine, '~') != NULL )
    1380                 :             {
    1381                 :                 /* Looks like a compressed file. Just log an error and return.
    1382                 :                  * The caller should reject the file because it contains 0 
    1383                 :                  * sections 
    1384                 :                  */
    1385               1 :                 CPLError(CE_Failure, CPLE_OpenFailed, 
    1386                 :                          "This looks like a compressed E00 file and cannot be "
    1387                 :                          "processed directly. You may need to uncompress it "
    1388                 :                          "first using the E00compr library or the e00conv "
    1389                 :                          "program." );
    1390               1 :                 return;  
    1391                 :             }
    1392                 : 
    1393                 :             /* All seems fine. Continue with normal processing */
    1394               2 :             bFirstLine = FALSE;
    1395                 :         }
    1396                 : 
    1397             224 :         obj = _AVCE00ReadNextLineE00(psRead, pszLine);
    1398                 : 
    1399             224 :         if (obj)
    1400                 :         {
    1401              68 :             pszName = 0;
    1402              68 :             switch (psInfo->eFileType)
    1403                 :             {
    1404                 :             case AVCFileARC:
    1405              14 :                 pszName = "ARC";
    1406              14 :                 break;
    1407                 : 
    1408                 :             case AVCFilePAL:
    1409               0 :                 pszName = "PAL";
    1410               0 :                 break;
    1411                 : 
    1412                 :             case AVCFileCNT:
    1413               0 :                 pszName = "CNT";
    1414               0 :                 break;
    1415                 : 
    1416                 :             case AVCFileLAB:
    1417               4 :                 pszName = "LAB";
    1418               4 :                 break;
    1419                 : 
    1420                 :             case AVCFileRPL:
    1421               0 :                 pszName = "RPL";
    1422               0 :                 break;
    1423                 : 
    1424                 :             case AVCFileTXT:
    1425               0 :                 pszName = "TXT";
    1426               0 :                 break;
    1427                 : 
    1428                 :             case AVCFileTX6:
    1429               0 :                 pszName = "TX6";
    1430               0 :                 break;
    1431                 : 
    1432                 :             case AVCFilePRJ:
    1433               2 :                 pszName = "PRJ";
    1434               2 :                 break;
    1435                 : 
    1436                 :             case AVCFileTABLE:
    1437              28 :                 pszName = psInfo->hdr.psTableDef->szTableName;
    1438                 :                 break;
    1439                 : 
    1440                 :             default:
    1441                 :                 break;
    1442                 :             }
    1443                 : 
    1444             154 :             if (pszName && (psRead->numSections == 0 ||
    1445              46 :                     psRead->pasSections[iSect].eType != psInfo->eFileType ||
    1446              40 :                     !EQUAL(pszName, psRead->pasSections[iSect].pszName)))
    1447                 :             {
    1448              14 :                 iSect = _AVCIncreaseSectionsArray(&(psRead->pasSections), 
    1449                 :                                       &(psRead->numSections), 1);
    1450                 : 
    1451              14 :                 psRead->pasSections[iSect].eType = psInfo->eFileType;
    1452                 :                 /* psRead->pasSections[iSect].pszName = CPLStrdup(psRead->pszCoverName); */
    1453              14 :                 psRead->pasSections[iSect].pszName = CPLStrdup(pszName);
    1454              14 :                 psRead->pasSections[iSect].pszFilename = CPLStrdup(psRead->pszCoverPath);
    1455              14 :                 psRead->pasSections[iSect].nLineNum = psInfo->nStartLineNum;
    1456              14 :                 psRead->pasSections[iSect].nFeatureCount = 0;
    1457                 :             }
    1458                 : 
    1459              68 :             if (pszName && psRead->numSections)
    1460                 :             {
    1461                 :                 /* increase feature count for current layer */
    1462              48 :                 ++psRead->pasSections[iSect].nFeatureCount;
    1463                 :             }
    1464                 :         }
    1465                 :     }
    1466                 : }
    1467                 : 
    1468                 : /**********************************************************************
    1469                 :  *                         _AVCE00ReadNextTableLine()
    1470                 :  *
    1471                 :  * Return the next line of the E00 representation of a info table.
    1472                 :  *
    1473                 :  * This function is used by AVCE00ReadNextLine() to generate table
    1474                 :  * output... it should never be called directly.
    1475                 :  **********************************************************************/
    1476               0 : static const char *_AVCE00ReadNextTableLine(AVCE00ReadPtr psInfo)
    1477                 : {
    1478               0 :     const char *pszLine = NULL;
    1479                 :     AVCE00Section *psSect;
    1480                 : 
    1481               0 :     psSect = &(psInfo->pasSections[psInfo->iCurSection]);
    1482                 : 
    1483               0 :     CPLAssert(psSect->eType == AVCFileTABLE);
    1484                 : 
    1485               0 :     if (psInfo->iCurStep == AVC_GEN_NOTSTARTED)
    1486                 :     {
    1487                 :         /*---------------------------------------------------------
    1488                 :          * Open table and start returning header
    1489                 :          *--------------------------------------------------------*/
    1490               0 :         if (psInfo->eCoverType == AVCCoverPC ||
    1491               0 :             psInfo->eCoverType == AVCCoverPC2)
    1492                 :         {
    1493                 :             /*---------------------------------------------------------
    1494                 :              * PC Arc/Info: We pass the DBF table's full filename + the
    1495                 :              * Arc/Info table name (for E00 header)
    1496                 :              *--------------------------------------------------------*/
    1497                 :             char *pszFname;
    1498               0 :             pszFname = CPLStrdup(CPLSPrintf("%s%s", psInfo->pszInfoPath,
    1499                 :                                                     psSect->pszFilename ));
    1500               0 :             psInfo->hFile = AVCBinReadOpen(pszFname, psSect->pszName, 
    1501                 :                                            psInfo->eCoverType, psSect->eType,
    1502                 :                                            psInfo->psDBCSInfo);
    1503               0 :             CPLFree(pszFname);
    1504                 :         }
    1505                 :         else
    1506                 :         {
    1507                 :             /*---------------------------------------------------------
    1508                 :              * AVCCoverV7 and AVCCoverWeird: 
    1509                 :              * We pass the INFO dir's path, and the Arc/Info table name
    1510                 :              * will be searched in the arc.dir
    1511                 :              *--------------------------------------------------------*/
    1512               0 :             psInfo->hFile = AVCBinReadOpen(psInfo->pszInfoPath, 
    1513               0 :                                            psSect->pszName, 
    1514                 :                                            psInfo->eCoverType, psSect->eType,
    1515                 :                                            psInfo->psDBCSInfo);
    1516                 :         }
    1517                 : 
    1518                 : 
    1519                 :         /* For some reason the file could not be opened... abort now.
    1520                 :          * An error message should have already been produced by 
    1521                 :          * AVCBinReadOpen()
    1522                 :          */
    1523               0 :         if (psInfo->hFile == NULL)
    1524               0 :             return NULL;
    1525                 : 
    1526               0 :         psInfo->iCurStep = AVC_GEN_TABLEHEADER;
    1527                 : 
    1528               0 :         pszLine = AVCE00GenTableHdr(psInfo->hGenInfo,
    1529               0 :                                     psInfo->hFile->hdr.psTableDef,
    1530                 :                                     FALSE);
    1531                 :     }
    1532                 :         
    1533               0 :     if (pszLine == NULL &&
    1534               0 :         psInfo->iCurStep == AVC_GEN_TABLEHEADER)
    1535                 :     {
    1536                 :         /*---------------------------------------------------------
    1537                 :          * Continue table header
    1538                 :          *--------------------------------------------------------*/
    1539               0 :         pszLine = AVCE00GenTableHdr(psInfo->hGenInfo,
    1540               0 :                                     psInfo->hFile->hdr.psTableDef,
    1541                 :                                     TRUE);
    1542                 : 
    1543               0 :         if (pszLine == NULL)
    1544                 :         {
    1545                 :             /* Finished with table header... time to proceed with the
    1546                 :              * table data.
    1547                 :              * Reset the AVCE00GenInfo struct. so that it returns NULL,
    1548                 :              * which will force reading of the first record from the 
    1549                 :              * file on the next call to AVCE00ReadNextLine()
    1550                 :              */
    1551               0 :             AVCE00GenReset(psInfo->hGenInfo);
    1552               0 :             psInfo->iCurStep = AVC_GEN_TABLEDATA;
    1553                 :         }
    1554                 : 
    1555                 :     }
    1556                 : 
    1557               0 :     if (pszLine == NULL &&
    1558               0 :         psInfo->iCurStep == AVC_GEN_TABLEDATA)
    1559                 :     {
    1560                 :         /*---------------------------------------------------------
    1561                 :          * Continue with records of data
    1562                 :          *--------------------------------------------------------*/
    1563                 : 
    1564               0 :         pszLine = AVCE00GenTableRec(psInfo->hGenInfo, 
    1565               0 :                                     psInfo->hFile->hdr.psTableDef->numFields,
    1566               0 :                                     psInfo->hFile->hdr.psTableDef->pasFieldDef,
    1567               0 :                                     psInfo->hFile->cur.pasFields,
    1568                 :                                     TRUE);
    1569                 : 
    1570               0 :         if (pszLine == NULL)
    1571                 :         {
    1572                 :             /* Current record is finished generating... we need to read 
    1573                 :              * a new one from the file.
    1574                 :              */
    1575               0 :             if (AVCBinReadNextObject(psInfo->hFile) != NULL)
    1576                 :             {
    1577               0 :                 pszLine = AVCE00GenTableRec(psInfo->hGenInfo, 
    1578               0 :                                     psInfo->hFile->hdr.psTableDef->numFields,
    1579               0 :                                     psInfo->hFile->hdr.psTableDef->pasFieldDef,
    1580               0 :                                     psInfo->hFile->cur.pasFields,
    1581                 :                                     FALSE);
    1582                 :             }            
    1583                 : 
    1584                 :         }
    1585                 :     }
    1586                 : 
    1587               0 :     if (pszLine == NULL)
    1588                 :     {
    1589                 :         /*---------------------------------------------------------
    1590                 :          * No more lines to output for this table ... Close it.
    1591                 :          *--------------------------------------------------------*/
    1592               0 :         AVCBinReadClose(psInfo->hFile);
    1593               0 :         psInfo->hFile = NULL;
    1594                 : 
    1595                 :         /*---------------------------------------------------------
    1596                 :          * And now proceed to the next section...
    1597                 :          * OK, I don't really like recursivity either... but it was
    1598                 :          * the simplest way to do this, and anyways we should never
    1599                 :          * have more than one level of recursivity.
    1600                 :          *--------------------------------------------------------*/
    1601               0 :         if (psInfo->bReadAllSections)
    1602               0 :             psInfo->iCurSection++;
    1603                 :         else
    1604               0 :             psInfo->iCurSection = psInfo->numSections;
    1605               0 :         psInfo->iCurStep = AVC_GEN_NOTSTARTED;
    1606                 : 
    1607               0 :         pszLine = AVCE00ReadNextLine(psInfo);
    1608                 :     }
    1609                 : 
    1610                 :     /*-----------------------------------------------------------------
    1611                 :      * Check for errors... if any error happened, tehn return NULL
    1612                 :      *----------------------------------------------------------------*/
    1613               0 :     if (CPLGetLastErrorNo() != 0)
    1614                 :     {
    1615               0 :         pszLine = NULL;
    1616                 :     }
    1617                 : 
    1618               0 :     return pszLine;
    1619                 : }
    1620                 : 
    1621                 : 
    1622                 : /**********************************************************************
    1623                 :  *                          AVCE00ReadNextLine()
    1624                 :  *
    1625                 :  * Returns the next line of the E00 representation of the coverage
    1626                 :  * or NULL when there are no more lines to generate, or if an error happened.
    1627                 :  * The returned line is a null-terminated string, and it does not
    1628                 :  * include a newline character.
    1629                 :  *
    1630                 :  * Call CPLGetLastErrorNo() after calling AVCE00ReadNextLine() to 
    1631                 :  * make sure that the line was generated succesfully.
    1632                 :  *
    1633                 :  * Note that AVCE00ReadNextLine() returns a reference to an
    1634                 :  * internal buffer whose contents will
    1635                 :  * be valid only until the next call to this function.  The caller should
    1636                 :  * not attempt to free() the returned pointer.
    1637                 :  **********************************************************************/
    1638               0 : const char *AVCE00ReadNextLine(AVCE00ReadPtr psInfo)
    1639                 : {
    1640               0 :     const char *pszLine = NULL;
    1641                 :     AVCE00Section *psSect;
    1642                 : 
    1643               0 :     CPLErrorReset();
    1644                 : 
    1645                 :     /*-----------------------------------------------------------------
    1646                 :      * Check if we have finished generating E00 output
    1647                 :      *----------------------------------------------------------------*/
    1648               0 :     if (psInfo->iCurSection >= psInfo->numSections)
    1649               0 :         return NULL;
    1650                 : 
    1651               0 :     psSect = &(psInfo->pasSections[psInfo->iCurSection]);
    1652                 : 
    1653                 :     /*-----------------------------------------------------------------
    1654                 :      * For simplicity, the generation of table output is in a separate
    1655                 :      * function.
    1656                 :      *----------------------------------------------------------------*/
    1657               0 :     if (psSect->eType == AVCFileTABLE)
    1658                 :     {
    1659               0 :         return _AVCE00ReadNextTableLine(psInfo);
    1660                 :     }
    1661                 : 
    1662               0 :     if (psSect->eType == AVCFileUnknown)
    1663                 :     {
    1664                 :     /*-----------------------------------------------------------------
    1665                 :      * Section not attached to any file, used to hold header lines
    1666                 :      * or section separators, etc... just return the line directly and
    1667                 :      * move pointer to the next section.
    1668                 :      *----------------------------------------------------------------*/
    1669               0 :         pszLine = psSect->pszName;
    1670               0 :         if (psInfo->bReadAllSections)
    1671               0 :             psInfo->iCurSection++;
    1672                 :         else
    1673               0 :             psInfo->iCurSection = psInfo->numSections;
    1674               0 :         psInfo->iCurStep = AVC_GEN_NOTSTARTED;
    1675                 :     }
    1676                 :     /*=================================================================
    1677                 :      *              ARC, PAL, CNT, LAB, TOL and TXT
    1678                 :      *================================================================*/
    1679               0 :     else if (psInfo->iCurStep == AVC_GEN_NOTSTARTED &&
    1680               0 :              (psSect->eType == AVCFileARC ||
    1681               0 :               psSect->eType == AVCFilePAL ||
    1682               0 :               psSect->eType == AVCFileRPL ||
    1683               0 :               psSect->eType == AVCFileCNT ||
    1684               0 :               psSect->eType == AVCFileLAB ||
    1685               0 :               psSect->eType == AVCFileTOL ||
    1686               0 :               psSect->eType == AVCFileTXT ||
    1687               0 :               psSect->eType == AVCFileTX6 ||
    1688               0 :               psSect->eType == AVCFileRXP   ) )
    1689                 :     {
    1690                 :     /*-----------------------------------------------------------------
    1691                 :      * Start processing of an ARC, PAL, CNT, LAB or TOL section:
    1692                 :      *   Open the file, get ready to read the first object from the 
    1693                 :      *   file, and return the header line.
    1694                 :      *  If the file fails to open then we will return NULL.
    1695                 :      *----------------------------------------------------------------*/
    1696               0 :         psInfo->hFile = AVCBinReadOpen(psInfo->pszCoverPath, 
    1697               0 :                                        psSect->pszFilename, 
    1698                 :                                        psInfo->eCoverType, psSect->eType,
    1699                 :                                        psInfo->psDBCSInfo);
    1700                 : 
    1701                 :         /*-------------------------------------------------------------
    1702                 :          * For some reason the file could not be opened... abort now.
    1703                 :          * An error message should have already been produced by 
    1704                 :          * AVCBinReadOpen()
    1705                 :          *------------------------------------------------------------*/
    1706               0 :         if (psInfo->hFile == NULL)
    1707               0 :             return NULL;
    1708                 : 
    1709               0 :         pszLine = AVCE00GenStartSection(psInfo->hGenInfo, 
    1710               0 :                                         psSect->eType, psSect->pszName);
    1711                 : 
    1712                 :         /*-------------------------------------------------------------
    1713                 :          * Reset the AVCE00GenInfo struct. so that it returns NULL,
    1714                 :          * which will force reading of the first object from the 
    1715                 :          * file on the next call to AVCE00ReadNextLine()
    1716                 :          *------------------------------------------------------------*/
    1717               0 :         AVCE00GenReset(psInfo->hGenInfo);
    1718               0 :         psInfo->iCurStep = AVC_GEN_DATA;
    1719                 :     }
    1720               0 :     else if (psInfo->iCurStep == AVC_GEN_DATA &&
    1721               0 :              (psSect->eType == AVCFileARC ||
    1722               0 :               psSect->eType == AVCFilePAL ||
    1723               0 :               psSect->eType == AVCFileRPL ||
    1724               0 :               psSect->eType == AVCFileCNT ||
    1725               0 :               psSect->eType == AVCFileLAB ||
    1726               0 :               psSect->eType == AVCFileTOL ||
    1727               0 :               psSect->eType == AVCFileTXT ||
    1728               0 :               psSect->eType == AVCFileTX6 ||
    1729               0 :               psSect->eType == AVCFileRXP    ) )
    1730                 :     {
    1731                 :     /*-----------------------------------------------------------------
    1732                 :      * Return the next line of an ARC/PAL/CNT/TOL/TXT object... 
    1733                 :      * if necessary, read the next object from the binary file.
    1734                 :      *----------------------------------------------------------------*/
    1735               0 :         pszLine = AVCE00GenObject(psInfo->hGenInfo, 
    1736                 :                                   psSect->eType,
    1737               0 :                   (psSect->eType==AVCFileARC?(void*)(psInfo->hFile->cur.psArc):
    1738               0 :                    psSect->eType==AVCFilePAL?(void*)(psInfo->hFile->cur.psPal):
    1739               0 :                    psSect->eType==AVCFileRPL?(void*)(psInfo->hFile->cur.psPal):
    1740               0 :                    psSect->eType==AVCFileCNT?(void*)(psInfo->hFile->cur.psCnt):
    1741               0 :                    psSect->eType==AVCFileLAB?(void*)(psInfo->hFile->cur.psLab):
    1742               0 :                    psSect->eType==AVCFileTOL?(void*)(psInfo->hFile->cur.psTol):
    1743               0 :                    psSect->eType==AVCFileTXT?(void*)(psInfo->hFile->cur.psTxt):
    1744               0 :                    psSect->eType==AVCFileTX6?(void*)(psInfo->hFile->cur.psTxt):
    1745               0 :                    psSect->eType==AVCFileRXP?(void*)(psInfo->hFile->cur.psRxp):
    1746                 :                    NULL),
    1747                 :                                   TRUE);
    1748               0 :         if (pszLine == NULL)
    1749                 :         {
    1750                 :             /*---------------------------------------------------------
    1751                 :              * Current object is finished generating... we need to read 
    1752                 :              * a new one from the file.
    1753                 :              *--------------------------------------------------------*/
    1754               0 :             if (AVCBinReadNextObject(psInfo->hFile) != NULL)
    1755                 :             {
    1756               0 :                 pszLine = AVCE00GenObject(psInfo->hGenInfo, 
    1757                 :                                           psSect->eType,
    1758               0 :                   (psSect->eType==AVCFileARC?(void*)(psInfo->hFile->cur.psArc):
    1759               0 :                    psSect->eType==AVCFilePAL?(void*)(psInfo->hFile->cur.psPal):
    1760               0 :                    psSect->eType==AVCFileRPL?(void*)(psInfo->hFile->cur.psPal):
    1761               0 :                    psSect->eType==AVCFileCNT?(void*)(psInfo->hFile->cur.psCnt):
    1762               0 :                    psSect->eType==AVCFileLAB?(void*)(psInfo->hFile->cur.psLab):
    1763               0 :                    psSect->eType==AVCFileTOL?(void*)(psInfo->hFile->cur.psTol):
    1764               0 :                    psSect->eType==AVCFileTXT?(void*)(psInfo->hFile->cur.psTxt):
    1765               0 :                    psSect->eType==AVCFileTX6?(void*)(psInfo->hFile->cur.psTxt):
    1766               0 :                    psSect->eType==AVCFileRXP?(void*)(psInfo->hFile->cur.psRxp):
    1767                 :                    NULL),
    1768                 :                                           FALSE);
    1769                 :             }            
    1770                 :         }
    1771               0 :         if (pszLine == NULL)
    1772                 :         {
    1773                 :             /*---------------------------------------------------------
    1774                 :              * Still NULL ??? This means we finished reading this file...
    1775                 :              * Start returning the "end of section" line(s)...
    1776                 :              *--------------------------------------------------------*/
    1777               0 :             AVCBinReadClose(psInfo->hFile);
    1778               0 :             psInfo->hFile = NULL;
    1779               0 :             psInfo->iCurStep = AVC_GEN_ENDSECTION;
    1780               0 :             pszLine = AVCE00GenEndSection(psInfo->hGenInfo, psSect->eType,
    1781                 :                                           FALSE);
    1782                 :         }
    1783                 :     }
    1784                 :     /*=================================================================
    1785                 :      *                          PRJ
    1786                 :      *================================================================*/
    1787               0 :     else if (psInfo->iCurStep == AVC_GEN_NOTSTARTED &&
    1788               0 :               psSect->eType == AVCFilePRJ   )
    1789                 :     {
    1790                 :         /*-------------------------------------------------------------
    1791                 :          * Start processing of PRJ section... return first header line.
    1792                 :          *------------------------------------------------------------*/
    1793               0 :         pszLine = AVCE00GenStartSection(psInfo->hGenInfo, 
    1794                 :                                         psSect->eType, NULL);
    1795                 : 
    1796               0 :         psInfo->hFile = NULL;
    1797               0 :         psInfo->iCurStep = AVC_GEN_DATA;
    1798                 :     }
    1799               0 :     else if (psInfo->iCurStep == AVC_GEN_DATA &&
    1800               0 :              psSect->eType == AVCFilePRJ  )
    1801                 :     {
    1802                 :         /*-------------------------------------------------------------
    1803                 :          * Return the next line of a PRJ section
    1804                 :          *------------------------------------------------------------*/
    1805               0 :         if (psInfo->hFile == NULL)
    1806                 :         {
    1807                 :             /*---------------------------------------------------------
    1808                 :              * File has not been read yet...
    1809                 :              * Read the PRJ file, and return the first PRJ line.
    1810                 :              *--------------------------------------------------------*/
    1811               0 :             psInfo->hFile = AVCBinReadOpen(psInfo->pszCoverPath, 
    1812               0 :                                            psSect->pszFilename, 
    1813                 :                                            psInfo->eCoverType, psSect->eType,
    1814                 :                                            psInfo->psDBCSInfo);
    1815                 : 
    1816                 :             /* For some reason the file could not be opened... abort now.
    1817                 :              * An error message should have already been produced by 
    1818                 :              * AVCBinReadOpen()
    1819                 :              */
    1820               0 :             if (psInfo->hFile == NULL)
    1821               0 :                 return NULL;
    1822                 : 
    1823               0 :             pszLine = AVCE00GenPrj(psInfo->hGenInfo, 
    1824               0 :                                    psInfo->hFile->cur.papszPrj, FALSE);
    1825                 :         }
    1826                 :         else
    1827                 :         {
    1828                 :             /*---------------------------------------------------------
    1829                 :              * Generate the next line of output.
    1830                 :              *--------------------------------------------------------*/
    1831               0 :             pszLine = AVCE00GenPrj(psInfo->hGenInfo, 
    1832               0 :                                    psInfo->hFile->cur.papszPrj, TRUE);
    1833                 :         }
    1834                 : 
    1835               0 :         if (pszLine == NULL)
    1836                 :         {
    1837                 :             /*---------------------------------------------------------
    1838                 :              * Still NULL ??? This means we finished generating this PRJ 
    1839                 :              * section...
    1840                 :              * Start returning the "end of section" line(s)...
    1841                 :              *--------------------------------------------------------*/
    1842               0 :             AVCBinReadClose(psInfo->hFile);
    1843               0 :             psInfo->hFile = NULL;
    1844               0 :             psInfo->iCurStep = AVC_GEN_ENDSECTION;
    1845               0 :             pszLine = AVCE00GenEndSection(psInfo->hGenInfo, psSect->eType,
    1846                 :                                           FALSE);
    1847                 :         }
    1848                 :     }
    1849               0 :     else if (psInfo->iCurStep != AVC_GEN_ENDSECTION)
    1850                 :     {
    1851                 :         /* We should never get here! */
    1852               0 :         CPLAssert(FALSE);
    1853                 :     }
    1854                 : 
    1855                 : 
    1856                 :     /*=================================================================
    1857                 :      *                End of section, for all files
    1858                 :      *================================================================*/
    1859                 : 
    1860                 :     /*-----------------------------------------------------------------
    1861                 :      * Finished processing of an ARC, PAL, CNT, LAB, TOL, PRJ file ...
    1862                 :      * continue returning the "end of section" line(s), and move the pointer
    1863                 :      * to the next section once we're done.
    1864                 :      *----------------------------------------------------------------*/
    1865               0 :     if (psInfo->iCurStep == AVC_GEN_ENDSECTION && pszLine == NULL)
    1866                 :     {
    1867               0 :         pszLine = AVCE00GenEndSection(psInfo->hGenInfo, psSect->eType, TRUE);
    1868                 : 
    1869               0 :         if (pszLine == NULL)
    1870                 :         {
    1871                 :             /*---------------------------------------------------------
    1872                 :              * Finished returning the last lines of the section...
    1873                 :              * proceed to the next section...
    1874                 :              * OK, I don't really like recursivity either... but it was
    1875                 :              * the simplest way to do this, and anyways we should never
    1876                 :              * have more than one level of recursivity.
    1877                 :              *--------------------------------------------------------*/
    1878               0 :             if (psInfo->bReadAllSections)
    1879               0 :                 psInfo->iCurSection++;
    1880                 :             else
    1881               0 :                 psInfo->iCurSection = psInfo->numSections;
    1882               0 :             psInfo->iCurStep = AVC_GEN_NOTSTARTED;
    1883                 : 
    1884               0 :             pszLine = AVCE00ReadNextLine(psInfo);
    1885                 :         }
    1886                 :     }
    1887                 : 
    1888               0 :     return pszLine;
    1889                 : }
    1890                 : 
    1891                 : 
    1892                 : 
    1893                 : /**********************************************************************
    1894                 :  *                         AVCE00ReadSectionsList()
    1895                 :  *
    1896                 :  * Returns an array of AVCE00Section structures that describe the
    1897                 :  * squeleton of the whole coverage.  The value of *numSect will be
    1898                 :  * set to the number of sections in the array.
    1899                 :  *
    1900                 :  * You can scan the returned array, and use AVCE00ReadGotoSection() to move
    1901                 :  * the read pointer directly to the beginning of a given section
    1902                 :  * of the file.
    1903                 :  *
    1904                 :  * Sections of type AVCFileUnknown correspond to lines in the
    1905                 :  * E00 output that are not directly linked to any coverage file, like 
    1906                 :  * the "EXP 0" line, the "IFO X", "SIN X", etc.
    1907                 :  *
    1908                 :  * THE RETURNED ARRAY IS AN INTERNAL STRUCTURE AND SHOULD NOT BE
    1909                 :  * MODIFIED OR FREED BY THE CALLER... its contents will be valid
    1910                 :  * for as long as the coverage will remain open.
    1911                 :  **********************************************************************/
    1912               0 : AVCE00Section *AVCE00ReadSectionsList(AVCE00ReadPtr psInfo, int *numSect)
    1913                 : {
    1914               0 :     CPLErrorReset();
    1915                 : 
    1916               0 :     *numSect = psInfo->numSections;
    1917               0 :     return psInfo->pasSections;
    1918                 : }
    1919                 : 
    1920                 : /**********************************************************************
    1921                 :  *                         AVCE00ReadGotoSection()
    1922                 :  *
    1923                 :  * Move the read pointer to the E00 section (coverage file) described in 
    1924                 :  * the psSect structure.  Call AVCE00ReadSectionsList() to get the list of
    1925                 :  * sections for the current coverage.
    1926                 :  *
    1927                 :  * if bContinue=TRUE, then reading will automatically continue with the
    1928                 :  * next sections of the file once the requested section is finished.
    1929                 :  * Otherwise, if bContinue=FALSE then reading will stop at the end
    1930                 :  * of this section (i.e. AVCE00ReadNextLine() will return NULL when 
    1931                 :  * it reaches the end of this section)
    1932                 :  *
    1933                 :  * Sections of type AVCFileUnknown returned by AVCE00ReadSectionsList()
    1934                 :  * correspond to lines in the E00 output that are not directly linked
    1935                 :  * to any coverage file, like the "EXP 0" line, the "IFO X", "SIN X", etc.
    1936                 :  * You can jump to these sections or any other one without problems.
    1937                 :  *
    1938                 :  * This function returns 0 on success or -1 on error.
    1939                 :  **********************************************************************/
    1940               0 : int AVCE00ReadGotoSection(AVCE00ReadPtr psInfo, AVCE00Section *psSect,
    1941                 :                           GBool bContinue)
    1942                 : {
    1943                 :     int     iSect;
    1944               0 :     GBool   bFound = FALSE;
    1945                 : 
    1946               0 :     CPLErrorReset();
    1947                 : 
    1948                 :     /*-----------------------------------------------------------------
    1949                 :      * Locate the requested section in the array.
    1950                 :      *----------------------------------------------------------------*/
    1951               0 :     for(iSect=0; iSect<psInfo->numSections; iSect++)
    1952                 :     {
    1953               0 :         if (psInfo->pasSections[iSect].eType == psSect->eType &&
    1954               0 :             EQUAL(psInfo->pasSections[iSect].pszName, psSect->pszName))
    1955                 :         {
    1956               0 :             bFound = TRUE;
    1957               0 :             break;
    1958                 :         }
    1959                 :     }
    1960                 : 
    1961                 :     /*-----------------------------------------------------------------
    1962                 :      * Not found ... generate an error...
    1963                 :      *----------------------------------------------------------------*/
    1964               0 :     if (!bFound)
    1965                 :     {
    1966               0 :         CPLError(CE_Failure, CPLE_IllegalArg, 
    1967                 :                  "Requested E00 section does not exist!");
    1968               0 :         return -1;
    1969                 :     }
    1970                 : 
    1971                 :     /*-----------------------------------------------------------------
    1972                 :      * Found it ... close current section and get ready to read 
    1973                 :      * the new one.
    1974                 :      *----------------------------------------------------------------*/
    1975               0 :     if (psInfo->hFile)
    1976                 :     {
    1977               0 :         AVCBinReadClose(psInfo->hFile);
    1978               0 :         psInfo->hFile = NULL;
    1979                 :     }
    1980                 : 
    1981               0 :     psInfo->bReadAllSections = bContinue;
    1982               0 :     psInfo->iCurSection = iSect;
    1983               0 :     psInfo->iCurStep = AVC_GEN_NOTSTARTED;
    1984                 : 
    1985               0 :     return 0;
    1986                 : }
    1987                 : 
    1988                 : /**********************************************************************
    1989                 :  *                         AVCE00ReadRewind()
    1990                 :  *
    1991                 :  * Rewinds the AVCE00ReadPtr just like the stdio rewind() 
    1992                 :  * function would do if you were reading an ASCII E00 file.
    1993                 :  *
    1994                 :  * Returns 0 on success or -1 on error.
    1995                 :  **********************************************************************/
    1996               0 : int  AVCE00ReadRewind(AVCE00ReadPtr psInfo)
    1997                 : {
    1998               0 :     CPLErrorReset();
    1999                 : 
    2000               0 :     return AVCE00ReadGotoSection(psInfo, &(psInfo->pasSections[0]), TRUE);
    2001                 : }
    2002                 : 
    2003                 : /**********************************************************************
    2004                 :  *                         AVCE00ReadRewindE00()
    2005                 :  *
    2006                 :  * Rewinds the AVCE00ReadE00Ptr just like the stdio rewind() 
    2007                 :  * function would do if you were reading an ASCII E00 file.
    2008                 :  *
    2009                 :  * Returns 0 on success or -1 on error.
    2010                 :  **********************************************************************/
    2011               5 : int  AVCE00ReadRewindE00(AVCE00ReadE00Ptr psRead)
    2012                 : {
    2013               5 :     CPLErrorReset();
    2014                 : 
    2015               5 :     psRead->bReadAllSections = TRUE;
    2016               5 :     psRead->eCurFileType = AVCFileUnknown;
    2017                 : 
    2018               5 :     psRead->hParseInfo->nCurLineNum = 0;
    2019               5 :     psRead->hParseInfo->nStartLineNum = 0;
    2020               5 :     psRead->hParseInfo->bForceEndOfSection = TRUE;
    2021               5 :     psRead->hParseInfo->eSuperSectionType = AVCFileUnknown;
    2022               5 :     AVCE00ParseSectionEnd(psRead->hParseInfo, NULL, 1);
    2023                 : 
    2024               5 :     return fseek(psRead->hFile, 0, SEEK_SET);
    2025                 : }
    2026                 : 
    2027                 : /**********************************************************************
    2028                 :  *                        _AVCE00ReadSeekE00()
    2029                 :  *
    2030                 :  * Seeks to a new location in the E00 file, keeping parse state
    2031                 :  * appropriately.
    2032                 :  *
    2033                 :  * NOTE: This is a pretty slow implementation.
    2034                 :  * NOTE: The SEEK_END is not implemented.
    2035                 :  *
    2036                 :  * Returns 0 on success or -1 on error.
    2037                 :  **********************************************************************/
    2038               3 : static int _AVCE00ReadSeekE00(AVCE00ReadE00Ptr psRead, int nOffset,
    2039                 :         int nWhence)
    2040                 : {
    2041                 :     const char *pszLine;
    2042                 :     void       *obj;
    2043                 : 
    2044               3 :     switch (nWhence)
    2045                 :     {
    2046                 :     case SEEK_CUR:
    2047               0 :         break;
    2048                 : 
    2049                 :     case SEEK_SET:
    2050               3 :         AVCE00ReadRewindE00(psRead);
    2051               3 :         break;
    2052                 : 
    2053                 :     default:
    2054               0 :         CPLAssert(nWhence == SEEK_CUR || nWhence == SEEK_SET);
    2055                 :         break;
    2056                 :     }
    2057                 : 
    2058              15 :     while (nOffset-- &&
    2059               3 :             CPLGetLastErrorNo() == 0 &&
    2060               3 :             (pszLine = CPLReadLine(psRead->hFile) ) != NULL )
    2061                 :     {
    2062               3 :         obj = _AVCE00ReadNextLineE00(psRead, pszLine);
    2063                 :     }
    2064                 : 
    2065               3 :     return nOffset ? -1 : 0;
    2066                 : }
    2067                 : 
    2068                 : /**********************************************************************
    2069                 :  *                      AVCE00ReadNextObjectE00()
    2070                 :  *
    2071                 :  * Returns the next object in an E00 file or NULL when there are no
    2072                 :  * more objects, or if an error happened.  The object type can be
    2073                 :  * determined via the eCurFileType attribute of the
    2074                 :  * AVCE00ReadE00Ptr object.
    2075                 :  *
    2076                 :  * Note that AVCE00ReadNextLine() returns a reference to an internal
    2077                 :  * buffer whose contents will be valid only until the next call to
    2078                 :  * this function.  The caller should not attempt to free() the
    2079                 :  * returned pointer.
    2080                 :  **********************************************************************/
    2081               9 : void *AVCE00ReadNextObjectE00(AVCE00ReadE00Ptr psRead)
    2082                 : {
    2083                 :     const char *pszLine;
    2084               9 :     void       *obj = NULL;
    2085                 : 
    2086                 :     do
    2087                 :     {
    2088              23 :         pszLine = CPLReadLine(psRead->hFile);
    2089              23 :         if (pszLine == 0)
    2090               0 :             break;
    2091              23 :         obj = _AVCE00ReadNextLineE00(psRead, pszLine);
    2092                 :     }
    2093                 :     while (obj == NULL &&
    2094              15 :             (psRead->bReadAllSections ||
    2095              15 :              psRead->eCurFileType != AVCFileUnknown) &&
    2096              53 :             CPLGetLastErrorNo() == 0);
    2097               9 :     return obj;
    2098                 : }
    2099                 : 
    2100                 : /**********************************************************************
    2101                 :  *                         AVCE00ReadSectionsListE00()
    2102                 :  *
    2103                 :  * Returns an array of AVCE00Section structures that describe the
    2104                 :  * sections in the E00 file.  The value of *numSect will be set to the
    2105                 :  * number of sections in the array.
    2106                 :  *
    2107                 :  * You can scan the returned array, and use AVCE00ReadGotoSectionE00()
    2108                 :  * to move the read pointer directly to the beginning of a given
    2109                 :  * section of the file.
    2110                 :  *
    2111                 :  * THE RETURNED ARRAY IS AN INTERNAL STRUCTURE AND SHOULD NOT BE
    2112                 :  * MODIFIED OR FREED BY THE CALLER... its contents will be valid
    2113                 :  * for as long as the coverage will remain open.
    2114                 :  **********************************************************************/
    2115               0 : AVCE00Section *AVCE00ReadSectionsListE00(AVCE00ReadE00Ptr psRead,
    2116                 :         int *numSect)
    2117                 : {
    2118               0 :     CPLErrorReset();
    2119                 : 
    2120               0 :     *numSect = psRead->numSections;
    2121               0 :     return psRead->pasSections;
    2122                 : }
    2123                 : 
    2124                 : /**********************************************************************
    2125                 :  *                         AVCE00ReadGotoSectionE00()
    2126                 :  *
    2127                 :  * Move the read pointer to the E00 section described in the psSect
    2128                 :  * structure.  Call AVCE00ReadSectionsListE00() to get the list of
    2129                 :  * sections for the current coverage.
    2130                 :  *
    2131                 :  * If bContinue is TRUE, then reading will automatically continue with
    2132                 :  * the next section of the file once the requested section is finished.
    2133                 :  * Otherwise, if bContinue is FALSE then reading will stop at the end
    2134                 :  * of this section (i.e. AVCE00ReadNextObjectE00() will return NULL
    2135                 :  * when the end of this section is reached)
    2136                 :  *
    2137                 :  * This function returns 0 on success or -1 on error.
    2138                 :  **********************************************************************/
    2139               3 : int AVCE00ReadGotoSectionE00(AVCE00ReadE00Ptr psRead,
    2140                 :         AVCE00Section *psSect, GBool bContinue)
    2141                 : {
    2142                 :     int     iSect;
    2143               3 :     GBool   bFound = FALSE;
    2144                 : 
    2145               3 :     CPLErrorReset();
    2146                 : 
    2147                 :     /*-----------------------------------------------------------------
    2148                 :      * Locate the requested section in the array.
    2149                 :      *----------------------------------------------------------------*/
    2150               3 :     for(iSect=0; iSect<psRead->numSections; iSect++)
    2151                 :     {
    2152               6 :         if (psRead->pasSections[iSect].eType == psSect->eType &&
    2153               3 :             EQUAL(psRead->pasSections[iSect].pszName, psSect->pszName))
    2154                 :         {
    2155               3 :             bFound = TRUE;
    2156               3 :             break;
    2157                 :         }
    2158                 :     }
    2159                 : 
    2160                 :     /*-----------------------------------------------------------------
    2161                 :      * Not found ... generate an error...
    2162                 :      *----------------------------------------------------------------*/
    2163               3 :     if (!bFound)
    2164                 :     {
    2165               0 :         CPLError(CE_Failure, CPLE_IllegalArg, 
    2166                 :                  "Requested E00 section does not exist!");
    2167               0 :         return -1;
    2168                 :     }
    2169                 : 
    2170                 :     /*-----------------------------------------------------------------
    2171                 :      * Found it ... advance parser to line number of start of section
    2172                 :      *----------------------------------------------------------------*/
    2173               3 :     _AVCE00ReadSeekE00(psRead, psRead->pasSections[iSect].nLineNum, SEEK_SET);
    2174                 : 
    2175               3 :     psRead->bReadAllSections = bContinue;
    2176                 : 
    2177               3 :     return 0;
    2178                 : }

Generated by: LCOV version 1.7