1 /***********************************************************************
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 *
9 * A copy of the License is available at *
10 * http://www.opensource.org/licenses/cpl1.0.txt *
11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
13 * Information and Software Systems Research *
17 * Glenn Fowler <gsf@research.att.com> *
18 * David Korn <dgk@research.att.com> *
19 * Phong Vo <kpv@research.att.com> *
21 ***********************************************************************/
27 * include style search support
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 */
43 static struct /* directory list state */
45 Dir_t
* head
; /* directory list head */
46 Dir_t
* tail
; /* directory list tail */
50 * append dir to pathfind() include list
54 pathinclude(const char* dir
)
59 if (dir
&& *dir
&& !streq(dir
, ".") && directory(dir
, &st
))
61 for (dp
= state
.head
; dp
; dp
= dp
->next
)
62 if (streq(dir
, dp
->dir
))
64 if (!(dp
= oldof(0, Dir_t
, 1, strlen(dir
))))
69 state
.tail
= state
.tail
->next
= dp
;
71 state
.head
= state
.tail
= dp
;
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)
85 pathfind(const char* name
, const char* lib
, const char* type
, char* buf
, size_t size
)
92 if (((s
= strrchr(name
, '/')) || (s
= (char*)name
)) && strchr(s
, '.'))
96 * always check the unadorned path first
97 * this handles . and absolute paths
100 if (regular(name
, &st
))
102 strncopy(buf
, name
, size
);
107 sfsprintf(buf
, size
, "%s.%s", name
, type
);
108 if (regular(buf
, &st
))
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
))
126 sfsprintf(buf
, size
, "%-.*s%s%.s", s
- error_info
.file
+ 1, error_info
.file
, name
, type
);
127 if (regular(buf
, &st
))
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
))
143 sfsprintf(tmp
, sizeof(tmp
), "%s/%s.%s", dp
->dir
, name
, type
);
144 if (pathpath(buf
, tmp
, "", PATH_REGULAR
))
150 * finally a lib related search on PATH
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
))
162 sfsprintf(tmp
, sizeof(tmp
), "lib/%s/%s.%s", lib
, name
, type
);
163 if (pathpath(buf
, tmp
, "", PATH_REGULAR
))