1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1985-2011 AT&T Intellectual Property * 5* and is licensed under the * 6* Eclipse Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.eclipse.org/org/documents/epl-v10.html * 11* (with md5 checksum b35adb5213ca9657e911e9befb180842) * 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 37typedef 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 43static 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 53int 54pathinclude(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 84char* 85pathfind(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(tmp, "", PATH_REGULAR, buf, size)) 140 return buf; 141 if (type) 142 { 143 sfsprintf(tmp, sizeof(tmp), "%s/%s.%s", dp->dir, name, type); 144 if (pathpath(tmp, "", PATH_REGULAR, buf, size)) 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(tmp, "", PATH_REGULAR, buf, size)) 159 return buf; 160 if (type) 161 { 162 sfsprintf(tmp, sizeof(tmp), "lib/%s/%s.%s", lib, name, type); 163 if (pathpath(tmp, "", PATH_REGULAR, buf, size)) 164 return buf; 165 } 166 } 167 return 0; 168} 169