source: trunk/src/gcc/libiberty/mpw.c@ 1013

Last change on this file since 1013 was 2, checked in by bird, 23 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 19.5 KB
RevLine 
[2]1/* MPW-Unix compatibility library.
2 Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
3
4This file is part of the libiberty library.
5Libiberty is free software; you can redistribute it and/or
6modify it under the terms of the GNU Library General Public
7License as published by the Free Software Foundation; either
8version 2 of the License, or (at your option) any later version.
9
10Libiberty is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13Library General Public License for more details.
14
15You should have received a copy of the GNU Library General Public
16License along with libiberty; see the file COPYING.LIB. If
17not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18Boston, MA 02111-1307, USA. */
19
20/* This should only be compiled and linked under MPW. */
21
22#include "mpw.h"
23
24#include <stdlib.h>
25
26#ifndef USE_MW_HEADERS
27#include <sys/time.h>
28#include <sys/resource.h>
29#endif
30
31#include <Types.h>
32#include <Files.h>
33
34#include <Timer.h>
35
36/* Initialize to 0 at first, then set to errno_max() later. */
37
38int sys_nerr = 0;
39
40/* Debug flag for pathname hacking. Set this to one and rebuild. */
41
42int DebugPI = -1;
43
44void
45mpwify_filename(char *unixname, char *macname)
46{
47 int i, j;
48
49 /* (should truncate 255 chars from end of name, not beginning) */
50 if (strlen (unixname) > 255)
51 {
52 fprintf (stderr, "Pathname \"%s\" is too long for Macs, truncating\n",
53 unixname);
54 }
55 j = 0;
56 /* If you're going to end up with one or more colons in the middle of a
57 path after an all-Unix relative path is translated, you must add a
58 colon on the front, so that the first component is not thought to be
59 a disk name. */
60 if (unixname[0] != '/' && ! strchr (unixname, ':') && strchr (unixname, '/'))
61 {
62 macname[j++] = ':';
63 }
64 for (i = 0; unixname[i] != '\0' && i < 255; ++i)
65 {
66 if (i == 0 && unixname[i] == '/')
67 {
68 if (strncmp (unixname, "/tmp/", 5) == 0)
69 {
70 /* A temporary name, make a more Mac-flavored tmpname. */
71 /* A better choice would be {Boot}Trash:foo, but
72 that would require being able to identify the
73 boot disk's and trashcan's name. Another option
74 would be to have an env var, so user can point it
75 at a ramdisk. */
76 macname[j++] = ':';
77 macname[j++] = 't';
78 macname[j++] = 'm';
79 macname[j++] = 'p';
80 macname[j++] = '_';
81 i += 4;
82 }
83 else
84 {
85 /* Don't copy the leading slash. */
86 }
87 }
88 else if (unixname[i] == ':' && unixname[i+1] == '/')
89 {
90 macname[j++] = ':';
91 i += 1;
92 }
93 else if (unixname[i] == '.' && unixname[i+1] == '/')
94 {
95 macname[j++] = ':';
96 i += 1;
97 }
98 else if (unixname[i] == '.' && unixname[i+1] == '.' && unixname[i+2] == '/')
99 {
100 macname[j++] = ':';
101 macname[j++] = ':';
102 i += 2;
103 }
104 else if (unixname[i] == '/')
105 {
106 macname[j++] = ':';
107 }
108 else
109 {
110 macname[j++] = unixname[i];
111 }
112 }
113 macname[j] = '\0';
114 /* Allow for getting the debug flag from an env var; quite useful. */
115 if (DebugPI < 0)
116 DebugPI = (*(getenv ("DEBUG_PATHNAMES")) == '1' ? 1 : 0);
117 if (DebugPI)
118 {
119 fprintf (stderr, "# Made \"%s\"\n", unixname);
120 fprintf (stderr, "# into \"%s\"\n", macname);
121 }
122}
123
124/* MPW-flavored basename finder. */
125
126char *
127mpw_basename (name)
128 char *name;
129{
130 char *base = name;
131
132 while (*name)
133 {
134 if (*name++ == ':')
135 {
136 base = name;
137 }
138 }
139 return base;
140}
141
142/* Mixed MPW/Unix basename finder. This can be led astray by
143 filenames with slashes in them and come up with a basename that
144 either corresponds to no file or (worse) to some other file, so
145 should only be tried if other methods of finding a file via a
146 basename have failed. */
147
148char *
149mpw_mixed_basename (name)
150 char *name;
151{
152 char *base = name;
153
154 while (*name)
155 {
156 if (*name == '/' || *name == ':')
157 {
158 base = name + 1;
159 }
160 ++name;
161 }
162 return base;
163}
164
165/* This function is fopen() modified to create files that are type TEXT
166 or 'BIN ', and always of type 'MPS '. */
167
168FILE *
169mpw_fopen (char *name, char *mode)
170{
171#undef fopen
172 int errnum;
173 FILE *fp;
174 char tmpname[256];
175
176 mpwify_filename (name, tmpname);
177 PROGRESS (1);
178 fp = fopen (tmpname, mode);
179 errnum = errno;
180
181 /* If writing, need to set type and creator usefully. */
182 if (strchr (mode, 'w'))
183 {
184 char *pname = (char *) malloc (strlen (tmpname) + 2);
185 OSErr e;
186 struct FInfo fi;
187
188 pname[0] = strlen (tmpname);
189 strcpy (pname+1, tmpname);
190
191 e = GetFInfo ((ConstStr255Param) pname, 0, &fi);
192 /* should do spiffier error handling */
193 if (e != 0)
194 fprintf(stderr, "GetFInfo returns %d\n", e);
195 if (strchr (mode, 'b'))
196 {
197 fi.fdType = (OSType) 'BIN ';
198 }
199 else
200 {
201 fi.fdType = (OSType) 'TEXT';
202 }
203 fi.fdCreator = (OSType) 'MPS ';
204 e = SetFInfo ((ConstStr255Param) pname, 0, &fi);
205 if (e != 0)
206 fprintf(stderr, "SetFInfo returns %d\n", e);
207 free (pname);
208 }
209 if (fp == NULL)
210 errno = errnum;
211 return fp;
212}
213
214/* This is a version of fseek() modified to fill the file with zeros
215 if seeking past the end of it. */
216
217#define ZEROBLKSIZE 4096
218
219char zeros[ZEROBLKSIZE];
220
221int
222mpw_fseek (FILE *fp, int offset, int whence)
223{
224#undef fseek
225 int cursize, numleft;
226
227 PROGRESS (1);
228 if (whence == SEEK_SET)
229 {
230 fseek (fp, 0, SEEK_END);
231 cursize = ftell (fp);
232 if (offset > cursize)
233 {
234 numleft = offset - cursize;
235 while (numleft > ZEROBLKSIZE)
236 {
237 /* This might fail, should check for that. */
238 PROGRESS (1);
239 fwrite (zeros, 1, ZEROBLKSIZE, fp);
240 numleft -= ZEROBLKSIZE;
241 }
242 PROGRESS (1);
243 fwrite (zeros, 1, numleft, fp);
244 fflush (fp);
245 }
246 }
247 return fseek (fp, offset, whence);
248}
249
250int
251mpw_fread (char *ptr, int size, int nitems, FILE *stream)
252{
253#undef fread
254 int rslt;
255
256 PROGRESS (1);
257 rslt = fread (ptr, size, nitems, stream);
258 PROGRESS (1);
259 return rslt;
260}
261
262int
263mpw_fwrite (char *ptr, int size, int nitems, FILE *stream)
264{
265#undef fwrite
266 int rslt;
267
268 PROGRESS (1);
269 rslt = fwrite (ptr, size, nitems, stream);
270 PROGRESS (1);
271 return rslt;
272}
273
274int
275link ()
276{
277 fprintf (stderr, "link not available!\n");
278 mpw_abort ();
279}
280
281int
282fork ()
283{
284 fprintf (stderr, "fork not available!\n");
285 mpw_abort ();
286}
287
288int
289vfork ()
290{
291 fprintf (stderr, "vfork not available!\n");
292 mpw_abort ();
293 return (-1);
294}
295
296int
297pipe (int *fd)
298{
299 fprintf (stderr, "pipe not available!\n");
300 mpw_abort ();
301 return (-1);
302}
303
304#ifndef USE_MW_HEADERS
305int
306execvp (char *file, char **argv)
307{
308 fprintf (stderr, "execvp not available!\n");
309 mpw_abort ();
310 return (-1);
311}
312
313int
314execv (char *path, char **argv)
315{
316 fprintf (stderr, "execv not available!\n");
317 mpw_abort ();
318 return (-1);
319}
320#endif
321
322int
323kill (int pid, int sig)
324{
325 fprintf (stderr, "kill not available!\n");
326 mpw_abort ();
327 return (-1);
328}
329
330int
331wait (int *status)
332{
333 *status = 0;
334 return 0;
335}
336
337#ifndef USE_MW_HEADERS
338int
339sleep (int seconds)
340{
341 unsigned long start_time, now;
342
343 time (&start_time);
344
345 while (1)
346 {
347 PROGRESS (1);
348 time (&now);
349 if (now > start_time + seconds)
350 return 0;
351 }
352}
353#endif
354
355void
356putenv (char *str)
357{
358 /* The GCC driver calls this to do things for collect2, but we
359 don't care about collect2. */
360}
361
362int
363chmod (char *path, int mode)
364{
365 /* Pretend it was all OK. */
366 return 0;
367}
368
369#ifndef USE_MW_HEADERS
370int
371getuid ()
372{
373 /* One value is as good as another... */
374 return 0;
375}
376
377int
378getgid ()
379{
380 /* One value is as good as another... */
381 return 0;
382}
383#endif
384
385/* Instead of coredumping, which is not a normal Mac facility, we
386 drop into Macsbug. If we then "g" from Macsbug, the program will
387 exit cleanly. */
388
389void
390mpw_abort ()
391{
392 /* Make sure no output still buffered up, then zap into MacsBug. */
393 fflush(stdout);
394 fflush(stderr);
395 printf("## Abort! ##\n");
396#ifdef MPW_SADE
397 SysError(8005);
398#else
399 Debugger();
400#endif
401 /* "g" in MacsBug will then cause a regular error exit. */
402 exit (1);
403}
404
405/* Imitation getrusage based on the ANSI clock() function. */
406
407int
408getrusage (int who, struct rusage *rusage)
409{
410 int clk = clock ();
411
412#if 0
413 rusage->ru_utime.tv_sec = clk / CLOCKS_PER_SEC;
414 rusage->ru_utime.tv_usec = ((clk * 1000) / CLOCKS_PER_SEC) * 1000;
415 rusage->ru_stime.tv_sec = 0;
416 rusage->ru_stime.tv_usec = 0;
417#endif
418}
419
420int
421sbrk ()
422{
423 return 0;
424}
425
426#ifndef USE_MW_HEADERS
427int
428isatty (int fd)
429{
430 return 0;
431}
432
433/* This is inherited from Timothy Murray's Posix library. */
434
435#include "utime.h"
436
437int
438utime (char *filename, struct utimbuf *times)
439{
440 CInfoPBRec cipbr;
441 HFileInfo *fpb = (HFileInfo *) &cipbr;
442 DirInfo *dpb = (DirInfo *) &cipbr;
443 unsigned char pname[256];
444 short err;
445
446 strcpy ((char *) pname, filename);
447 c2pstr (pname);
448
449 dpb->ioDrDirID = 0L;
450 fpb->ioNamePtr = pname;
451 fpb->ioVRefNum = 0;
452 fpb->ioFDirIndex = 0;
453 fpb->ioFVersNum = 0;
454 err = PBGetCatInfo (&cipbr, 0);
455 if (err != noErr) {
456 errno = ENOENT;
457 return -1;
458 }
459 dpb->ioDrDirID = 0L;
460 fpb->ioFlMdDat = times->modtime;
461 fpb->ioFlCrDat = times->actime;
462 err = PBSetCatInfo (&cipbr, 0);
463 if (err != noErr) {
464 errno = EACCES;
465 return -1;
466 }
467 return 0;
468}
469
470int
471mkdir (char *path, int mode)
472{
473 errno = ENOSYS;
474 return -1;
475}
476
477int
478rmdir ()
479{
480 errno = ENOSYS;
481 return -1;
482}
483#endif
484
485chown ()
486{
487 errno = ENOSYS;
488 return -1;
489}
490
491char *myenviron[] = {NULL};
492
493char **environ = myenviron;
494
495#ifndef USE_MW_HEADERS
496
497/* Minimal 'stat' emulation: tells directories from files and
498 gives length and mtime.
499
500 Derived from code written by Guido van Rossum, CWI, Amsterdam
501 and placed by him in the public domain. */
502
503extern int __uid, __gid;
504
505int __uid = 0;
506int __gid = 0;
507
508/* Bits in ioFlAttrib: */
509#define LOCKBIT (1<<0) /* File locked */
510#define DIRBIT (1<<4) /* It's a directory */
511
512/* Macified "stat" in which filename is given relative to a directory,
513 specified by long DirID. */
514
515static int
516_stat (char *name, long dirid, struct stat *buf)
517{
518 CInfoPBRec cipbr;
519 HFileInfo *fpb = (HFileInfo*) &cipbr;
520 DirInfo *dpb = (DirInfo*) &cipbr;
521 Str255 pname;
522 short err;
523
524 /* Make a temp copy of the name and pascalize. */
525 strcpy ((char *) pname, name);
526 c2pstr (pname);
527
528 cipbr.dirInfo.ioDrDirID = dirid;
529 cipbr.hFileInfo.ioNamePtr = pname;
530 cipbr.hFileInfo.ioVRefNum = 0;
531 cipbr.hFileInfo.ioFDirIndex = 0;
532 cipbr.hFileInfo.ioFVersNum = 0;
533 err = PBGetCatInfo (&cipbr, 0);
534 if (err != noErr)
535 {
536 errno = ENOENT;
537 return -1;
538 }
539 /* Mac files are readable if they can be accessed at all. */
540 buf->st_mode = 0444;
541 /* Mark unlocked files as writeable. */
542 if (!(fpb->ioFlAttrib & LOCKBIT))
543 buf->st_mode |= 0222;
544 if (fpb->ioFlAttrib & DIRBIT)
545 {
546 /* Mark directories as "executable". */
547 buf->st_mode |= 0111 | S_IFDIR;
548 buf->st_size = dpb->ioDrNmFls;
549 buf->st_rsize = 0;
550 }
551 else
552 {
553 buf->st_mode |= S_IFREG;
554 /* Mark apps as "executable". */
555 if (fpb->ioFlFndrInfo.fdType == 'APPL')
556 buf->st_mode |= 0111;
557 /* Fill in the sizes of data and resource forks. */
558 buf->st_size = fpb->ioFlLgLen;
559 buf->st_rsize = fpb->ioFlRLgLen;
560 }
561 /* Fill in various times. */
562 buf->st_atime = fpb->ioFlCrDat;
563 buf->st_mtime = fpb->ioFlMdDat;
564 buf->st_ctime = fpb->ioFlCrDat;
565 /* Set up an imitation inode number. */
566 buf->st_ino = (unsigned short) fpb->ioDirID;
567 /* Set up an imitation device. */
568 GetVRefNum (buf->st_ino, &buf->st_dev);
569 buf->st_uid = __uid;
570 buf->st_gid = __gid;
571/* buf->st_FlFndrInfo = fpb->ioFlFndrInfo; */
572 return 0;
573}
574
575/* stat() sets up an empty dirid. */
576
577int
578stat (char *path, struct stat *buf)
579{
580 long rslt, errnum;
581 char tmpname[256];
582
583 mpwify_filename (path, tmpname);
584 if (DebugPI)
585 fprintf (stderr, "# stat (%s, %x)", tmpname, buf);
586 PROGRESS (1);
587 rslt = _stat (tmpname, 0L, buf);
588 errnum = errno;
589 if (DebugPI)