]> git.sur5r.net Git - cc65/blob - src/common/searchpath.c
d71326b8b170e14151b98b062d87b4493952d52e
[cc65] / src / common / searchpath.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                               searchpath.h                                */
4 /*                                                                           */
5 /*                    Search path path handling for ld65                     */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2010, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdlib.h>
37 #include <string.h>
38 #if defined(_MSC_VER)
39 /* Microsoft compiler */
40 #  include <io.h>
41 #else
42 /* Anyone else */
43 #  include <unistd.h>
44 #endif
45
46 /* common */
47 #include "coll.h"
48 #include "searchpath.h"
49 #include "strbuf.h"
50 #include "xmalloc.h"
51
52
53
54 /*****************************************************************************/
55 /*                                   Data                                    */
56 /*****************************************************************************/
57
58
59
60 /* A search path list is a collection containing path elements. We have
61  * several of those.
62  */
63 static Collection SearchPaths[MAX_SEARCH_PATHS] = {
64     STATIC_COLLECTION_INITIALIZER,
65     STATIC_COLLECTION_INITIALIZER,
66     STATIC_COLLECTION_INITIALIZER,
67     STATIC_COLLECTION_INITIALIZER,
68     STATIC_COLLECTION_INITIALIZER,
69     STATIC_COLLECTION_INITIALIZER,
70     STATIC_COLLECTION_INITIALIZER,
71     STATIC_COLLECTION_INITIALIZER,
72 };
73
74
75
76 /*****************************************************************************/
77 /*                                   Code                                    */
78 /*****************************************************************************/
79
80
81
82 static void Add (Collection* Paths, const char* New)
83 /* Cleanup a new search path and add it to the list */
84 {
85     unsigned NewLen;
86     char*    NewPath;
87
88     /* Get the length of the new path */
89     NewLen = strlen (New);
90
91     /* Check for a trailing path separator and remove it */
92     if (NewLen > 0 && (New[NewLen-1] == '\\' || New[NewLen-1] == '/')) {
93         --NewLen;
94     }
95
96     /* Allocate memory for the new string */
97     NewPath = (char*) xmalloc (NewLen + 1);
98
99     /* Copy the path and terminate it */
100     memcpy (NewPath, New, NewLen);
101     NewPath [NewLen] = '\0';
102
103     /* Add the path to the collection */
104     CollAppend (Paths, NewPath);
105 }
106
107
108
109 static char* Find (const Collection* PathList, const char* File)
110 /* Search for a file in a list of directories. If found, return the complete
111  * name including the path in a malloced data area, if not found, return 0.
112  */
113 {               
114     char* Name = 0;
115     StrBuf PathName = AUTO_STRBUF_INITIALIZER;
116
117     /* Start the search */
118     unsigned I;
119     for (I = 0; I < CollCount (PathList); ++I) {
120
121         /* Copy the next path element into the buffer */
122         SB_CopyStr (&PathName, CollConstAt (PathList, I));
123
124         /* Add a path separator and the filename */
125         if (SB_NotEmpty (&PathName)) {
126             SB_AppendChar (&PathName, '/');
127         }
128         SB_AppendStr (&PathName, File);
129         SB_Terminate (&PathName);
130
131         /* Check if this file exists */
132         if (access (SB_GetBuf (&PathName), 0) == 0) {
133             /* The file exists, we're done */
134             Name = xstrdup (SB_GetBuf (&PathName));
135             break;
136         }
137     }
138
139     /* Cleanup and return the result of the search */
140     SB_Done (&PathName);
141     return Name;
142 }
143
144
145
146 void AddSearchPath (const char* NewPath, unsigned Where)
147 /* Add a new search path to the existing one */
148 {
149     /* Allow a NULL path */
150     if (NewPath) {
151         unsigned I;
152         for (I = 0; I < MAX_SEARCH_PATHS; ++I) {
153             if (Where & (0x01U << I)) {
154                 Add (&SearchPaths[I], NewPath);
155             }
156         }
157     }
158 }
159
160
161
162 void AddSearchPathFromEnv (const char* EnvVar, unsigned Where)
163 /* Add a search path from an environment variable */
164 {
165     AddSearchPath (getenv (EnvVar), Where);
166 }
167
168
169
170 void AddSubSearchPathFromEnv (const char* EnvVar, const char* SubDir, unsigned Where)
171 /* Add a search path from an environment variable, adding a subdirectory to
172  * the environment variable value.
173  */
174 {
175     StrBuf Dir = AUTO_STRBUF_INITIALIZER;
176
177     const char* EnvVal = getenv (EnvVar);
178     if (EnvVal == 0) {
179         /* Not found */
180         return;
181     }
182
183     /* Copy the environment variable to the buffer */
184     SB_CopyStr (&Dir, EnvVal);
185
186     /* Add a path separator if necessary */
187     if (SB_NotEmpty (&Dir)) {
188         if (SB_LookAtLast (&Dir) != '\\' && SB_LookAtLast (&Dir) != '/') {
189             SB_AppendChar (&Dir, '/');
190         }
191     }
192
193     /* Add the subdirectory */
194     SB_AppendStr (&Dir, SubDir);
195
196     /* Terminate the string */
197     SB_Terminate (&Dir);
198
199     /* Add the search path */
200     AddSearchPath (SB_GetConstBuf (&Dir), Where);
201
202     /* Free the temp buffer */
203     SB_Done (&Dir);
204 }
205
206
207
208 void ForgetAllSearchPaths (unsigned Where)
209 /* Forget all search paths in the given lists. */
210 {
211     unsigned I;
212     for (I = 0; I < MAX_SEARCH_PATHS; ++I) {
213         if (Where & (0x01U << I)) {
214             unsigned J;
215             Collection* P = &SearchPaths[I];
216             for (J = 0; J < CollCount (P); ++J) {
217                 xfree (CollAt (P, J));
218             }
219             CollDeleteAll (P);
220         }
221     }
222 }
223
224
225
226 char* SearchFile (const char* Name, unsigned Where)
227 /* Search for a file in a list of directories. Return a pointer to a malloced
228  * area that contains the complete path, if found, return 0 otherwise.
229  */
230 {
231     unsigned I;
232     for (I = 0; I < MAX_SEARCH_PATHS; ++I) {
233         if (Where & (0x01U << I)) {
234             char* Path = Find (&SearchPaths[I], Name);
235             if (Path) {
236                 /* Found the file */
237                 return Path;
238             }
239         }
240     }
241     return 0;
242 }
243
244
245