gerbv  2.10.1-dev~93f1b5
gerb_file.c
Go to the documentation of this file.
1 /*
2  * gEDA - GNU Electronic Design Automation
3  * This file is a part of gerbv.
4  *
5  * Copyright (C) 2000-2002 Stefan Petersen (spe@stacken.kth.se)
6  *
7  * $Id$
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
22  */
23 
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <string.h>
36 
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #ifdef HAVE_UNISTD_H
40 #include <unistd.h>
41 #endif
42 #ifdef HAVE_SYS_MMAN_H
43 #include <sys/mman.h>
44 #endif
45 #include <errno.h>
46 #include <glib/gstdio.h>
47 
48 #include "common.h"
49 #include "gerbv.h"
50 #include "gerb_file.h"
51 
52 /* DEBUG printing. #define DEBUG 1 in config.h to use this fcn. */
53 #define dprintf \
54  if (DEBUG) \
55  printf
56 
57 gerb_file_t*
58 gerb_fopen(const char* filename) {
59  gerb_file_t* fd;
60  struct stat statinfo;
61 
62  dprintf("---> Entering gerb_fopen, filename = %s\n", filename);
63 
64  fd = g_new(gerb_file_t, 1);
65  if (fd == NULL) {
66  return NULL;
67  }
68 
69  dprintf(" Doing fopen\n");
70  /* fopen() can't open files with non ASCII filenames on windows */
71  fd->fd = g_fopen(filename, "rb");
72  if (fd->fd == NULL) {
73  g_free(fd);
74  return NULL;
75  }
76 
77  dprintf(" Doing fstat\n");
78  fd->ptr = 0;
79  fd->fileno = fileno(fd->fd);
80  if (fstat(fd->fileno, &statinfo) < 0) {
81  fclose(fd->fd);
82  g_free(fd);
83  return NULL;
84  }
85 
86  dprintf(" Checking S_ISREG\n");
87  if (!S_ISREG(statinfo.st_mode)) {
88  fclose(fd->fd);
89  g_free(fd);
90  errno = EISDIR;
91  return NULL;
92  }
93 
94  dprintf(" Checking statinfo.st_size\n");
95  if ((int)statinfo.st_size == 0) {
96  fclose(fd->fd);
97  g_free(fd);
98  errno = EIO; /* More compatible with the world outside Linux */
99  return NULL;
100  }
101 
102 #ifdef HAVE_SYS_MMAN_H
103 
104  dprintf(" Doing mmap\n");
105  fd->datalen = (int)statinfo.st_size;
106  fd->data = (char*)mmap(0, statinfo.st_size, PROT_READ, MAP_PRIVATE, fd->fileno, 0);
107  if (fd->data == MAP_FAILED) {
108  fclose(fd->fd);
109  g_free(fd);
110  fd = NULL;
111  }
112 
113 #else
114  /* all systems without mmap, not only MINGW32 */
115 
116  dprintf(" Doing calloc\n");
117  fd->datalen = (int)statinfo.st_size;
118  fd->data = calloc(1, statinfo.st_size + 1);
119  if (fd->data == NULL) {
120  fclose(fd->fd);
121  g_free(fd);
122  return NULL;
123  }
124  if (fread((void*)fd->data, 1, statinfo.st_size, fd->fd) != statinfo.st_size) {
125  fclose(fd->fd);
126  g_free(fd->data);
127  g_free(fd);
128  return NULL;
129  }
130  rewind(fd->fd);
131 
132 #endif
133 
134  dprintf(" Setting filename\n");
135  fd->filename = g_strdup(filename);
136 
137  dprintf("<--- Leaving gerb_fopen\n");
138  return fd;
139 } /* gerb_fopen */
140 
141 int
142 gerb_fgetc(gerb_file_t* fd) {
143 
144  if (fd->ptr >= fd->datalen)
145  return EOF;
146 
147  return (int)fd->data[fd->ptr++];
148 } /* gerb_fgetc */
149 
150 int
151 gerb_fgetint(gerb_file_t* fd, int* len) {
152  long int result;
153  char* end;
154 
155  errno = 0;
156  result = strtol(fd->data + fd->ptr, &end, 10);
157  if (errno) {
158  GERB_COMPILE_ERROR(_("Failed to read integer"));
159  return 0;
160  }
161 
162  if (len) {
163  *len = end - (fd->data + fd->ptr);
164  }
165 
166  fd->ptr = end - fd->data;
167 
168  if (len && (result < 0))
169  *len -= 1;
170 
171  return (int)result;
172 } /* gerb_fgetint */
173 
174 double
175 gerb_fgetdouble(gerb_file_t* fd) {
176  double result;
177  char* end;
178 
179  errno = 0;
180  result = strtod(fd->data + fd->ptr, &end);
181  if (errno) {
182  GERB_COMPILE_ERROR(_("Failed to read double"));
183  return 0.0;
184  }
185 
186  fd->ptr = end - fd->data;
187 
188  return result;
189 } /* gerb_fgetdouble */
190 
191 char*
192 gerb_fgetstring(gerb_file_t* fd, char term) {
193  char* strend = NULL;
194  char* newstr;
195  char *i, *iend;
196  int len;
197 
198  iend = fd->data + fd->datalen;
199  for (i = fd->data + fd->ptr; i < iend; i++) {
200  if (*i == term) {
201  strend = i;
202  break;
203  }
204  }
205 
206  if (strend == NULL)
207  return NULL;
208 
209  len = strend - (fd->data + fd->ptr);
210 
211  newstr = (char*)g_malloc(len + 1);
212  if (newstr == NULL)
213  return NULL;
214  strncpy(newstr, fd->data + fd->ptr, len);
215  newstr[len] = '\0';
216  fd->ptr += len;
217 
218  return newstr;
219 } /* gerb_fgetstring */
220 
221 void
222 gerb_ungetc(gerb_file_t* fd) {
223  if (fd->ptr)
224  fd->ptr--;
225 
226  return;
227 } /* gerb_ungetc */
228 
229 void
230 gerb_fclose(gerb_file_t* fd) {
231  if (fd) {
232  g_free(fd->filename);
233 
234 #ifdef HAVE_SYS_MMAN_H
235  if (munmap(fd->data, fd->datalen) < 0)
236  GERB_FATAL_ERROR("munmap: %s", strerror(errno));
237 #else
238  g_free(fd->data);
239 #endif
240  if (fclose(fd->fd) == EOF)
241  GERB_FATAL_ERROR("fclose: %s", strerror(errno));
242  g_free(fd);
243  }
244 
245  return;
246 } /* gerb_fclose */
247 
248 char*
249 gerb_find_file(const char* filename, char** paths) {
250  char* curr_path = NULL;
251  char* complete_path = NULL;
252  int i;
253 
254 #ifdef DEBUG
255  if (DEBUG > 0) {
256  for (i = 0; paths[i] != NULL; i++) {
257  printf("%s(): paths[%d] = \"%s\"\n", __FUNCTION__, i, paths[i]);
258  }
259  }
260 #endif
261 
262  for (i = 0; paths[i] != NULL; i++) {
263  dprintf("%s(): Try paths[%d] = \"%s\"\n", __FUNCTION__, i, paths[i]);
264 
265  /*
266  * Environment variables start with a $ sign
267  */
268  if (paths[i][0] == '$') {
269  char *env_name, *env_value, *tmp;
270  int len;
271 
272  /* Extract environment name. Remember we start with a $ */
273 
274  tmp = strchr(paths[i], G_DIR_SEPARATOR);
275  if (tmp == NULL)
276  len = strlen(paths[i]) - 1;
277  else
278  len = tmp - paths[i] - 1;
279  env_name = (char*)g_malloc(len + 1);
280  if (env_name == NULL)
281  return NULL;
282  strncpy(env_name, (char*)(paths[i] + 1), len);
283  env_name[len] = '\0';
284 
285  env_value = getenv(env_name);
286  dprintf(
287  "%s(): Trying \"%s\" = \"%s\" from the environment\n", __FUNCTION__, env_name,
288  env_value == NULL ? "(null)" : env_value
289  );
290 
291  if (env_value == NULL) {
292  curr_path = NULL;
293  } else {
294  curr_path = (char*)g_malloc(strlen(env_value) + strlen(&paths[i][len + 1]) + 1);
295  if (curr_path == NULL)
296  return NULL;
297  strcpy(curr_path, env_value);
298  strcat(curr_path, &paths[i][len + 1]);
299  g_free(env_name);
300  }
301  } else {
302  curr_path = paths[i];
303  }
304 
305  if (curr_path != NULL) {
306  /*
307  * Build complete path (inc. filename) and check if file exists.
308  */
309  complete_path = g_build_filename(curr_path, filename, NULL);
310  if (complete_path == NULL)
311  return NULL;
312 
313  if (paths[i][0] == '$') {
314  g_free(curr_path);
315  curr_path = NULL;
316  }
317 
318  dprintf("%s(): Tring to access \"%s\"\n", __FUNCTION__, complete_path);
319 
320  if (access(complete_path, R_OK) != -1)
321  break;
322 
323  g_free(complete_path);
324  complete_path = NULL;
325  }
326  }
327 
328  if (complete_path == NULL)
329  errno = ENOENT;
330 
331  dprintf(
332  "%s(): returning complete_path = \"%s\"\n", __FUNCTION__, complete_path == NULL ? "(null)" : complete_path
333  );
334 
335  return complete_path;
336 } /* gerb_find_file */
Contains basic defines.
char * gerb_find_file(const char *filename, char **paths)
Search for files in directories pointed out by paths, a NULL terminated list of directories to search...
Definition: gerb_file.c:249
Header info for the file parsing support functions.
The main header file for the libgerbv library.