source: git/src/filename.c @ 3e912fd

RELEASE/1.0RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersfaster-cavernloglog-selectstereostereo-2025walls-datawalls-data-hanging-as-warningwarn-only-for-hanging-survey
Last change on this file since 3e912fd was 25ab06b, checked in by Olly Betts <olly@…>, 24 years ago

Prefer balanced quotes (`...') to unbalanced ('...') in messages.

cavern: file reading errors now treated as fatal; unattached survey error
now fatal; if there are errors, don't produce output files; bug fix: buffer
overrun in showline(); removed PRINT_NAME_PTRS debug stuff.

survex: syntax errors in command line arguments now fatal.

Turned off aven building for now.

3dtodxf renamed to cad3d to reflect choice of output formats.

git-svn-id: file:///home/survex-svn/survex/trunk@619 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 8.2 KB
RevLine 
[846746e]1/* OS dependent filename manipulation routines
[704ad2b]2 * Copyright (c) Olly Betts 1998-2001
[846746e]3 *
[89231c4]4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
[846746e]8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
[89231c4]11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
[846746e]13 *
[89231c4]14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
[846746e]17 */
[6ba8d69]18
[a420b49]19#ifdef HAVE_CONFIG_H
20# include <config.h>
21#endif
22
[9af1d7a9]23#include "filename.h"
[47c7a94]24
25#include <ctype.h>
[9af1d7a9]26#include <string.h>
27
[ce5b43c]28/* FIXME: finish sorting out safe_fopen vs fopenWithPthAndExt... */
29
[a420b49]30/* Wrapper for fopen which throws a fatal error if it fails.
31 * Some versions of fopen() are quite happy to open a directory.
32 * We aren't, so catch this case. */
33extern FILE *
34safe_fopen(const char *fnm, const char *mode)
35{
36   FILE *f;
37   if (fDirectory(fnm))
[759fb47]38      fatalerror(/*Filename `%s' refers to directory*/44, fnm);
[a420b49]39
40   f = fopen(fnm, mode);
41   if (!f) fatalerror(mode[0] == 'w' ?
[759fb47]42                      /*Failed to open output file `%s'*/47 :
43                      /*Couldn't open data file `%s'*/24, fnm);
[25ab06b]44   if (mode[0] == 'w') filename_register_output(fnm);
[a420b49]45   return f;
46}
47
[ce5b43c]48extern FILE *
49safe_fopen_with_ext(const char *fnm, const char *ext, const char *mode)
50{
51   FILE *f;
52   char *p;
53   p = add_ext(fnm, ext);
54   f = safe_fopen(p, mode);
55   osfree(p);
56   return f;
57}
58
59static FILE *
[a420b49]60fopen_not_dir(const char *fnm, const char *mode)
61{
62   if (fDirectory(fnm)) return NULL;
63   return fopen(fnm, mode);
[9af1d7a9]64}
65
[a420b49]66extern char * FAR
[ce5b43c]67path_from_fnm(const char *fnm)
[a420b49]68{
[9af1d7a9]69   char *pth;
70   const char *lf;
71   int lenpth = 0;
72
[a420b49]73   lf = strrchr(fnm, FNM_SEP_LEV);
[9af1d7a9]74#ifdef FNM_SEP_LEV2
[029824d]75   {
[eee67ab]76      const char *lf2 = strrchr(lf ? lf + 1 : fnm, FNM_SEP_LEV2);
[029824d]77      if (lf2) lf = lf2;
78   }
[9af1d7a9]79#endif
80#ifdef FNM_SEP_DRV
[a420b49]81   if (!lf) lf = strrchr(fnm, FNM_SEP_DRV);
[9af1d7a9]82#endif
83   if (lf) lenpth = lf - fnm + 1;
84
[a420b49]85   pth = osmalloc(lenpth + 1);
86   memcpy(pth, fnm, lenpth);
[9af1d7a9]87   pth[lenpth] = '\0';
88
89   return pth;
90}
91
[ce5b43c]92extern char *
93base_from_fnm(const char *fnm)
94{
95   char *p;
[cb3d1e2]96
[ce5b43c]97   p = strrchr(fnm, FNM_SEP_EXT);
98   /* Trim off any leaf extension, but dirs can have extensions too */
[029824d]99   if (p && !strchr(p, FNM_SEP_LEV)
[ce5b43c]100#ifdef FNM_SEP_LEV2
[029824d]101       && !strchr(p, FNM_SEP_LEV2)
[ce5b43c]102#endif
103       ) {
[e917a13]104      size_t len = (const char *)p - fnm;
[ce5b43c]105
106      p = osmalloc(len + 1);
107      memcpy(p, fnm, len);
108      p[len] = '\0';
109      return p;
110   }
111
112   return osstrdup(fnm);
113}
114
115extern char *
116baseleaf_from_fnm(const char *fnm)
117{
118   const char *p;
119   char *q;
120   size_t len;
[cb3d1e2]121
[ce5b43c]122   p = fnm;
123   q = strrchr(p, FNM_SEP_LEV);
124   if (q) p = q + 1;
125#ifdef FNM_SEP_LEV2
126   q = strrchr(p, FNM_SEP_LEV2);
127   if (q) p = q + 1;
128#endif
[cb3d1e2]129
[ce5b43c]130   q = strrchr(p, FNM_SEP_EXT);
[e917a13]131   if (q) len = (const char *)q - p; else len = strlen(p);
[ce5b43c]132
133   q = osmalloc(len + 1);
134   memcpy(q, p, len);
135   q[len] = '\0';
136   return q;
137}
138
[a420b49]139extern char * FAR
[ce5b43c]140leaf_from_fnm(const char *fnm)
[a420b49]141{
[029824d]142   const char *lf;
[a420b49]143   lf = strrchr(fnm, FNM_SEP_LEV);
[029824d]144   if (lf) fnm = lf + 1;
[9af1d7a9]145#ifdef FNM_SEP_LEV2
[029824d]146   lf = strrchr(fnm, FNM_SEP_LEV2);
147   if (lf) fnm = lf + 1;
[9af1d7a9]148#endif
149#ifdef FNM_SEP_DRV
[029824d]150   lf = strrchr(fnm, FNM_SEP_DRV);
151   if (lf) fnm = lf + 1;
[9af1d7a9]152#endif
153   return osstrdup(fnm);
154}
155
156/* Make fnm from pth and lf, inserting an FNM_SEP_LEV if appropriate */
[a420b49]157extern char * FAR
[ce5b43c]158use_path(const char *pth, const char *lf)
[a420b49]159{
[9af1d7a9]160   char *fnm;
161   int len, len_total;
162   bool fAddSep = fFalse;
163
164   len = strlen(pth);
165   len_total = len + strlen(lf) + 1;
166
167   /* if there's a path and it doesn't end in a separator, insert one */
[a420b49]168   if (len && pth[len - 1] != FNM_SEP_LEV) {
[9af1d7a9]169#ifdef FNM_SEP_LEV2
[a420b49]170      if (pth[len - 1] != FNM_SEP_LEV2) {
[9af1d7a9]171#endif
172#ifdef FNM_SEP_DRV
[a420b49]173         if (pth[len - 1] != FNM_SEP_DRV) {
[9af1d7a9]174#endif
175            fAddSep = fTrue;
176            len_total++;
177#ifdef FNM_SEP_DRV
178         }
179#endif
180#ifdef FNM_SEP_LEV2
181      }
182#endif
183   }
184
185   fnm = osmalloc(len_total);
[a420b49]186   strcpy(fnm, pth);
[9af1d7a9]187   if (fAddSep) fnm[len++] = FNM_SEP_LEV;
[a420b49]188   strcpy(fnm + len, lf);
[9af1d7a9]189   return fnm;
190}
191
192/* Add ext to fnm, inserting an FNM_SEP_EXT if appropriate */
[a420b49]193extern char * FAR
[ce5b43c]194add_ext(const char *fnm, const char *ext)
[a420b49]195{
[9af1d7a9]196   char * fnmNew;
197   int len, len_total;
198#ifdef FNM_SEP_EXT
199   bool fAddSep = fFalse;
200#endif
201
202   len = strlen(fnm);
203   len_total = len + strlen(ext) + 1;
204#ifdef FNM_SEP_EXT
205   if (ext[0] != FNM_SEP_EXT) {
206      fAddSep = fTrue;
207      len_total++;
208   }
209#endif
210
211   fnmNew = osmalloc(len_total);
[a420b49]212   strcpy(fnmNew, fnm);
[9af1d7a9]213#ifdef FNM_SEP_EXT
214   if (fAddSep) fnmNew[len++] = FNM_SEP_EXT;
215#endif
[a420b49]216   strcpy(fnmNew + len, ext);
[9af1d7a9]217   return fnmNew;
218}
219
220/* fopen file, found using pth and fnm
[25ab06b]221 * fnmUsed is used to return filename used to open file (ignored if NULL)
[9af1d7a9]222 * or NULL if file didn't open
223 */
[a420b49]224extern FILE FAR *
[25ab06b]225fopenWithPthAndExt(const char *pth, const char *fnm, const char *ext,
226                   const char *mode, char **fnmUsed)
[a420b49]227{
228   char *fnmFull = NULL;
229   FILE *fh = NULL;
230   bool fAbs;
231
232   /* if no pth treat fnm as absolute */
233   fAbs = (pth == NULL || *pth == '\0' || fAbsoluteFnm(fnm));
234
235   /* if appropriate, try it without pth */
236   if (fAbs) {
[25ab06b]237      fh = fopen_not_dir(fnm, mode);
[a420b49]238      if (fh) {
[25ab06b]239         if (fnmUsed) fnmFull = osstrdup(fnm);
[a420b49]240      } else {
[25ab06b]241         if (ext && *ext) {
[a420b49]242            /* we've been given an extension so try using it */
[25ab06b]243            fnmFull = add_ext(fnm, ext);
244            fh = fopen_not_dir(fnmFull, mode);
[a420b49]245         }
[9af1d7a9]246      }
[a420b49]247   } else {
248      /* try using path given - first of all without the extension */
[ce5b43c]249      fnmFull = use_path(pth, fnm);
[25ab06b]250      fh = fopen_not_dir(fnmFull, mode);
[a420b49]251      if (!fh) {
[25ab06b]252         if (ext && *ext) {
[a420b49]253            /* we've been given an extension so try using it */
254            char *fnmTmp;
255            fnmTmp = fnmFull;
[25ab06b]256            fnmFull = add_ext(fnmFull, ext);
[a420b49]257            osfree(fnmTmp);
[25ab06b]258            fh = fopen_not_dir(fnmFull, mode);
[a420b49]259         }
[9af1d7a9]260      }
[a420b49]261   }
262
263   /* either it opened or didn't. If not, fh == NULL from fopen_not_dir() */
264
265   /* free name if it didn't open or name isn't wanted */
[25ab06b]266   if (fh == NULL || fnmUsed == NULL) osfree(fnmFull);
267   if (fnmUsed) *fnmUsed = (fh ? fnmFull : NULL);
[a420b49]268   return fh;
[9af1d7a9]269}
[47c7a94]270
271/* Like fopenWithPthAndExt except that "foreign" paths are translated to
272 * native ones (e.g. on Unix dir\file.ext -> dir/file.ext) */
273FILE *
274fopen_portable(const char *pth, const char *fnm, const char *ext,
[25ab06b]275               const char *mode, char **fnmUsed)
[47c7a94]276{
[25ab06b]277   FILE *fh = fopenWithPthAndExt(pth, fnm, ext, mode, fnmUsed);
[47c7a94]278   if (fh == NULL) {
279#if (OS==RISCOS) || (OS==UNIX)
280      int f_changed = 0;
281      char *fnm_trans, *p;
282#if OS==RISCOS
283      char *q;
284#endif
285      fnm_trans = osstrdup(fnm);
286#if OS==RISCOS
287      q = fnm_trans;
288#endif
289      for (p = fnm_trans; *p; p++) {
290         switch (*p) {
291#if (OS==RISCOS)
292         /* swap either slash to a dot, and a dot to a forward slash */
293         /* but .. goes to ^ */
294         case '.':
295            if (p[1] == '.') {
296               *q++ = '^';
297               p++; /* skip second dot */
298            } else {
299               *q++ = '/';
300            }
301            f_changed = 1;
302            break;
303         case '/': case '\\':
304            *q++ = '.';
305            f_changed = 1;
306            break;
307         default:
308            *q++ = *p; break;
309#else
310         case '\\': /* swap a backslash to a forward slash */
311            *p = '/';
312            f_changed = 1;
313            break;
314#endif
315         }
316      }
317#if OS==RISCOS
318      *q = '\0';
319#endif
320      if (f_changed)
[25ab06b]321         fh = fopenWithPthAndExt(pth, fnm_trans, ext, mode, fnmUsed);
[47c7a94]322
323#if (OS==UNIX)
324      /* as a last ditch measure, try lowercasing the filename */
325      if (fh == NULL) {
326         f_changed = 0;
327         for (p = fnm_trans; *p ; p++)
328            if (isupper(*p)) {
329               *p = tolower(*p);
330               f_changed = 1;
331            }
332         if (f_changed)
[25ab06b]333            fh = fopenWithPthAndExt(pth, fnm_trans, ext, mode, fnmUsed);
[47c7a94]334      }
335#endif
336      osfree(fnm_trans);
337#endif
338   }
339   return fh;
340}
[25ab06b]341
342typedef struct filelist {
343   char *fnm;
344   struct filelist *next;
345} filelist;
346
347static filelist *flhead = NULL;
348
349void
350filename_register_output(const char *fnm)
351{
352   filelist *p = osnew(filelist);
353   p->fnm = osstrdup(fnm);
354   p->next = flhead;
355   flhead = p;
356}
357
358void
359filename_delete_output(void)
360{
361   while (flhead) {
362      filelist *p = flhead;
363      flhead = flhead->next;
364      remove(p->fnm);
365      osfree(p->fnm);
366      osfree(p);
367   }
368}
Note: See TracBrowser for help on using the repository browser.