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