gerb_file.c

Go to the documentation of this file.
00001 /*
00002  * gEDA - GNU Electronic Design Automation
00003  * This file is a part of gerbv.
00004  *
00005  *   Copyright (C) 2000-2002 Stefan Petersen (spe@stacken.kth.se)
00006  *
00007  * $Id$
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
00022  */
00023 
00029 #ifdef HAVE_CONFIG_H
00030 #include "config.h"
00031 #endif
00032 
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 
00037 #include <sys/types.h>
00038 #include <sys/stat.h>
00039 #ifdef HAVE_UNISTD_H
00040 #include <unistd.h>
00041 #endif
00042 #ifdef HAVE_SYS_MMAN_H
00043 #include <sys/mman.h>
00044 #endif
00045 #include <errno.h>
00046 
00047 #include "gerbv.h"
00048 #include "gerb_file.h"
00049 
00050 /* DEBUG printing.  #define DEBUG 1 in config.h to use this fcn. */
00051 #define dprintf if(DEBUG) printf
00052 
00053 gerb_file_t *
00054 gerb_fopen(char const * filename)
00055 {
00056     gerb_file_t *fd;
00057     struct stat statinfo;
00058     
00059     dprintf("---> Entering gerb_fopen, filename = %s\n", filename);
00060 #ifdef HAVE_SYS_MMAN_H
00061     fd = (gerb_file_t *)g_malloc(sizeof(gerb_file_t));
00062     if (fd == NULL) {
00063        return NULL;
00064     }
00065 
00066     dprintf("     Doing fopen\n");
00067     fd->fd = fopen(filename, "r");
00068     if (fd->fd == NULL) {
00069        g_free(fd);
00070        return NULL;
00071     }
00072 
00073     dprintf("     Doing fstat\n");
00074     fd->ptr = 0;
00075     fd->fileno = fileno(fd->fd);
00076     if (fstat(fd->fileno, &statinfo) < 0) {
00077        fclose(fd->fd);
00078        g_free(fd);
00079        return NULL;
00080     }
00081 
00082     dprintf("     Checking S_ISREG\n");
00083     if (!S_ISREG(statinfo.st_mode)) {
00084        fclose(fd->fd);
00085        g_free(fd);
00086        errno = EISDIR;
00087        return NULL;
00088     }
00089 
00090     dprintf("     Checking statinfo.st_size\n");
00091     if ((int)statinfo.st_size == 0) {
00092        fclose(fd->fd);
00093        g_free(fd);
00094        errno = EIO; /* More compatible with the world outside Linux */
00095        return NULL;
00096     }
00097 
00098     dprintf("     Doing mmap\n");
00099     fd->datalen = (int)statinfo.st_size;
00100     fd->data = (char *)mmap(0, statinfo.st_size, PROT_READ, MAP_PRIVATE, 
00101                          fd->fileno, 0);
00102     if(fd->data == MAP_FAILED) {
00103        fclose(fd->fd);
00104        g_free(fd);
00105        fd = NULL;
00106     }
00107 #else
00108     /* all systems without mmap, not only MINGW32 */
00109     fd = (gerb_file_t *)g_malloc(sizeof(gerb_file_t));
00110     if (fd == NULL) {
00111        return NULL;
00112     }
00113 
00114     if (stat(filename, &statinfo) < 0) {
00115        fclose(fd->fd);
00116        g_free(fd);
00117         return NULL;
00118     }
00119     
00120     fd->fd = fopen(filename, "rb");
00121     fd->ptr = 0;
00122     fd->fileno = fileno(fd->fd);
00123     if (fstat(fd->fileno, &statinfo) < 0) {
00124        fclose(fd->fd);
00125        g_free(fd);
00126        return NULL;
00127     }  
00128     if (!S_ISREG(statinfo.st_mode)) {
00129        fclose(fd->fd);
00130        g_free(fd);
00131        errno = EISDIR;
00132        return NULL;
00133     }
00134     if ((int)statinfo.st_size == 0) {
00135        fclose(fd->fd);
00136        g_free(fd);
00137        errno = EIO; /* More compatible with the world outside Linux */
00138        return NULL;
00139     }
00140     fd->datalen = (int)statinfo.st_size;
00141     fd->data = calloc(1, statinfo.st_size + 1);
00142     if (fd->data == NULL) {
00143         fclose(fd->fd);
00144         g_free(fd);
00145         return NULL;
00146     }
00147     if (fread((void*)fd->data, 1, statinfo.st_size, fd->fd) != statinfo.st_size) {
00148         fclose(fd->fd);
00149        g_free(fd->data);
00150         g_free(fd);
00151        return NULL;
00152     }
00153     rewind (fd->fd);
00154 #endif
00155 
00156     dprintf("<--- Leaving gerb_fopen\n");
00157     return fd;
00158 } /* gerb_fopen */
00159 
00160 
00161 int
00162 gerb_fgetc(gerb_file_t *fd)
00163 {
00164 
00165     if (fd->ptr >= fd->datalen)
00166        return EOF;
00167 
00168     return (int) fd->data[fd->ptr++];
00169 } /* gerb_fgetc */
00170 
00171 
00172 int
00173 gerb_fgetint(gerb_file_t *fd, int *len)
00174 {
00175     long int result;
00176     char *end;
00177     
00178     errno = 0;
00179     result = strtol(fd->data + fd->ptr, &end, 10);
00180     if (errno) {
00181        GERB_COMPILE_ERROR("Failed to read integer");
00182        return 0;
00183     }
00184 
00185     if (len) {
00186        *len = end - (fd->data + fd->ptr);
00187     }
00188 
00189     fd->ptr = end - fd->data;
00190 
00191     if (len && (result < 0))
00192        *len -= 1;
00193 
00194     return (int)result;
00195 } /* gerb_fgetint */
00196 
00197 
00198 double
00199 gerb_fgetdouble(gerb_file_t *fd)
00200 {
00201     double result;
00202     char *end;
00203 
00204     errno = 0;    
00205     result = strtod(fd->data + fd->ptr, &end);
00206     if (errno) {
00207        GERB_COMPILE_ERROR("Failed to read double");
00208        return 0.0;
00209     }
00210 
00211     fd->ptr = end - fd->data;
00212 
00213     return result;
00214 } /* gerb_fgetdouble */
00215 
00216 
00217 char *
00218 gerb_fgetstring(gerb_file_t *fd, char term)
00219 {
00220     char *strend = NULL;
00221     char *newstr;
00222     char *i, *iend;
00223     int len;
00224 
00225     iend = fd->data + fd->datalen;
00226     for (i = fd->data + fd->ptr; i < iend; i++) {
00227        if (*i == term) {
00228            strend = i;
00229            break;
00230        }
00231     }
00232 
00233     if (strend == NULL)
00234        return NULL;
00235 
00236     len = strend - (fd->data + fd->ptr);
00237 
00238     newstr = (char *)g_malloc(len + 1);
00239     if (newstr == NULL)
00240        return NULL;
00241     strncpy(newstr, fd->data + fd->ptr, len);
00242     newstr[len] = '\0';
00243     fd->ptr += len;
00244 
00245     return newstr;
00246 } /* gerb_fgetstring */
00247 
00248 
00249 void 
00250 gerb_ungetc(gerb_file_t *fd)
00251 {
00252     if (fd->ptr)
00253        fd->ptr--;
00254 
00255     return;
00256 } /* gerb_ungetc */
00257 
00258 
00259 void
00260 gerb_fclose(gerb_file_t *fd)
00261 {
00262     if (fd) {
00263 #ifdef HAVE_SYS_MMAN_H
00264        if (munmap(fd->data, fd->datalen) < 0)
00265            GERB_FATAL_ERROR("munmap:%s", strerror(errno));
00266 #else
00267        g_free(fd->data);
00268 #endif   
00269        if (fclose(fd->fd) == EOF)
00270            GERB_FATAL_ERROR("fclose:%s", strerror(errno));
00271        g_free(fd);
00272     }
00273 
00274     return;
00275 } /* gerb_fclose */
00276 
00277 
00278 char *
00279 gerb_find_file(char const * filename, char **paths)
00280 {
00281     char *curr_path = NULL;
00282     char *complete_path = NULL;
00283     int        i;
00284 
00285     for (i = 0; paths[i] != NULL; i++) {
00286 
00287        /*
00288         * Environment variables start with a $ sign 
00289         */
00290        if (paths[i][0] == '$') {
00291            char *env_name, *env_value, *tmp;
00292            int len;
00293 
00294            /* Extract environment name. Remember we start with a $ */
00295         
00296            tmp = strchr(paths[i], G_DIR_SEPARATOR);
00297            if (tmp == NULL) 
00298               len = strlen(paths[i]) - 1;
00299            else
00300               len = tmp - paths[i] - 1;
00301            env_name = (char *)g_malloc(len + 1);
00302            if (env_name == NULL)
00303               return NULL;
00304            strncpy(env_name, (char *)(paths[i] + 1), len);
00305            env_name[len] = '\0';
00306 
00307            env_value = getenv(env_name);
00308            if (env_value == NULL) break;
00309            curr_path = (char *)g_malloc(strlen(env_value) + strlen(&paths[i][len + 1]) + 1);
00310            if (curr_path == NULL)
00311               return NULL;
00312            strcpy(curr_path, env_value);
00313            strcat(curr_path, &paths[i][len + 1]);
00314            g_free(env_name);
00315        } else {
00316            curr_path = paths[i];
00317        }
00318 
00319        /*
00320         * Build complete path (inc. filename) and check if file exists.
00321         */
00322        complete_path = (char *)g_malloc(strlen(curr_path) + strlen(filename) + 2);
00323        if (complete_path == NULL)
00324            return NULL;
00325        strcpy(complete_path, curr_path);
00326        complete_path[strlen(curr_path)] = G_DIR_SEPARATOR;
00327        complete_path[strlen(curr_path) + 1] = '\0';
00328        strncat(complete_path, filename, strlen(filename));
00329 
00330        if (paths[i][0] == '$') {
00331            g_free(curr_path);
00332            curr_path = NULL;
00333        }
00334        
00335        if (access(complete_path, R_OK) != -1)
00336            break;
00337 
00338        g_free(complete_path);
00339        complete_path = NULL;
00340     }
00341 
00342     if (complete_path == NULL)
00343        errno = ENOENT;
00344 
00345     return complete_path;
00346 } /* gerb_find_file */

Generated on Tue Aug 19 00:14:48 2008 for gerbv by  doxygen 1.5.6