use same location as .configured, etc, to store .files-touched
[AROS.git] / compiler / clib / __upath.c
blob78d5a29730e172b41b03456f75276f314acf878f
2 /*
3 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
4 $Id$
6 Desc: utility internal function __path_u2a()
7 Lang: english
8 */
10 #include "__arosc_privdata.h"
12 #include <string.h>
13 #include <stdlib.h>
14 #include <errno.h>
16 static const char *__path_devstuff_u2a(const char *path);
17 static void __path_normalstuff_u2a(const char *path, char *buf);
19 #ifdef BUILD_TEST
20 static int __doupath = 1;
21 static char *__apathbuf;
22 # define realloc_nocopy realloc
23 #endif
25 /*****************************************************************************
27 NAME */
28 #include "__upath.h"
31 const char *__path_u2a(
33 /* SYNOPSIS */
34 const char *upath)
36 /* FUNCTION
37 Translates an unix-style path into an AmigaDOS one.
39 INPUTS
40 upath - Unix-style path to translate into an AmigaDOS-style equivalent.
42 RESULT
43 A pointer to a string containing the AmigaDOS-style path, or NULL in
44 case of error.
46 The pointer is valid only until next call to this function, so if
47 you need to call this function recursively, you must save the string
48 pointed to by the pointer before calling this function again.
50 NOTES
51 This function is for private usage by system code. Do not use it
52 elsewhere.
54 INTERNALS
56 SEE ALSO
58 ******************************************************************************/
60 const char *newpath;
62 /* Does the path really need to be converted? */
63 if (!__doupath)
64 return upath;
66 /* Safety check. */
67 if (upath == NULL)
69 errno = EFAULT;
70 return NULL;
73 /* Some scripts (config.guess) try to access /.attbin
74 which is MacOS-specific thing. Block it. */
75 if (!strncmp(upath, "/.attbin", 8))
77 errno = ENOENT;
78 return NULL;
82 First see whether the path is in the /dev/#? form and,
83 if so, if it's handled internally
85 newpath = __path_devstuff_u2a(upath);
86 if (!newpath)
88 /* Else, convert it normally */
89 newpath = realloc_nocopy(__apathbuf, strlen(upath) + 1);
91 if (newpath == NULL)
93 errno = ENOMEM;
94 return NULL;
97 __apathbuf = (char *)newpath;
98 __path_normalstuff_u2a(upath, __apathbuf);
101 return newpath;
104 /*****************************************************************************
106 NAME */
107 #include "__upath.h"
110 const char *__path_a2u(
112 /* SYNOPSIS */
113 const char *apath)
115 /* FUNCTION
116 Translates an AmigaDOS-style path into an unix one.
118 INPUTS
119 apath - AmigaDOS-style path to translate into an unix-style equivalent.
121 RESULT
122 A pointer to a string containing the unix-style path, or NULL in
123 case of error.
125 The pointer is valid only until next call to this function, so if
126 you need to call this function recursively, you must save the string
127 pointed to by the pointer before calling this function again.
129 NOTES
130 This function is for private usage by system code. Do not use it
131 elsewhere.
133 INTERNALS
135 SEE ALSO
137 ******************************************************************************/
139 const char *old_apath = apath;
140 char ch, *upath, *old_upath;
141 size_t size = 0;
142 int run;
143 register enum
145 S_START0,
146 S_START1,
147 S_START,
148 S_VOLUME,
149 S_PARENT,
150 S_SLASH
151 } state;
153 /* Safety check. */
154 if (apath == NULL)
156 errno = EFAULT;
157 return NULL;
160 if (!__doupath)
161 return apath;
163 while ((ch = *apath++))
165 if (ch == '/')
166 size += 3;
167 else
168 size += 1;
171 if (size == 0)
172 return "";
174 old_upath = realloc_nocopy(__apathbuf, 1 + size + 1);
175 if (old_upath == NULL)
177 errno = ENOMEM;
178 return NULL;
181 __apathbuf = old_upath;
182 upath = ++old_upath;
183 apath = old_apath;
185 run = 1;
186 state = S_START0;
187 while (run)
189 register char ch = apath[0];
191 switch (state)
193 case S_START0:
194 if (ch == '/')
195 state = S_PARENT;
196 else
198 state = S_START1;
199 continue;
202 break;
204 case S_START1:
205 if (ch == ':')
206 state = S_VOLUME;
207 else
208 case S_START:
209 if (ch == '/')
210 state = S_SLASH;
211 else
212 if (ch == '\0')
213 run = 0;
214 else
215 upath++[0] = ch;
217 break;
219 case S_VOLUME:
220 (--old_upath)[0] = '/';
221 state = S_SLASH;
222 continue;
224 break;
226 case S_SLASH:
227 upath++[0] = '/';
229 if (ch == '/')
230 state = S_PARENT;
231 else
233 state = S_START;
234 continue;
237 break;
239 case S_PARENT:
240 upath[0] = '.'; upath[1] = '.'; upath[2] = '/'; upath += 3;
242 if (ch != '/')
244 state = S_START;
245 continue;
248 break;
251 upath[0] = '\0';
252 apath++;
255 upath[0] = '\0';
256 return old_upath;
260 static const char *__path_devstuff_u2a(const char *path)
263 Translate the various /dev/#? most used files into the AROS equivalent.
264 Use a tree-like handmade search to speed things up
267 if (path[0] == '/' && path[1] == 'd' && path[2] == 'e' && path[3] == 'v')
269 if (path[4] == '/')
271 if (path[5] == 'n' && path[6] == 'u' && path[7] == 'l' && path[8] == 'l' && path[9] == '\0')
272 return "NIL:";
273 else
274 if (path[5] == 'z' && path[6] == 'e' && path[7] == 'r' && path[8] == 'o' && path[9] == '\0')
275 return "ZERO:";
276 else
277 if (path[5] == 's' && path[6] == 't' && path[7] == 'd')
279 if (path[8] == 'i' && path[9] == 'n' && path[10] == '\0')
280 return "IN:";
281 else
282 if (path[8] == 'o' && path[9] == 'u' && path[10] == 't' && path[11] == '\0')
283 return "OUT:";
284 else
285 if (path[8] == 'e' && path[9] == 'r' && path[10] == 'r' && path[11] == '\0')
286 return "ERR:";
288 else
289 if (path[5] == '\0')
290 return "DEV:";
292 else
293 if (path[4] == '\0')
294 return "DEV:";
297 return NULL;
300 static void __path_normalstuff_u2a(const char *path, char *buf)
302 register char dir_sep = '\0';
303 register int makevol = 0;
304 register enum
306 S_START0,
307 S_START,
308 S_DOT1,
309 S_DOT2,
310 S_SLASH,
311 } state = S_START0;
313 int run = 1;
315 while (path[0] == '/')
317 path++;
318 makevol = 1;
321 while (run)
323 register char ch = path[0];
325 switch (state)
327 case S_START0:
328 if (ch == '.')
329 state = S_DOT1;
330 else
332 state = S_START;
333 continue;
335 break;
336 case S_START:
337 if (ch == '/')
339 dir_sep = '/';
340 state = S_SLASH;
342 else
343 if (ch == ':')
345 dir_sep = ':';
346 state = S_SLASH;
348 else
349 if (ch == '\0')
350 run = 0;
351 else
352 buf++[0] = ch;
354 break;
356 case S_DOT1:
357 if (ch == '\0')
358 run = 0;
359 else
360 if (ch == '.')
361 state = S_DOT2;
362 else
363 if (ch == '/')
365 dir_sep = '\0';
366 state = S_SLASH;
368 else
370 buf[0] = '.';
371 buf[1] = ch;
372 buf += 2;
373 state = S_START;
376 break;
378 case S_DOT2:
379 if (ch == '/' || ch == '\0')
381 dir_sep = '/';
382 state = S_SLASH;
383 continue;
385 else
387 buf[0] = '.';
388 buf[1] = '.';
389 buf[2] = ch;
390 buf += 3;
391 state = S_START;
394 break;
396 case S_SLASH:
397 if (ch != '/')
399 if (makevol)
401 makevol = 0;
402 dir_sep = ':';
405 if (dir_sep != '\0')
406 buf++[0] = dir_sep;
408 state = S_START0;
410 continue;
413 break;
416 path++;
419 if (makevol)
420 buf++[0] = ':';
422 buf[0] = '\0';
426 #ifdef BUILD_TEST
428 #include <stdio.h>
429 int main(int argc, char *argv[])
431 if (argc != 3)
432 return 20;
434 printf("%s\n", __path_u2a(argv[1]));
435 printf("%s\n", __path_a2u(argv[2]));
437 #endif