]> git.sur5r.net Git - cc65/blob - src/common/searchpath.c
PushSearchPath will add the path only if it's not already there.
[cc65] / src / common / searchpath.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                               searchpath.h                                */
4 /*                                                                           */
5 /*                         Handling of search paths                          */
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 /*                                   Code                                    */
56 /*****************************************************************************/
57
58
59
60 static char* CleanupPath (const char* Path)
61 /* Prepare and return a clean copy of Path */
62 {
63     unsigned Len;
64     char*    NewPath;
65
66     /* Get the length of the path */
67     Len = strlen (Path);
68
69     /* Check for a trailing path separator and remove it */
70     if (Len > 0 && (Path[Len-1] == '\\' || Path[Len-1] == '/')) {
71         --Len;
72     }
73
74     /* Allocate memory for the new string */
75     NewPath = (char*) xmalloc (Len + 1);
76
77     /* Copy the path and terminate it, then return the copy */
78     memcpy (NewPath, Path, Len);
79     NewPath [Len] = '\0';
80     return NewPath;
81 }
82
83
84
85 static void Add (SearchPath* P, const char* New)
86 /* Cleanup a new search path and add it to the list */
87 {
88     /* Add a clean copy of the path to the collection */
89     CollAppend (P, CleanupPath (New));
90 }
91
92
93
94 SearchPath* NewSearchPath (void)
95 /* Create a new, empty search path list */
96 {
97     return NewCollection ();
98 }
99
100
101
102 void AddSearchPath (SearchPath* P, const char* NewPath)
103 /* Add a new search path to the end of an existing list */
104 {
105     /* Allow a NULL path */
106     if (NewPath) {
107         Add (P, NewPath);
108     }
109 }
110
111
112
113 void AddSearchPathFromEnv (SearchPath* P, const char* EnvVar)
114 /* Add a search path from an environment variable to the end of an existing
115  * list.
116  */
117 {
118     AddSearchPath (P, getenv (EnvVar));
119 }
120
121
122
123 void AddSubSearchPathFromEnv (SearchPath* P, const char* EnvVar, const char* SubDir)
124 /* Add a search path from an environment variable, adding a subdirectory to
125  * the environment variable value.
126  */
127 {
128     StrBuf Dir = AUTO_STRBUF_INITIALIZER;
129
130     const char* EnvVal = getenv (EnvVar);
131     if (EnvVal == 0) {
132         /* Not found */
133         return;
134     }
135
136     /* Copy the environment variable to the buffer */
137     SB_CopyStr (&Dir, EnvVal);
138
139     /* Add a path separator if necessary */
140     if (SB_NotEmpty (&Dir)) {
141         if (SB_LookAtLast (&Dir) != '\\' && SB_LookAtLast (&Dir) != '/') {
142             SB_AppendChar (&Dir, '/');
143         }
144     }
145
146     /* Add the subdirectory and terminate the string */
147     SB_AppendStr (&Dir, SubDir);
148     SB_Terminate (&Dir);
149
150     /* Add the search path */
151     AddSearchPath (P, SB_GetConstBuf (&Dir));
152
153     /* Free the temp buffer */
154     SB_Done (&Dir);
155 }
156
157
158
159 int PushSearchPath (SearchPath* P, const char* NewPath)
160 /* Add a new search path to the head of an existing search path list, provided
161  * that it's not already there. If the path is already at the first position,
162  * return zero, otherwise return a non zero value.
163  */
164 {                                      
165     /* Generate a clean copy of NewPath */
166     char* Path = CleanupPath (NewPath);   
167
168     /* If we have paths, check if Path is already at position zero */
169     if (CollCount (P) > 0 && strcmp (CollConstAt (P, 0), Path) == 0) {
170         /* Match. Delete the copy and return to the caller */
171         xfree (Path);
172         return 0;
173     }
174
175     /* Insert a clean copy of the path at position 0, return success */
176     CollInsert (P, Path, 0);
177     return 1;
178 }
179
180
181
182 void PopSearchPath (SearchPath* P)
183 /* Remove a search path from the head of an existing search path list */
184 {
185     /* Remove the path at position 0 */
186     xfree (CollAt (P, 0));
187     CollDelete (P, 0);
188 }
189
190
191
192 void ForgetSearchPath (SearchPath* P)
193 /* Forget all search paths in the given list */
194 {
195     unsigned I;
196     for (I = 0; I < CollCount (P); ++I) {
197         xfree (CollAt (P, I));
198     }
199     CollDeleteAll (P);
200 }
201
202
203
204 char* SearchFile (const SearchPath* P, const char* File)
205 /* Search for a file in a list of directories. Return a pointer to a malloced
206  * area that contains the complete path, if found, return 0 otherwise.
207  */
208 {
209     char* Name = 0;
210     StrBuf PathName = AUTO_STRBUF_INITIALIZER;
211
212     /* Start the search */
213     unsigned I;
214     for (I = 0; I < CollCount (P); ++I) {
215
216         /* Copy the next path element into the buffer */
217         SB_CopyStr (&PathName, CollConstAt (P, I));
218
219         /* Add a path separator and the filename */
220         if (SB_NotEmpty (&PathName)) {
221             SB_AppendChar (&PathName, '/');
222         }
223         SB_AppendStr (&PathName, File);
224         SB_Terminate (&PathName);
225
226         /* Check if this file exists */
227         if (access (SB_GetBuf (&PathName), 0) == 0) {
228             /* The file exists, we're done */
229             Name = xstrdup (SB_GetBuf (&PathName));
230             break;
231         }
232     }
233
234     /* Cleanup and return the result of the search */
235     SB_Done (&PathName);
236     return Name;
237 }
238
239
240