Many: use stdin support of file_case::muxer()
[s-roff.git] / src / libs / libgroff / searchpath.cpp
blobf36b79434ceee62601545164784ab694a16a2d8d
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2003, 2005
3 Free Software Foundation, Inc.
4 Written by James Clark (jjc@jclark.com)
6 This file is part of groff.
8 groff 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 groff 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. */
22 #include "lib.h"
24 #include <stdlib.h>
25 #include <assert.h>
26 #include <errno.h>
28 #include "file_case.h"
29 #include "searchpath.h"
30 #include "nonposix.h"
32 #ifdef _WIN32
33 # include "relocate.h"
34 #else
35 # define relocate(path) strsave(path)
36 #endif
38 static file_case * _try_iter(char const *dirs, char const *name,
39 uint32_t flags);
41 static file_case *
42 _try_iter(char const *dirs, char const *name, uint32_t flags)
44 file_case *fcp;
45 bool delname = ((flags & fcp->fc_take_path) != 0);
46 flags = (flags & ~(fcp->fc_const_path)) | fcp->fc_take_path;
47 unsigned namelen = strlen(name);
48 char const *p = dirs;
50 for (;;) {
51 char *end = strchr(p, PATH_SEP_CHAR);
52 if (end == NULL)
53 end = strchr(p, '\0');
54 int need_slash = (end > p && strchr(DIR_SEPS, end[-1]) == NULL);
55 char *origpath = new char[(end - p) + need_slash + namelen + 1];
56 memcpy(origpath, p, end - p);
57 if (need_slash)
58 origpath[end - p] = '/';
59 strcpy(origpath + (end - p) + need_slash, name);
60 #if 0
61 fprintf(stderr, "origpath `%s'\n", origpath);
62 #endif
63 char *path = relocate(origpath);
64 a_delete origpath;
65 #if 0
66 fprintf(stderr, "trying `%s'\n", path);
67 #endif
68 if ((fcp = file_case::muxer(path, flags)) != NULL)
69 goto jleave;
70 if (errno != ENOENT)
71 goto jleave;
72 if (*end == '\0')
73 break;
74 p = end + 1;
76 errno = ENOENT;
77 jleave:
78 if (delname)
79 a_delete name;
80 return fcp;
83 search_path::search_path(const char *envvar, const char *standard,
84 int add_home, int add_current)
86 char *home = 0;
87 if (add_home)
88 home = getenv("HOME");
89 char *e = 0;
90 if (envvar)
91 e = getenv(envvar);
92 dirs = new char[((e && *e) ? strlen(e) + 1 : 0)
93 + (add_current ? 1 + 1 : 0)
94 + ((home && *home) ? strlen(home) + 1 : 0)
95 + ((standard && *standard) ? strlen(standard) : 0)
96 + 1];
97 *dirs = '\0';
98 if (e && *e) {
99 strcat(dirs, e);
100 strcat(dirs, PATH_SEP);
102 if (add_current) {
103 strcat(dirs, ".");
104 strcat(dirs, PATH_SEP);
106 if (home && *home) {
107 strcat(dirs, home);
108 strcat(dirs, PATH_SEP);
110 if (standard && *standard)
111 strcat(dirs, standard);
112 init_len = strlen(dirs);
115 search_path::~search_path()
117 // dirs is always allocated
118 a_delete dirs;
121 void search_path::command_line_dir(const char *s)
123 char *old = dirs;
124 unsigned old_len = strlen(old);
125 unsigned slen = strlen(s);
126 dirs = new char[old_len + 1 + slen + 1];
127 memcpy(dirs, old, old_len - init_len);
128 char *p = dirs;
129 p += old_len - init_len;
130 if (init_len == 0)
131 *p++ = PATH_SEP_CHAR;
132 memcpy(p, s, slen);
133 p += slen;
134 if (init_len > 0) {
135 *p++ = PATH_SEP_CHAR;
136 memcpy(p, old + old_len - init_len, init_len);
137 p += init_len;
139 *p++ = '\0';
140 a_delete old;
143 file_case *search_path::open_file(char const *name, uint32_t flags)
145 assert(name != NULL);
147 file_case *fcp;
148 if (IS_ABSOLUTE(name) || *dirs == '\0')
149 fcp = file_case::muxer(name, flags);
150 else
151 fcp = _try_iter(dirs, name, flags);
152 return fcp;
155 file_case *search_path::open_file_cautious(char const *name, uint32_t flags)
157 file_case *fcp;
158 if (name == NULL || strcmp(name, "-") == 0) {
159 name = NULL;
160 goto jmuxer;
162 if (IS_ABSOLUTE(name) || *dirs == '\0')
163 jmuxer:
164 fcp = file_case::muxer(name, flags);
165 else
166 fcp = _try_iter(dirs, name, flags);
167 return fcp;