]> git.sur5r.net Git - cc65/blob - src/common/searchpath.c
Only for jumps, the lib uses named asm labels in branches
[cc65] / src / common / searchpath.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                               searchpath.h                                */
4 /*                                                                           */
5 /*                         Handling of search paths                          */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2013, 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(_WIN32)
39 #  include <windows.h>
40 #endif
41 #if defined(_MSC_VER)
42 /* Microsoft compiler */
43 #  include <io.h>
44 #else
45 /* Anyone else */
46 #  include <unistd.h>
47 #endif
48
49 /* common */
50 #include "coll.h"
51 #include "searchpath.h"
52 #include "strbuf.h"
53 #include "xmalloc.h"
54
55
56
57 /*****************************************************************************/
58 /*                                   Code                                    */
59 /*****************************************************************************/
60
61
62
63 static char* CleanupPath (const char* Path)
64 /* Prepare and return a clean copy of Path */
65 {
66     unsigned Len;
67     char*    NewPath;
68
69     /* Get the length of the path */
70     Len = strlen (Path);
71
72     /* Check for a trailing path separator and remove it */
73     if (Len > 0 && (Path[Len-1] == '\\' || Path[Len-1] == '/')) {
74         --Len;
75     }
76
77     /* Allocate memory for the new string */
78     NewPath = (char*) xmalloc (Len + 1);
79
80     /* Copy the path and terminate it, then return the copy */
81     memcpy (NewPath, Path, Len);
82     NewPath [Len] = '\0';
83     return NewPath;
84 }
85
86
87
88 static void Add (SearchPaths* P, const char* New)
89 /* Cleanup a new search path and add it to the list */
90 {
91     /* Add a clean copy of the path to the collection */
92     CollAppend (P, CleanupPath (New));
93 }
94
95
96
97 SearchPaths* NewSearchPath (void)
98 /* Create a new, empty search path list */
99 {
100     return NewCollection ();
101 }
102
103
104
105 void AddSearchPath (SearchPaths* P, const char* NewPath)
106 /* Add a new search path to the end of an existing list */
107 {
108     /* Allow a NULL path */
109     if (NewPath) {
110         Add (P, NewPath);
111     }
112 }
113
114
115
116 void AddSearchPathFromEnv (SearchPaths* P, const char* EnvVar)
117 /* Add a search path from an environment variable to the end of an existing
118 ** list.
119 */
120 {
121     AddSearchPath (P, getenv (EnvVar));
122 }
123
124
125
126 void AddSubSearchPathFromEnv (SearchPaths* P, const char* EnvVar, const char* SubDir)
127 /* Add a search path from an environment variable, adding a subdirectory to
128 ** the environment variable value.
129 */
130 {
131     StrBuf Dir = AUTO_STRBUF_INITIALIZER;
132
133     const char* EnvVal = getenv (EnvVar);
134     if (EnvVal == 0) {
135         /* Not found */
136         return;
137     }
138
139     /* Copy the environment variable to the buffer */
140     SB_CopyStr (&Dir, EnvVal);
141
142     /* Add a path separator if necessary */
143     if (SB_NotEmpty (&Dir)) {
144         if (SB_LookAtLast (&Dir) != '\\' && SB_LookAtLast (&Dir) != '/') {
145             SB_AppendChar (&Dir, '/');
146         }
147     }
148
149     /* Add the subdirectory and terminate the string */
150     SB_AppendStr (&Dir, SubDir);
151     SB_Terminate (&Dir);
152
153     /* Add the search path */
154     AddSearchPath (P, SB_GetConstBuf (&Dir));
155
156     /* Free the temp buffer */
157     SB_Done (&Dir);
158 }
159
160
161
162 void AddSubSearchPathFromWinBin (SearchPaths* P, const char* SubDir)
163 {
164 /* Windows only:
165 ** Add a search path from the running binary, adding a subdirectory to
166 ** the parent directory of the directory containing the binary.
167 */
168 #if defined(_WIN32)
169
170     char Dir[_MAX_PATH];
171     char* Ptr;
172
173     if (GetModuleFileName (NULL, Dir, _MAX_PATH) == 0) {
174         return;
175     }
176
177     /* Remove binary name */
178     Ptr = strrchr (Dir, '\\');
179     if (Ptr == 0) {
180         return;
181     }
182     *Ptr = '\0';
183
184     /* Check for 'bin' directory */
185     Ptr = strrchr (Dir, '\\');
186     if (Ptr == 0) {
187         return;
188     }
189     if (strcmp (Ptr++, "\\bin") != 0) {
190         return;
191     }
192
193     /* Append SubDir */
194     strcpy (Ptr, SubDir);
195
196     /* Add the search path */
197     AddSearchPath (P, Dir);
198
199 #else
200
201     (void) P;
202     (void) SubDir;
203
204 #endif
205 }
206
207
208 int PushSearchPath (SearchPaths* P, const char* NewPath)
209 /* Add a new search path to the head of an existing search path list, provided
210 ** that it's not already there. If the path is already at the first position,
211 ** return zero, otherwise return a non zero value.
212 */
213 {                                      
214     /* Generate a clean copy of NewPath */
215     char* Path = CleanupPath (NewPath);   
216
217     /* If we have paths, check if Path is already at position zero */
218     if (CollCount (P) > 0 && strcmp (CollConstAt (P, 0), Path) == 0) {
219         /* Match. Delete the copy and return to the caller */
220         xfree (Path);
221         return 0;
222     }
223
224     /* Insert a clean copy of the path at position 0, return success */
225     CollInsert (P, Path, 0);
226     return 1;
227 }
228
229
230
231 void PopSearchPath (SearchPaths* P)
232 /* Remove a search path from the head of an existing search path list */
233 {
234     /* Remove the path at position 0 */
235     xfree (CollAt (P, 0));
236     CollDelete (P, 0);
237 }
238
239
240
241 char* GetSearchPath (SearchPaths* P, unsigned Index)
242 /* Return the search path at the given index, if the index is valid, return an
243 ** empty string otherwise.
244 */
245 {
246     if (Index < CollCount (P))
247         return CollAtUnchecked (P, Index);
248     return "";
249 }
250
251
252
253 char* SearchFile (const SearchPaths* P, const char* File)
254 /* Search for a file in a list of directories. Return a pointer to a malloced
255 ** area that contains the complete path, if found, return 0 otherwise.
256 */
257 {
258     char* Name = 0;
259     StrBuf PathName = AUTO_STRBUF_INITIALIZER;
260
261     /* Start the search */
262     unsigned I;
263     for (I = 0; I < CollCount (P); ++I) {
264
265         /* Copy the next path element into the buffer */
266         SB_CopyStr (&PathName, CollConstAt (P, I));
267
268         /* Add a path separator and the filename */
269         if (SB_NotEmpty (&PathName)) {
270             SB_AppendChar (&PathName, '/');
271         }
272         SB_AppendStr (&PathName, File);
273         SB_Terminate (&PathName);
274
275         /* Check if this file exists */
276         if (access (SB_GetBuf (&PathName), 0) == 0) {
277             /* The file exists, we're done */
278             Name = xstrdup (SB_GetBuf (&PathName));
279             break;
280         }
281     }
282
283     /* Cleanup and return the result of the search */
284     SB_Done (&PathName);
285     return Name;
286 }