1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1985-2009 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 23 /* 24 * Glenn Fowler 25 * AT&T Research 26 * 27 * include style search support 28 */ 29 30 #include <ast.h> 31 #include <error.h> 32 #include <ls.h> 33 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"))) 36 37 typedef struct Dir_s /* directory list element */ 38 { 39 struct Dir_s* next; /* next in list */ 40 char dir[1]; /* directory path */ 41 } Dir_t; 42 43 static struct /* directory list state */ 44 { 45 Dir_t* head; /* directory list head */ 46 Dir_t* tail; /* directory list tail */ 47 } state; 48 49 /* 50 * append dir to pathfind() include list 51 */ 52 53 int 54 pathinclude(const char* dir) 55 { 56 register Dir_t* dp; 57 struct stat st; 58 59 if (dir && *dir && !streq(dir, ".") && directory(dir, &st)) 60 { 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; 72 } 73 return 0; 74 } 75 76 /* 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) 82 */ 83 84 char* 85 pathfind(const char* name, const char* lib, const char* type, char* buf, size_t size) 86 { 87 register Dir_t* dp; 88 register char* s; 89 char tmp[PATH_MAX]; 90 struct stat st; 91 92 if (((s = strrchr(name, '/')) || (s = (char*)name)) && strchr(s, '.')) 93 type = 0; 94 95 /* 96 * always check the unadorned path first 97 * this handles . and absolute paths 98 */ 99 100 if (regular(name, &st)) 101 { 102 strncopy(buf, name, size); 103 return buf; 104 } 105 if (type) 106 { 107 sfsprintf(buf, size, "%s.%s", name, type); 108 if (regular(buf, &st)) 109 return buf; 110 } 111 if (*name == '/') 112 return 0; 113 114 /* 115 * check the directory of the including file 116 * on the assumption that error_info.file is properly stacked 117 */ 118 119 if (error_info.file && (s = strrchr(error_info.file, '/'))) 120 { 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) 125 { 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; 129 } 130 } 131 132 /* 133 * check the include dir list 134 */ 135 136 for (dp = state.head; dp; dp = dp->next) 137 { 138 sfsprintf(tmp, sizeof(tmp), "%s/%s", dp->dir, name); 139 if (pathpath(buf, tmp, "", PATH_REGULAR)) 140 return buf; 141 if (type) 142 { 143 sfsprintf(tmp, sizeof(tmp), "%s/%s.%s", dp->dir, name, type); 144 if (pathpath(buf, tmp, "", PATH_REGULAR)) 145 return buf; 146 } 147 } 148 149 /* 150 * finally a lib related search on PATH 151 */ 152 153 if (lib) 154 { 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) 161 { 162 sfsprintf(tmp, sizeof(tmp), "lib/%s/%s.%s", lib, name, type); 163 if (pathpath(buf, tmp, "", PATH_REGULAR)) 164 return buf; 165 } 166 } 167 return 0; 168 } 169