1da2e3ebdSchin /***********************************************************************
2da2e3ebdSchin * *
3da2e3ebdSchin * This software is part of the ast package *
4*3e14f97fSRoger A. Faulkner * Copyright (c) 1985-2010 AT&T Intellectual Property *
5da2e3ebdSchin * and is licensed under the *
6da2e3ebdSchin * Common Public License, Version 1.0 *
77c2fbfb3SApril Chin * by AT&T Intellectual Property *
8da2e3ebdSchin * *
9da2e3ebdSchin * A copy of the License is available at *
10da2e3ebdSchin * http://www.opensource.org/licenses/cpl1.0.txt *
11da2e3ebdSchin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12da2e3ebdSchin * *
13da2e3ebdSchin * Information and Software Systems Research *
14da2e3ebdSchin * AT&T Research *
15da2e3ebdSchin * Florham Park NJ *
16da2e3ebdSchin * *
17da2e3ebdSchin * Glenn Fowler <gsf@research.att.com> *
18da2e3ebdSchin * David Korn <dgk@research.att.com> *
19da2e3ebdSchin * Phong Vo <kpv@research.att.com> *
20da2e3ebdSchin * *
21da2e3ebdSchin ***********************************************************************/
22da2e3ebdSchin #pragma prototyped
23da2e3ebdSchin /*
24da2e3ebdSchin * Glenn Fowler
25da2e3ebdSchin * AT&T Research
26da2e3ebdSchin *
27da2e3ebdSchin * include style search support
28da2e3ebdSchin */
29da2e3ebdSchin
30da2e3ebdSchin #include <ast.h>
31da2e3ebdSchin #include <error.h>
32da2e3ebdSchin #include <ls.h>
33da2e3ebdSchin
34da2e3ebdSchin #define directory(p,s) (stat((p),(s))>=0&&S_ISDIR((s)->st_mode))
35da2e3ebdSchin #define regular(p,s) (stat((p),(s))>=0&&(S_ISREG((s)->st_mode)||streq(p,"/dev/null")))
36da2e3ebdSchin
37da2e3ebdSchin typedef struct Dir_s /* directory list element */
38da2e3ebdSchin {
39da2e3ebdSchin struct Dir_s* next; /* next in list */
40da2e3ebdSchin char dir[1]; /* directory path */
41da2e3ebdSchin } Dir_t;
42da2e3ebdSchin
43da2e3ebdSchin static struct /* directory list state */
44da2e3ebdSchin {
45da2e3ebdSchin Dir_t* head; /* directory list head */
46da2e3ebdSchin Dir_t* tail; /* directory list tail */
47da2e3ebdSchin } state;
48da2e3ebdSchin
49da2e3ebdSchin /*
50da2e3ebdSchin * append dir to pathfind() include list
51da2e3ebdSchin */
52da2e3ebdSchin
53da2e3ebdSchin int
pathinclude(const char * dir)54da2e3ebdSchin pathinclude(const char* dir)
55da2e3ebdSchin {
56da2e3ebdSchin register Dir_t* dp;
57da2e3ebdSchin struct stat st;
58da2e3ebdSchin
59da2e3ebdSchin if (dir && *dir && !streq(dir, ".") && directory(dir, &st))
60da2e3ebdSchin {
61da2e3ebdSchin for (dp = state.head; dp; dp = dp->next)
62da2e3ebdSchin if (streq(dir, dp->dir))
63da2e3ebdSchin return 0;
64da2e3ebdSchin if (!(dp = oldof(0, Dir_t, 1, strlen(dir))))
65da2e3ebdSchin return -1;
66da2e3ebdSchin strcpy(dp->dir, dir);
67da2e3ebdSchin dp->next = 0;
68da2e3ebdSchin if (state.tail)
69da2e3ebdSchin state.tail = state.tail->next = dp;
70da2e3ebdSchin else
71da2e3ebdSchin state.head = state.tail = dp;
72da2e3ebdSchin }
73da2e3ebdSchin return 0;
74da2e3ebdSchin }
75da2e3ebdSchin
76da2e3ebdSchin /*
77da2e3ebdSchin * return path to name using pathinclude() list
78da2e3ebdSchin * path placed in <buf,size>
79da2e3ebdSchin * if lib!=0 then pathpath() attempted after include search
80da2e3ebdSchin * if type!=0 and name has no '.' then file.type also attempted
81da2e3ebdSchin * any *: prefix in lib is ignored (discipline library dictionary support)
82da2e3ebdSchin */
83da2e3ebdSchin
84da2e3ebdSchin char*
pathfind(const char * name,const char * lib,const char * type,char * buf,size_t size)85da2e3ebdSchin pathfind(const char* name, const char* lib, const char* type, char* buf, size_t size)
86da2e3ebdSchin {
87da2e3ebdSchin register Dir_t* dp;
88da2e3ebdSchin register char* s;
89da2e3ebdSchin char tmp[PATH_MAX];
90da2e3ebdSchin struct stat st;
91da2e3ebdSchin
92da2e3ebdSchin if (((s = strrchr(name, '/')) || (s = (char*)name)) && strchr(s, '.'))
93da2e3ebdSchin type = 0;
94da2e3ebdSchin
95da2e3ebdSchin /*
96da2e3ebdSchin * always check the unadorned path first
97da2e3ebdSchin * this handles . and absolute paths
98da2e3ebdSchin */
99da2e3ebdSchin
100da2e3ebdSchin if (regular(name, &st))
101da2e3ebdSchin {
102da2e3ebdSchin strncopy(buf, name, size);
103da2e3ebdSchin return buf;
104da2e3ebdSchin }
105da2e3ebdSchin if (type)
106da2e3ebdSchin {
107da2e3ebdSchin sfsprintf(buf, size, "%s.%s", name, type);
108da2e3ebdSchin if (regular(buf, &st))
109da2e3ebdSchin return buf;
110da2e3ebdSchin }
111da2e3ebdSchin if (*name == '/')
112da2e3ebdSchin return 0;
113da2e3ebdSchin
114da2e3ebdSchin /*
115da2e3ebdSchin * check the directory of the including file
116da2e3ebdSchin * on the assumption that error_info.file is properly stacked
117da2e3ebdSchin */
118da2e3ebdSchin
119da2e3ebdSchin if (error_info.file && (s = strrchr(error_info.file, '/')))
120da2e3ebdSchin {
121da2e3ebdSchin sfsprintf(buf, size, "%-.*s%s", s - error_info.file + 1, error_info.file, name);
122da2e3ebdSchin if (regular(buf, &st))
123da2e3ebdSchin return buf;
124da2e3ebdSchin if (type)
125da2e3ebdSchin {
126da2e3ebdSchin sfsprintf(buf, size, "%-.*s%s%.s", s - error_info.file + 1, error_info.file, name, type);
127da2e3ebdSchin if (regular(buf, &st))
128da2e3ebdSchin return buf;
129da2e3ebdSchin }
130da2e3ebdSchin }
131da2e3ebdSchin
132da2e3ebdSchin /*
133da2e3ebdSchin * check the include dir list
134da2e3ebdSchin */
135da2e3ebdSchin
136da2e3ebdSchin for (dp = state.head; dp; dp = dp->next)
137da2e3ebdSchin {
138da2e3ebdSchin sfsprintf(tmp, sizeof(tmp), "%s/%s", dp->dir, name);
139da2e3ebdSchin if (pathpath(buf, tmp, "", PATH_REGULAR))
140da2e3ebdSchin return buf;
141da2e3ebdSchin if (type)
142da2e3ebdSchin {
143da2e3ebdSchin sfsprintf(tmp, sizeof(tmp), "%s/%s.%s", dp->dir, name, type);
144da2e3ebdSchin if (pathpath(buf, tmp, "", PATH_REGULAR))
145da2e3ebdSchin return buf;
146da2e3ebdSchin }
147da2e3ebdSchin }
148da2e3ebdSchin
149da2e3ebdSchin /*
150da2e3ebdSchin * finally a lib related search on PATH
151da2e3ebdSchin */
152da2e3ebdSchin
153da2e3ebdSchin if (lib)
154da2e3ebdSchin {
155da2e3ebdSchin if (s = strrchr((char*)lib, ':'))
156da2e3ebdSchin lib = (const char*)s + 1;
157da2e3ebdSchin sfsprintf(tmp, sizeof(tmp), "lib/%s/%s", lib, name);
158da2e3ebdSchin if (pathpath(buf, tmp, "", PATH_REGULAR))
159da2e3ebdSchin return buf;
160da2e3ebdSchin if (type)
161da2e3ebdSchin {
162da2e3ebdSchin sfsprintf(tmp, sizeof(tmp), "lib/%s/%s.%s", lib, name, type);
163da2e3ebdSchin if (pathpath(buf, tmp, "", PATH_REGULAR))
164da2e3ebdSchin return buf;
165da2e3ebdSchin }
166da2e3ebdSchin }
167da2e3ebdSchin return 0;
168da2e3ebdSchin }
169