dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / libast / common / path / pathfind.c
blob8a4c2fb2369acfd443ad4bf4a5350130b5347724
1 /***********************************************************************
2 * *
3 * This software is part of the ast package *
4 * Copyright (c) 1985-2010 AT&T Intellectual Property *
5 * and is licensed under the *
6 * Common Public License, Version 1.0 *
7 * by AT&T Intellectual Property *
8 * *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
12 * *
13 * Information and Software Systems Research *
14 * AT&T Research *
15 * Florham Park NJ *
16 * *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
20 * *
21 ***********************************************************************/
22 #pragma prototyped
24 * Glenn Fowler
25 * AT&T Research
27 * include style search support
30 #include <ast.h>
31 #include <error.h>
32 #include <ls.h>
34 #define directory(p,s) (stat((p),(s))>=0&&S_ISDIR((s)->st_mode))
35 #define regular(p,s) (stat((p),(s))>=0&&(S_ISREG((s)->st_mode)||streq(p,"/dev/null")))
37 typedef struct Dir_s /* directory list element */
39 struct Dir_s* next; /* next in list */
40 char dir[1]; /* directory path */
41 } Dir_t;
43 static struct /* directory list state */
45 Dir_t* head; /* directory list head */
46 Dir_t* tail; /* directory list tail */
47 } state;
50 * append dir to pathfind() include list
53 int
54 pathinclude(const char* dir)
56 register Dir_t* dp;
57 struct stat st;
59 if (dir && *dir && !streq(dir, ".") && directory(dir, &st))
61 for (dp = state.head; dp; dp = dp->next)
62 if (streq(dir, dp->dir))
63 return 0;
64 if (!(dp = oldof(0, Dir_t, 1, strlen(dir))))
65 return -1;
66 strcpy(dp->dir, dir);
67 dp->next = 0;
68 if (state.tail)
69 state.tail = state.tail->next = dp;
70 else
71 state.head = state.tail = dp;
73 return 0;
77 * return path to name using pathinclude() list
78 * path placed in <buf,size>
79 * if lib!=0 then pathpath() attempted after include search
80 * if type!=0 and name has no '.' then file.type also attempted
81 * any *: prefix in lib is ignored (discipline library dictionary support)
84 char*
85 pathfind(const char* name, const char* lib, const char* type, char* buf, size_t size)
87 register Dir_t* dp;
88 register char* s;
89 char tmp[PATH_MAX];
90 struct stat st;
92 if (((s = strrchr(name, '/')) || (s = (char*)name)) && strchr(s, '.'))
93 type = 0;
96 * always check the unadorned path first
97 * this handles . and absolute paths
100 if (regular(name, &st))
102 strncopy(buf, name, size);
103 return buf;
105 if (type)
107 sfsprintf(buf, size, "%s.%s", name, type);
108 if (regular(buf, &st))
109 return buf;
111 if (*name == '/')
112 return 0;
115 * check the directory of the including file
116 * on the assumption that error_info.file is properly stacked
119 if (error_info.file && (s = strrchr(error_info.file, '/')))
121 sfsprintf(buf, size, "%-.*s%s", s - error_info.file + 1, error_info.file, name);
122 if (regular(buf, &st))
123 return buf;
124 if (type)
126 sfsprintf(buf, size, "%-.*s%s%.s", s - error_info.file + 1, error_info.file, name, type);
127 if (regular(buf, &st))
128 return buf;
133 * check the include dir list
136 for (dp = state.head; dp; dp = dp->next)
138 sfsprintf(tmp, sizeof(tmp), "%s/%s", dp->dir, name);
139 if (pathpath(buf, tmp, "", PATH_REGULAR))
140 return buf;
141 if (type)
143 sfsprintf(tmp, sizeof(tmp), "%s/%s.%s", dp->dir, name, type);
144 if (pathpath(buf, tmp, "", PATH_REGULAR))
145 return buf;
150 * finally a lib related search on PATH
153 if (lib)
155 if (s = strrchr((char*)lib, ':'))
156 lib = (const char*)s + 1;
157 sfsprintf(tmp, sizeof(tmp), "lib/%s/%s", lib, name);
158 if (pathpath(buf, tmp, "", PATH_REGULAR))
159 return buf;
160 if (type)
162 sfsprintf(tmp, sizeof(tmp), "lib/%s/%s.%s", lib, name, type);
163 if (pathpath(buf, tmp, "", PATH_REGULAR))
164 return buf;
167 return 0;