- Give PCI controllers lower unit numbers than legacy controllers.
[cake.git] / compiler / clib / __upath.c
blobda5d507594573db4c203c4c0afbed665125a2973
2 /*
3 Copyright © 1995-2001, 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;
74 First see whether the path is in the /dev/#? form and,
75 if so, if it's handled internally
77 newpath = __path_devstuff_u2a(upath);
78 if (!newpath)
80 /* Else, convert it normally */
81 newpath = realloc_nocopy(__apathbuf, strlen(upath) + 1);
83 if (newpath == NULL)
85 errno = ENOMEM;
86 return NULL;
89 __apathbuf = (char *)newpath;
90 __path_normalstuff_u2a(upath, __apathbuf);
93 return newpath;
96 /*****************************************************************************
98 NAME */
99 #include "__upath.h"
102 const char *__path_a2u(
104 /* SYNOPSIS */
105 const char *apath)
107 /* FUNCTION
108 Translates an AmigaDOS-style path into an unix one.
110 INPUTS
111 apath - AmigaDOS-style path to translate into an unix-style equivalent.
113 RESULT
114 A pointer to a string containing the unix-style path, or NULL in
115 case of error.
117 The pointer is valid only until next call to this function, so if
118 you need to call this function recursively, you must save the string
119 pointed to by the pointer before calling this function again.
121 NOTES
122 This function is for private usage by system code. Do not use it
123 elsewhere.
125 INTERNALS
127 SEE ALSO
129 ******************************************************************************/
131 const char *old_apath = apath;
132 char ch, *upath, *old_upath;
133 size_t size = 0;
134 int run;
135 register enum
137 S_START0,
138 S_START1,
139 S_START,
140 S_VOLUME,
141 S_PARENT,
142 S_SLASH
143 } state;
145 /* Safety check. */
146 if (apath == NULL)
148 errno = EFAULT;
149 return NULL;
152 if (!__doupath)
153 return apath;
155 while ((ch = *apath++))
157 if (ch == '/')
158 size += 3;
159 else
160 size += 1;
163 if (size == 0)
164 return "";
166 old_upath = realloc_nocopy(__apathbuf, 1 + size + 1);
167 if (old_upath == NULL)
169 errno = ENOMEM;
170 return NULL;
173 __apathbuf = old_upath;
174 upath = ++old_upath;
175 apath = old_apath;
177 run = 1;
178 state = S_START0;
179 while (run)
181 register char ch = apath[0];
183 switch (state)
185 case S_START0:
186 if (ch == '/')
187 state = S_PARENT;
188 else
190 state = S_START1;
191 continue;
194 break;
196 case S_START1:
197 if (ch == ':')
198 state = S_VOLUME;
199 else
200 case S_START:
201 if (ch == '/')
202 state = S_SLASH;
203 else
204 if (ch == '\0')
205 run = 0;
206 else
207 upath++[0] = ch;
209 break;
211 case S_VOLUME:
212 (--old_upath)[0] = '/';
213 state = S_SLASH;
214 continue;
216 break;
218 case S_SLASH:
219 upath++[0] = '/';
221 if (ch == '/')
222 state = S_PARENT;
223 else
225 state = S_START;
226 continue;
229 break;
231 case S_PARENT:
232 upath[0] = '.'; upath[1] = '.'; upath[2] = '/'; upath += 3;
234 if (ch != '/')
236 state = S_START;
237 continue;
240 break;
243 upath[0] = '\0';
244 apath++;
247 upath[0] = '\0';
248 return old_upath;
252 static const char *__path_devstuff_u2a(const char *path)
255 Translate the various /dev/#? most used files into the AROS equivalent.
256 Use a tree-like handmade search to speed things up
259 if (path[0] == '/' && path[1] == 'd' && path[2] == 'e' && path[3] == 'v')
261 if (path[4] == '/')
263 if (path[5] == 'n' && path[6] == 'u' && path[7] == 'l' && path[8] == 'l' && path[9] == '\0')
264 return "NIL:";
265 else
266 if (path[5] == 'z' && path[6] == 'e' && path[7] == 'r' && path[8] == 'o' && path[9] == '\0')
267 return "ZERO:";
268 else
269 if (path[5] == 's' && path[6] == 't' && path[7] == 'd')
271 if (path[8] == 'i' && path[9] == 'n' && path[10] == '\0')
272 return "IN:";
273 else
274 if (path[8] == 'o' && path[9] == 'u' && path[10] == 't' && path[11] == '\0')
275 return "OUT:";
276 else
277 if (path[8] == 'e' && path[9] == 'r' && path[10] == 'r' && path[11] == '\0')
278 return "ERR:";
280 else
281 if (path[5] == '\0')
282 return "DEV:";
284 else
285 if (path[4] == '\0')
286 return "DEV:";
289 return NULL;
292 static void __path_normalstuff_u2a(const char *path, char *buf)
294 register char dir_sep = '\0';
295 register int makevol = 0;
296 register enum
298 S_START0,
299 S_START,
300 S_DOT1,
301 S_DOT2,
302 S_SLASH,
303 } state = S_START0;
305 int run = 1;
307 while (path[0] == '/')
309 path++;
310 makevol = 1;
313 while (run)
315 register char ch = path[0];
317 switch (state)
319 case S_START0:
320 if (ch == '.')
321 state = S_DOT1;
322 else
324 state = S_START;
325 continue;
327 break;
328 case S_START:
329 if (ch == '/')
331 dir_sep = '/';
332 state = S_SLASH;
334 else
335 if (ch == ':')
337 dir_sep = ':';
338 state = S_SLASH;
340 else
341 if (ch == '\0')
342 run = 0;
343 else
344 buf++[0] = ch;
346 break;
348 case S_DOT1:
349 if (ch == '\0')
350 run = 0;
351 else
352 if (ch == '.')
353 state = S_DOT2;
354 else
355 if (ch == '/')
357 dir_sep = '\0';
358 state = S_SLASH;
360 else
362 buf[0] = '.';
363 buf[1] = ch;
364 buf += 2;
365 state = S_START;
368 break;
370 case S_DOT2:
371 if (ch == '/' || ch == '\0')
373 dir_sep = '/';
374 state = S_SLASH;
375 continue;
377 else
379 buf[0] = '.';
380 buf[1] = '.';
381 buf[2] = ch;
382 buf += 3;
383 state = S_START;
386 break;
388 case S_SLASH:
389 if (ch != '/')
391 if (makevol)
393 makevol = 0;
394 dir_sep = ':';
397 if (dir_sep != '\0')
398 buf++[0] = dir_sep;
400 state = S_START0;
402 continue;
405 break;
408 path++;
411 if (makevol)
412 buf++[0] = ':';
414 buf[0] = '\0';
418 #ifdef BUILD_TEST
420 #include <stdio.h>
421 int main(int argc, char *argv[])
423 if (argc != 3)
424 return 20;
426 printf("%s\n", __path_u2a(argv[1]));
427 printf("%s\n", __path_a2u(argv[2]));
429 #endif