Get rid of the old texinfo.
[dragonfly.git] / contrib / groff / src / libs / libgroff / searchpath.cc
1 // -*- C++ -*-
2 /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
3    Free Software Foundation, Inc.
4      Written by James Clark (jjc@jclark.com)
5
6 This file is part of groff.
7
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.
12
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.
17
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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22 #include "lib.h"
23
24 #include <stdlib.h>
25 #include <assert.h>
26
27 #include "searchpath.h"
28 #include "nonposix.h"
29
30 search_path::search_path(const char *envvar, const char *standard,
31                          int add_home, int add_current)
32 {
33   char *home = 0;
34   if (add_home)
35     home = getenv("HOME");
36   char *e = 0;
37   if (envvar)
38     e = getenv(envvar);
39   dirs = new char[((e && *e) ? strlen(e) + 1 : 0)
40                   + (add_current ? 1 + 1 : 0)
41                   + ((home && *home) ? strlen(home) + 1 : 0)
42                   + ((standard && *standard) ? strlen(standard) : 0)
43                   + 1];
44   *dirs = '\0';
45   if (e && *e) {
46     strcat(dirs, e);
47     strcat(dirs, PATH_SEP);
48   }
49   if (add_current) {
50     strcat(dirs, ".");
51     strcat(dirs, PATH_SEP);
52   }
53   if (home && *home) {
54     strcat(dirs, home);
55     strcat(dirs, PATH_SEP);
56   }
57   if (standard && *standard)
58     strcat(dirs, standard);
59   init_len = strlen(dirs);
60 }
61
62 search_path::~search_path()
63 {
64   // dirs is always allocated
65   a_delete dirs;
66 }
67
68 void search_path::command_line_dir(const char *s)
69 {
70   char *old = dirs;
71   unsigned old_len = strlen(old);
72   unsigned slen = strlen(s);
73   dirs = new char[old_len + 1 + slen + 1];
74   memcpy(dirs, old, old_len - init_len);
75   char *p = dirs;
76   p += old_len - init_len;
77   if (init_len == 0)
78     *p++ = PATH_SEP[0];
79   memcpy(p, s, slen);
80   p += slen;
81   if (init_len > 0) {
82     *p++ = PATH_SEP[0];
83     memcpy(p, old + old_len - init_len, init_len);
84     p += init_len;
85   }
86   *p++ = '\0';
87   a_delete old;
88 }
89
90 FILE *search_path::open_file(const char *name, char **pathp)
91 {
92   assert(name != 0);
93   if (IS_ABSOLUTE(name) || *dirs == '\0') {
94     FILE *fp = fopen(name, "r");
95     if (fp) {
96       if (pathp)
97         *pathp = strsave(name);
98       return fp;
99     }
100     else
101       return 0;
102   }
103   unsigned namelen = strlen(name);
104   char *p = dirs;
105   for (;;) {
106     char *end = strchr(p, PATH_SEP[0]);
107     if (!end)
108       end = strchr(p, '\0');
109     int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0;
110     char *path = new char[(end - p) + need_slash + namelen + 1];
111     memcpy(path, p, end - p);
112     if (need_slash)
113       path[end - p] = '/';
114     strcpy(path + (end - p) + need_slash, name);
115 #if 0
116     fprintf(stderr, "trying `%s'\n", path);
117 #endif
118     FILE *fp = fopen(path, "r");
119     if (fp) {
120       if (pathp)
121         *pathp = path;
122       else
123         a_delete path;
124       return fp;
125     }
126     a_delete path;
127     if (*end == '\0')
128       break;
129     p = end + 1;
130   }
131   return 0;
132 }