Fixed compatibility of output.
[AROS.git] / compiler / posixc / __upath.c
blob90f4a523c90d7dcef74f9315c6800684567e1ef6
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: PosixC internal functions for Amiga<>UNIX filename conversion
6 Lang: english
7 */
9 #include "__posixc_intbase.h"
11 #include <string.h>
12 #include <stdlib.h>
13 #include <errno.h>
15 #define DEBUG 0
16 #include <aros/debug.h>
18 static const char *__path_devstuff_u2a(const char *path);
19 static void __path_normalstuff_u2a(const char *path, char *buf);
21 /*****************************************************************************
23 NAME */
24 #include "__upath.h"
27 const char *__path_u2a(
29 /* SYNOPSIS */
30 const char *upath)
32 /* FUNCTION
33 Translates a unix-style path into an AmigaDOS one.
35 INPUTS
36 upath - Unix-style path to translate into an AmigaDOS-style equivalent.
38 RESULT
39 A pointer to a string containing the AmigaDOS-style path, or NULL in
40 case of error.
42 The pointer is valid only until next call to this function, so if
43 you need to call this function recursively, you must save the string
44 pointed to by the pointer before calling this function again.
46 NOTES
47 This function is for private usage by system code. Do not use it
48 elsewhere.
50 INTERNALS
52 SEE ALSO
54 ******************************************************************************/
56 struct PosixCIntBase *PosixCBase =
57 (struct PosixCIntBase *)__aros_getbase_PosixCBase();
58 const char *newpath;
60 D(bug("Entering __path_u2a(\"%s\")\n", upath));
62 /* Does the path really need to be converted? */
63 if (!PosixCBase->doupath)
65 D(bug("__path_u2a: No conversion needed\n"));
67 return upath;
70 /* Safety check. */
71 if (upath == NULL)
73 errno = EFAULT;
74 return NULL;
77 /* Some scripts (config.guess) try to access /.attbin
78 which is MacOS-specific thing. Block it.
79 FIXME: Can we avod this hack ?
81 if (!strncmp(upath, "/.attbin", 8))
83 errno = ENOENT;
84 return NULL;
88 First see whether the path is in the /dev/#? form and,
89 if so, if it's handled internally
91 newpath = __path_devstuff_u2a(upath);
92 if (!newpath)
94 D(bug("__path_u2a: No /dev stuff, doing normal conversion\n"));
96 /* Else, convert it normally */
97 newpath = realloc_nocopy(PosixCBase->upathbuf, strlen(upath) + 1);
99 if (newpath == NULL)
101 errno = ENOMEM;
102 return NULL;
105 PosixCBase->upathbuf = (char *)newpath;
106 __path_normalstuff_u2a(upath, PosixCBase->upathbuf);
109 D(bug("__path_u2a: converted path \"%s\"\n", newpath));
111 return newpath;
114 /*****************************************************************************
116 NAME */
117 #include "__upath.h"
120 const char *__path_a2u(
122 /* SYNOPSIS */
123 const char *apath)
125 /* FUNCTION
126 Translates an AmigaDOS-style path into an unix one.
128 INPUTS
129 apath - AmigaDOS-style path to translate into an unix-style equivalent.
131 RESULT
132 A pointer to a string containing the unix-style path, or NULL in
133 case of error.
135 The pointer is valid only until next call to this function, so if
136 you need to call this function recursively, you must save the string
137 pointed to by the pointer before calling this function again.
139 NOTES
140 This function is for private usage by system code. Do not use it
141 elsewhere.
143 INTERNALS
145 SEE ALSO
147 ******************************************************************************/
149 struct PosixCIntBase *PosixCBase =
150 (struct PosixCIntBase *)__aros_getbase_PosixCBase();
151 const char *old_apath = apath;
152 char ch, *upath, *old_upath;
153 size_t size = 0;
154 int run;
155 register enum
157 S_START0,
158 S_START1,
159 S_START,
160 S_VOLUME,
161 S_PARENT,
162 S_SLASH
163 } state;
165 /* Safety check. */
166 if (apath == NULL)
168 errno = EFAULT;
169 return NULL;
172 if (!PosixCBase->doupath)
173 return apath;
175 while ((ch = *apath++))
177 if (ch == '/')
178 size += 3;
179 else
180 size += 1;
183 if (size == 0)
184 return "";
186 old_upath = realloc_nocopy(PosixCBase->upathbuf, 1 + size + 1);
187 if (old_upath == NULL)
189 errno = ENOMEM;
190 return NULL;
193 PosixCBase->upathbuf = old_upath;
194 upath = ++old_upath;
195 apath = old_apath;
197 run = 1;
198 state = S_START0;
199 while (run)
201 register char ch = apath[0];
203 switch (state)
205 case S_START0:
206 if (ch == '/')
207 state = S_PARENT;
208 else
210 state = S_START1;
211 continue;
214 break;
216 case S_START1:
217 if (ch == ':')
218 state = S_VOLUME;
219 else
220 case S_START:
221 if (ch == '/')
222 state = S_SLASH;
223 else
224 if (ch == '\0')
225 run = 0;
226 else
227 upath++[0] = ch;
229 break;
231 case S_VOLUME:
232 (--old_upath)[0] = '/';
233 state = S_SLASH;
234 continue;
236 break;
238 case S_SLASH:
239 upath++[0] = '/';
241 if (ch == '/')
242 state = S_PARENT;
243 else
245 state = S_START;
246 continue;
249 break;
251 case S_PARENT:
252 upath[0] = '.'; upath[1] = '.'; upath[2] = '/'; upath += 3;
254 if (ch != '/')
256 state = S_START;
257 continue;
260 break;
263 upath[0] = '\0';
264 apath++;
267 upath[0] = '\0';
268 return old_upath;
272 static const char *__path_devstuff_u2a(const char *path)
275 Translate the various /dev/#? most used files into the AROS equivalent.
276 Use a tree-like handmade search to speed things up
279 if (path[0] == '/' && path[1] == 'd' && path[2] == 'e' && path[3] == 'v')
281 if (path[4] == '/')
283 if (path[5] == 'n' && path[6] == 'u' && path[7] == 'l' && path[8] == 'l' && path[9] == '\0')
284 return "NIL:";
285 else
286 if (path[5] == 'z' && path[6] == 'e' && path[7] == 'r' && path[8] == 'o' && path[9] == '\0')
287 return "ZERO:";
288 else
289 if (path[5] == 's' && path[6] == 't' && path[7] == 'd')
291 if (path[8] == 'i' && path[9] == 'n' && path[10] == '\0')
292 return "IN:";
293 else
294 if (path[8] == 'o' && path[9] == 'u' && path[10] == 't' && path[11] == '\0')
295 return "OUT:";
296 else
297 if (path[8] == 'e' && path[9] == 'r' && path[10] == 'r' && path[11] == '\0')
298 return "ERR:";
300 else
301 if (path[5] == '\0')
302 return "DEV:";
304 else
305 if (path[4] == '\0')
306 return "DEV:";
309 return NULL;
312 static void __path_normalstuff_u2a(const char *path, char *buf)
314 register char dir_sep = '\0';
315 register int makevol = 0;
316 register enum
318 S_START0,
319 S_START,
320 S_DOT1,
321 S_DOT2,
322 S_SLASH,
323 } state = S_START0;
325 int run = 1;
327 while (path[0] == '/')
329 path++;
330 makevol = 1;
333 while (run)
335 register char ch = path[0];
337 switch (state)
339 case S_START0:
340 if (ch == '.')
341 state = S_DOT1;
342 else
344 state = S_START;
345 continue;
347 break;
348 case S_START:
349 if (ch == '/')
351 dir_sep = '/';
352 state = S_SLASH;
354 else
355 if (ch == ':')
357 dir_sep = ':';
358 state = S_SLASH;
360 else
361 if (ch == '\0')
362 run = 0;
363 else
364 buf++[0] = ch;
366 break;
368 case S_DOT1:
369 if (ch == '\0')
370 run = 0;
371 else
372 if (ch == '.')
373 state = S_DOT2;
374 else
375 if (ch == '/')
377 dir_sep = '\0';
378 state = S_SLASH;
380 else
382 buf[0] = '.';
383 buf[1] = ch;
384 buf += 2;
385 state = S_START;
388 break;
390 case S_DOT2:
391 if (ch == '/' || ch == '\0')
393 dir_sep = '/';
394 state = S_SLASH;
395 continue;
397 else
399 buf[0] = '.';
400 buf[1] = '.';
401 buf[2] = ch;
402 buf += 3;
403 state = S_START;
406 break;
408 case S_SLASH:
409 if (ch != '/')
411 if (makevol)
413 makevol = 0;
414 dir_sep = ':';
417 if (dir_sep != '\0')
418 buf++[0] = dir_sep;
420 state = S_START0;
422 continue;
425 break;
428 path++;
431 if (makevol)
432 buf++[0] = ':';
434 buf[0] = '\0';