Sync-to-go: update copyright for 2015
[s-roff.git] / src / lib-roff / searchpath.cpp
blob7f70a715e626b1c931562dadbaa48e86107ea11d
1 /*@
2 * Copyright (c) 2014 - 2015 Steffen (Daode) Nurpmeso <sdaoden@users.sf.net>.
4 * Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2003, 2005
5 * Free Software Foundation, Inc.
6 * Written by James Clark (jjc@jclark.com)
8 * This is free software; you can redistribute it and/or modify it under
9 * the terms of the GNU General Public License as published by the Free
10 * Software Foundation; either version 2, or (at your option) any later
11 * version.
13 * This is distributed in the hope that it will be useful, but WITHOUT ANY
14 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 * for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with groff; see the file COPYING. If not, write to the Free Software
20 * Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "config.h"
24 #include "lib.h"
26 #include <assert.h>
27 #include <errno.h>
28 #include <stdlib.h>
30 #include "file_case.h"
31 #include "nonposix.h"
32 #include "searchpath.h"
34 #ifdef _WIN32
35 # include "relocate.h"
36 #else
37 # define relocate(path) strsave(path)
38 #endif
40 static file_case * _try_iter(char const *dirs, char const *name,
41 uint32_t flags);
43 static file_case *
44 _try_iter(char const *dirs, char const *name, uint32_t flags)
46 file_case *fcp;
47 bool delname = ((flags & fcp->fc_take_path) != 0);
48 flags = (flags & ~(fcp->fc_const_path)) | fcp->fc_take_path;
49 unsigned namelen = strlen(name);
50 char const *p = dirs;
52 for (;;) {
53 char *end = strchr(p, PATH_SEP_CHAR);
54 if (end == NULL)
55 end = strchr(p, '\0');
56 int need_slash = (end > p && strchr(DIR_SEPS, end[-1]) == NULL);
57 char *origpath = new char[(end - p) + need_slash + namelen + 1];
58 memcpy(origpath, p, end - p);
59 if (need_slash)
60 origpath[end - p] = '/';
61 strcpy(origpath + (end - p) + need_slash, name);
62 #if 0
63 fprintf(stderr, "origpath `%s'\n", origpath);
64 #endif
65 char *path = relocate(origpath);
66 a_delete origpath;
67 #if 0
68 fprintf(stderr, "trying `%s'\n", path);
69 #endif
70 if ((fcp = file_case::muxer(path, flags)) != NULL)
71 goto jleave;
72 if (errno != ENOENT)
73 goto jleave;
74 if (*end == '\0')
75 break;
76 p = end + 1;
78 errno = ENOENT;
79 jleave:
80 if (delname)
81 a_delete name;
82 return fcp;
85 search_path::search_path(const char *envvar, const char *standard,
86 int add_home, int add_current)
88 char *home = 0;
89 if (add_home)
90 home = getenv("HOME");
91 char *e = 0;
92 if (envvar)
93 e = getenv(envvar);
94 dirs = new char[((e && *e) ? strlen(e) + 1 : 0)
95 + (add_current ? 1 + 1 : 0)
96 + ((home && *home) ? strlen(home) + 1 : 0)
97 + ((standard && *standard) ? strlen(standard) : 0)
98 + 1];
99 *dirs = '\0';
100 if (e && *e) {
101 strcat(dirs, e);
102 strcat(dirs, PATH_SEP);
104 if (add_current) {
105 strcat(dirs, ".");
106 strcat(dirs, PATH_SEP);
108 if (home && *home) {
109 strcat(dirs, home);
110 strcat(dirs, PATH_SEP);
112 if (standard && *standard)
113 strcat(dirs, standard);
114 init_len = strlen(dirs);
117 search_path::~search_path()
119 // dirs is always allocated
120 a_delete dirs;
123 void search_path::command_line_dir(const char *s)
125 char *old = dirs;
126 unsigned old_len = strlen(old);
127 unsigned slen = strlen(s);
128 dirs = new char[old_len + 1 + slen + 1];
129 memcpy(dirs, old, old_len - init_len);
130 char *p = dirs;
131 p += old_len - init_len;
132 if (init_len == 0)
133 *p++ = PATH_SEP_CHAR;
134 memcpy(p, s, slen);
135 p += slen;
136 if (init_len > 0) {
137 *p++ = PATH_SEP_CHAR;
138 memcpy(p, old + old_len - init_len, init_len);
139 p += init_len;
141 *p++ = '\0';
142 a_delete old;
145 file_case *search_path::open_file(char const *name, uint32_t flags)
147 assert(name != NULL);
149 file_case *fcp;
150 if (IS_ABSOLUTE(name) || *dirs == '\0')
151 fcp = file_case::muxer(name, flags);
152 else
153 fcp = _try_iter(dirs, name, flags);
154 return fcp;
157 file_case *search_path::open_file_cautious(char const *name, uint32_t flags)
159 file_case *fcp;
160 if (name == NULL || strcmp(name, "-") == 0) {
161 name = NULL;
162 goto jmuxer;
164 if (IS_ABSOLUTE(name) || *dirs == '\0')
165 jmuxer:
166 fcp = file_case::muxer(name, flags);
167 else
168 fcp = _try_iter(dirs, name, flags);
169 return fcp;
172 // s-it2-mode