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

Generated by: LCOV version 1.7