summaryrefslogtreecommitdiff
path: root/libiberty/mpw.c
diff options
context:
space:
mode:
Diffstat (limited to 'libiberty/mpw.c')
-rw-r--r--libiberty/mpw.c1010
1 files changed, 1010 insertions, 0 deletions
diff --git a/libiberty/mpw.c b/libiberty/mpw.c
new file mode 100644
index 00000000000..ca3ae412d25
--- /dev/null
+++ b/libiberty/mpw.c
@@ -0,0 +1,1010 @@
+/* MPW-Unix compatibility library.
+ Copyright (C) 1993, 1994, 1995, 1996 Free Software Foundation, Inc.
+
+This file is part of the libiberty library.
+Libiberty is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+Libiberty is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with libiberty; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
+/* This should only be compiled and linked under MPW. */
+
+#include "mpw.h"
+
+#include <stdlib.h>
+
+#ifndef USE_MW_HEADERS
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+
+#include <Types.h>
+#include <Files.h>
+
+#include <Timer.h>
+
+/* Initialize to 0 at first, then set to errno_max() later. */
+
+int sys_nerr = 0;
+
+/* Debug flag for pathname hacking. Set this to one and rebuild. */
+
+int DebugPI = -1;
+
+void
+mpwify_filename(char *unixname, char *macname)
+{
+ int i, j;
+
+ /* (should truncate 255 chars from end of name, not beginning) */
+ if (strlen (unixname) > 255)
+ {
+ fprintf (stderr, "Pathname \"%s\" is too long for Macs, truncating\n",
+ unixname);
+ }
+ j = 0;
+ /* If you're going to end up with one or more colons in the middle of a
+ path after an all-Unix relative path is translated, you must add a
+ colon on the front, so that the first component is not thought to be
+ a disk name. */
+ if (unixname[0] != '/' && ! strchr (unixname, ':') && strchr (unixname, '/'))
+ {
+ macname[j++] = ':';
+ }
+ for (i = 0; unixname[i] != '\0' && i < 255; ++i)
+ {
+ if (i == 0 && unixname[i] == '/')
+ {
+ if (strncmp (unixname, "/tmp/", 5) == 0)
+ {
+ /* A temporary name, make a more Mac-flavored tmpname. */
+ /* A better choice would be {Boot}Trash:foo, but
+ that would require being able to identify the
+ boot disk's and trashcan's name. Another option
+ would be to have an env var, so user can point it
+ at a ramdisk. */
+ macname[j++] = ':';
+ macname[j++] = 't';
+ macname[j++] = 'm';
+ macname[j++] = 'p';
+ macname[j++] = '_';
+ i += 4;
+ }
+ else
+ {
+ /* Don't copy the leading slash. */
+ }
+ }
+ else if (unixname[i] == ':' && unixname[i+1] == '/')
+ {
+ macname[j++] = ':';
+ i += 1;
+ }
+ else if (unixname[i] == '.' && unixname[i+1] == '/')
+ {
+ macname[j++] = ':';
+ i += 1;
+ }
+ else if (unixname[i] == '.' && unixname[i+1] == '.' && unixname[i+2] == '/')
+ {
+ macname[j++] = ':';
+ macname[j++] = ':';
+ i += 2;
+ }
+ else if (unixname[i] == '/')
+ {
+ macname[j++] = ':';
+ }
+ else
+ {
+ macname[j++] = unixname[i];
+ }
+ }
+ macname[j] = '\0';
+ /* Allow for getting the debug flag from an env var; quite useful. */
+ if (DebugPI < 0)
+ DebugPI = (*(getenv ("DEBUG_PATHNAMES")) == '1' ? 1 : 0);
+ if (DebugPI)
+ {
+ fprintf (stderr, "# Made \"%s\"\n", unixname);
+ fprintf (stderr, "# into \"%s\"\n", macname);
+ }
+}
+
+/* MPW-flavored basename finder. */
+
+char *
+mpw_basename (name)
+ char *name;
+{
+ char *base = name;
+
+ while (*name)
+ {
+ if (*name++ == ':')
+ {
+ base = name;
+ }
+ }
+ return base;
+}
+
+/* Mixed MPW/Unix basename finder. This can be led astray by
+ filenames with slashes in them and come up with a basename that
+ either corresponds to no file or (worse) to some other file, so
+ should only be tried if other methods of finding a file via a
+ basename have failed. */
+
+char *
+mpw_mixed_basename (name)
+ char *name;
+{
+ char *base = name;
+
+ while (*name)
+ {
+ if (*name == '/' || *name == ':')
+ {
+ base = name + 1;
+ }
+ ++name;
+ }
+ return base;
+}
+
+/* This function is fopen() modified to create files that are type TEXT
+ or 'BIN ', and always of type 'MPS '. */
+
+FILE *
+mpw_fopen (char *name, char *mode)
+{
+#undef fopen
+ int errnum;
+ FILE *fp;
+ char tmpname[256];
+
+ mpwify_filename (name, tmpname);
+ PROGRESS (1);
+ fp = fopen (tmpname, mode);
+ errnum = errno;
+
+ /* If writing, need to set type and creator usefully. */
+ if (strchr (mode, 'w'))
+ {
+ char *pname = (char *) malloc (strlen (tmpname) + 2);
+ OSErr e;
+ struct FInfo fi;
+
+ pname[0] = strlen (tmpname);
+ strcpy (pname+1, tmpname);
+
+ e = GetFInfo ((ConstStr255Param) pname, 0, &fi);
+ /* should do spiffier error handling */
+ if (e != 0)
+ fprintf(stderr, "GetFInfo returns %d\n", e);
+ if (strchr (mode, 'b'))
+ {
+ fi.fdType = (OSType) 'BIN ';
+ }
+ else
+ {
+ fi.fdType = (OSType) 'TEXT';
+ }
+ fi.fdCreator = (OSType) 'MPS ';
+ e = SetFInfo ((ConstStr255Param) pname, 0, &fi);
+ if (e != 0)
+ fprintf(stderr, "SetFInfo returns %d\n", e);
+ free (pname);
+ }
+ if (fp == NULL)
+ errno = errnum;
+ return fp;
+}
+
+/* This is a version of fseek() modified to fill the file with zeros
+ if seeking past the end of it. */
+
+#define ZEROBLKSIZE 4096
+
+char zeros[ZEROBLKSIZE];
+
+int
+mpw_fseek (FILE *fp, int offset, int whence)
+{
+#undef fseek
+ int cursize, numleft;
+
+ PROGRESS (1);
+ if (whence == SEEK_SET)
+ {
+ fseek (fp, 0, SEEK_END);
+ cursize = ftell (fp);
+ if (offset > cursize)
+ {
+ numleft = offset - cursize;
+ while (numleft > ZEROBLKSIZE)
+ {
+ /* This might fail, should check for that. */
+ PROGRESS (1);
+ fwrite (zeros, 1, ZEROBLKSIZE, fp);
+ numleft -= ZEROBLKSIZE;
+ }
+ PROGRESS (1);
+ fwrite (zeros, 1, numleft, fp);
+ fflush (fp);
+ }
+ }
+ return fseek (fp, offset, whence);
+}
+
+int
+mpw_fread (char *ptr, int size, int nitems, FILE *stream)
+{
+#undef fread
+ int rslt;
+
+ PROGRESS (1);
+ rslt = fread (ptr, size, nitems, stream);
+ PROGRESS (1);
+ return rslt;
+}
+
+int
+mpw_fwrite (char *ptr, int size, int nitems, FILE *stream)
+{
+#undef fwrite
+ int rslt;
+
+ PROGRESS (1);
+ rslt = fwrite (ptr, size, nitems, stream);
+ PROGRESS (1);
+ return rslt;
+}
+
+int
+link ()
+{
+ fprintf (stderr, "link not available!\n");
+ mpw_abort ();
+}
+
+int
+fork ()
+{
+ fprintf (stderr, "fork not available!\n");
+ mpw_abort ();
+}
+
+int
+vfork ()
+{
+ fprintf (stderr, "vfork not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+
+int
+pipe (int *fd)
+{
+ fprintf (stderr, "pipe not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+
+#ifndef USE_MW_HEADERS
+int
+execvp (char *file, char **argv)
+{
+ fprintf (stderr, "execvp not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+
+int
+execv (char *path, char **argv)
+{
+ fprintf (stderr, "execv not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+#endif
+
+int
+kill (int pid, int sig)
+{
+ fprintf (stderr, "kill not available!\n");
+ mpw_abort ();
+ return (-1);
+}
+
+int
+wait (int *status)
+{
+ *status = 0;
+ return 0;
+}
+
+#ifndef USE_MW_HEADERS
+int
+sleep (int seconds)
+{
+ unsigned long start_time, now;
+
+ time (&start_time);
+
+ while (1)
+ {
+ PROGRESS (1);
+ time (&now);
+ if (now > start_time + seconds)
+ return 0;
+ }
+}
+#endif
+
+void
+putenv (char *str)
+{
+ /* The GCC driver calls this to do things for collect2, but we
+ don't care about collect2. */
+}
+
+int
+chmod (char *path, int mode)
+{
+ /* Pretend it was all OK. */
+ return 0;
+}
+
+#ifndef USE_MW_HEADERS
+int
+getuid ()
+{
+ /* One value is as good as another... */
+ return 0;
+}
+
+int
+getgid ()
+{
+ /* One value is as good as another... */
+ return 0;
+}
+#endif
+
+/* Instead of coredumping, which is not a normal Mac facility, we
+ drop into Macsbug. If we then "g" from Macsbug, the program will
+ exit cleanly. */
+
+void
+mpw_abort ()
+{
+ /* Make sure no output still buffered up, then zap into MacsBug. */
+ fflush(stdout);
+ fflush(stderr);
+ printf("## Abort! ##\n");
+#ifdef MPW_SADE
+ SysError(8005);
+#else
+ Debugger();
+#endif
+ /* "g" in MacsBug will then cause a regular error exit. */
+ exit (1);
+}
+
+/* Imitation getrusage based on the ANSI clock() function. */
+
+int
+getrusage (int who, struct rusage *rusage)
+{
+ int clk = clock ();
+
+#if 0
+ rusage->ru_utime.tv_sec = clk / CLOCKS_PER_SEC;
+ rusage->ru_utime.tv_usec = ((clk * 1000) / CLOCKS_PER_SEC) * 1000;
+ rusage->ru_stime.tv_sec = 0;
+ rusage->ru_stime.tv_usec = 0;
+#endif
+}
+
+int
+sbrk ()
+{
+ return 0;
+}
+
+#ifndef USE_MW_HEADERS
+int
+isatty (int fd)
+{
+ return 0;
+}
+
+/* This is inherited from Timothy Murray's Posix library. */
+
+#include "utime.h"
+
+int
+utime (char *filename, struct utimbuf *times)
+{
+ CInfoPBRec cipbr;
+ HFileInfo *fpb = (HFileInfo *) &cipbr;
+ DirInfo *dpb = (DirInfo *) &cipbr;
+ unsigned char pname[256];
+ short err;
+
+ strcpy ((char *) pname, filename);
+ c2pstr (pname);
+
+ dpb->ioDrDirID = 0L;
+ fpb->ioNamePtr = pname;
+ fpb->ioVRefNum = 0;
+ fpb->ioFDirIndex = 0;
+ fpb->ioFVersNum = 0;
+ err = PBGetCatInfo (&cipbr, 0);
+ if (err != noErr) {
+ errno = ENOENT;
+ return -1;
+ }
+ dpb->ioDrDirID = 0L;
+ fpb->ioFlMdDat = times->modtime;
+ fpb->ioFlCrDat = times->actime;
+ err = PBSetCatInfo (&cipbr, 0);
+ if (err != noErr) {
+ errno = EACCES;
+ return -1;
+ }
+ return 0;
+}
+
+int
+mkdir (char *path, int mode)
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+int
+rmdir ()
+{
+ errno = ENOSYS;
+ return -1;
+}
+#endif
+
+chown ()
+{
+ errno = ENOSYS;
+ return -1;
+}
+
+char *myenviron[] = {NULL};
+
+char **environ = myenviron;
+
+#ifndef USE_MW_HEADERS
+
+/* Minimal 'stat' emulation: tells directories from files and
+ gives length and mtime.
+
+ Derived from code written by Guido van Rossum, CWI, Amsterdam
+ and placed by him in the public domain. */
+
+extern int __uid, __gid;
+
+int __uid = 0;
+int __gid = 0;
+
+/* Bits in ioFlAttrib: */
+#define LOCKBIT (1<<0) /* File locked */
+#define DIRBIT (1<<4) /* It's a directory */
+
+/* Macified "stat" in which filename is given relative to a directory,
+ specified by long DirID. */
+
+static int
+_stat (char *name, long dirid, struct stat *buf)
+{
+ CInfoPBRec cipbr;
+ HFileInfo *fpb = (HFileInfo*) &cipbr;
+ DirInfo *dpb = (DirInfo*) &cipbr;
+ Str255 pname;
+ short err;
+
+ /* Make a temp copy of the name and pascalize. */
+ strcpy ((char *) pname, name);
+ c2pstr (pname);
+
+ cipbr.dirInfo.ioDrDirID = dirid;
+ cipbr.hFileInfo.ioNamePtr = pname;
+ cipbr.hFileInfo.ioVRefNum = 0;
+ cipbr.hFileInfo.ioFDirIndex = 0;
+ cipbr.hFileInfo.ioFVersNum = 0;
+ err = PBGetCatInfo (&cipbr, 0);
+ if (err != noErr)
+ {
+ errno = ENOENT;
+ return -1;
+ }
+ /* Mac files are readable if they can be accessed at all. */
+ buf->st_mode = 0444;
+ /* Mark unlocked files as writeable. */
+ if (!(fpb->ioFlAttrib & LOCKBIT))
+ buf->st_mode |= 0222;
+ if (fpb->ioFlAttrib & DIRBIT)
+ {
+ /* Mark directories as "executable". */
+ buf->st_mode |= 0111 | S_IFDIR;
+ buf->st_size = dpb->ioDrNmFls;
+ buf->st_rsize = 0;
+ }
+ else
+ {
+ buf->st_mode |= S_IFREG;
+ /* Mark apps as "executable". */
+ if (fpb->ioFlFndrInfo.fdType == 'APPL')
+ buf->st_mode |= 0111;
+ /* Fill in the sizes of data and resource forks. */
+ buf->st_size = fpb->ioFlLgLen;
+ buf->st_rsize = fpb->ioFlRLgLen;
+ }
+ /* Fill in various times. */
+ buf->st_atime = fpb->ioFlCrDat;
+ buf->st_mtime = fpb->ioFlMdDat;
+ buf->st_ctime = fpb->ioFlCrDat;
+ /* Set up an imitation inode number. */
+ buf->st_ino = (unsigned short) fpb->ioDirID;
+ /* Set up an imitation device. */
+ GetVRefNum (buf->st_ino, &buf->st_dev);
+ buf->st_uid = __uid;
+ buf->st_gid = __gid;
+/* buf->st_FlFndrInfo = fpb->ioFlFndrInfo; */
+ return 0;
+}
+
+/* stat() sets up an empty dirid. */
+
+int
+stat (char *path, struct stat *buf)
+{
+ long rslt, errnum;
+ char tmpname[256];
+
+ mpwify_filename (path, tmpname);
+ if (DebugPI)
+ fprintf (stderr, "# stat (%s, %x)", tmpname, buf);
+ PROGRESS (1);
+ rslt = _stat (tmpname, 0L, buf);
+ errnum = errno;
+ if (DebugPI)
+ {
+ fprintf (stderr, " -> %d", rslt);
+ if (rslt != 0)
+ fprintf (stderr, " (errno is %d)", errnum);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+ }
+ if (rslt != 0)
+ errno = errnum;
+ return rslt;
+}
+
+int
+fstat (int fd, struct stat *buf)
+{
+ FCBPBRec fcb;
+ FILE *fp;
+ Str255 pathname;
+ long dirid = 0L, temp;
+ long rslt, errnum;
+ short err;
+
+ if (DebugPI < 0)
+ DebugPI = (*(getenv ("DEBUG_PATHNAMES")) == '1' ? 1 : 0);
+ if (DebugPI)
+ fprintf (stderr, "# fstat (%d, %x)", fd, buf);
+ PROGRESS (1);
+ pathname[0] = 0;
+#ifdef FIOFNAME
+ /* Use an MPW-specific ioctl to get the pathname associated with
+ the file descriptor. */
+ ioctl (fd, FIOFNAME, (long *) pathname);
+#else
+ you lose
+#endif
+ if (DebugPI)
+ fprintf (stderr, " (name is %s)", pathname);
+ dirid = 0L /* fcb.ioFCBParID */ ;
+ rslt = _stat ((char *) pathname, dirid, buf);
+ errnum = errno;
+ if (DebugPI)
+ {
+ fprintf (stderr, " -> %d", rslt);
+ if (rslt != 0)
+ fprintf (stderr, " (errno is %d)", errnum);
+ fprintf (stderr, "\n");
+ fflush (stderr);
+ }
+ if (rslt != 0)
+ errno = errnum;
+ return rslt;
+}
+
+#endif /* n USE_MW_HEADERS */
+
+chdir ()
+{
+ errno = ENOSYS;
+ return (-1);
+}
+
+char *
+getcwd (char *buf, int size)
+{
+ if (buf == NULL)
+ buf = (char *) malloc (size);
+ strcpy(buf, ":");
+ return buf;
+}
+
+/* This should probably be more elaborate for MPW. */
+
+char *
+getpwd ()
+{
+ return ":";
+}
+
+int
+mpw_open (char *filename, int arg2, int arg3)
+{
+#undef open
+ int fd, errnum = 0;
+ char tmpname[256];
+
+ mpwify_filename (filename, tmpname);
+ fd = open (tmpname, arg2);
+ errnum = errno;
+
+ if (DebugPI)
+ {
+ fprintf (stderr, "# open (%s, %d, %d)", tmpname, arg2, arg3);
+ fprintf (stderr, " -> %d", fd);
+ if (fd == -1)
+ fprintf (stderr, " (errno is %d)", errnum);
+ fprintf (stderr, "\n");
+ }
+ if (fd == -1)
+ errno = errnum;
+ return fd;
+}
+
+int
+mpw_access (char *filename, unsigned int cmd)
+{
+#undef access
+
+ int rslt, errnum = 0;
+ struct stat st;
+ char tmpname[256];
+
+ mpwify_filename (filename, tmpname);
+ if (cmd & R_OK || cmd & X_OK)
+ {
+ rslt = stat (tmpname, &st);
+ errnum = errno;
+ if (rslt >= 0)
+ {
+ if ((((st.st_mode & 004) == 0) && (cmd & R_OK))
+ || (((st.st_mode & 002) == 0) && (cmd & W_OK))
+ || (((st.st_mode & 001) == 0) && (cmd & X_OK)))
+ {
+ rslt = -1;
+ errnum = EACCES;
+ }
+ }
+ }
+ if (DebugPI)
+ {
+ fprintf (stderr, "# mpw_access (%s, %d)", tmpname, cmd);
+ fprintf (stderr, " -> %d", rslt);
+ if (rslt != 0)
+ fprintf (stderr, " (errno is %d)", errnum);
+ fprintf (stderr, "\n");
+ }
+ if (rslt != 0)
+ errno = errnum;
+ return rslt;
+}
+
+/* The MPW library creat() has no mode argument. */
+
+int
+mpw_creat (char *path, /* mode_t */ int mode)
+{
+#undef creat
+
+#ifdef USE_MW_HEADERS
+ return creat (path, mode);
+#else
+ return creat (path);
+#endif
+}
+
+/* This is a hack to get control in an MPW tool before it crashes the
+ machine. */
+
+mpw_special_init (name)
+ char *name;
+{
+ if (strstr (name, "DEBUG"))
+ DebugStr("\pat beginning of program");
+}
+
+static int current_umask;
+
+int
+umask(int mask)
+{
+ int oldmask = current_umask;
+
+ current_umask = mask;
+ return oldmask;
+}
+
+/* Cursor-spinning stuff that includes metering of spin rate and delays. */
+
+/* Nonzero when cursor spinning has been set up properly. */
+
+int cursor_inited;
+
+/* Nonzero if spin should be measured and excessive delays reported. */
+
+int measure_spin;
+
+/* Nonzero if spin histogram and rate data should be written out. */
+
+int dump_spin_data;
+
+long warning_threshold = 400000;
+
+long bucket_size = 1024;
+
+long bucket_power = 10;
+
+long numbuckets = 300;
+
+int *delay_counts;
+
+int overflow_count;
+
+char *current_progress;
+
+static UnsignedWide last_microseconds;
+
+static char *last_spin_file = "";
+
+static int last_spin_line;
+
+void
+warn_if_spin_delay (char *file, int line)
+{
+ long diff, ix;
+ UnsignedWide now;
+
+ Microseconds(&now);
+
+ diff = now.lo - last_microseconds.lo;
+
+ if (diff > warning_threshold)
+ fprintf (stderr, "# %s: %ld.%06ld sec delay getting from %s:%d to %s:%d\n",
+ (current_progress ? current_progress : ""),
+ diff / 1000000, diff % 1000000,
+ last_spin_file, last_spin_line, file, line);
+ if (dump_spin_data)
+ {
+ if (diff >= 0)
+ {
+ ix = diff >> bucket_power;
+ if (ix >= 0 && ix < numbuckets && delay_counts != NULL)
+ ++delay_counts[ix];
+ else
+ ++overflow_count;
+ }
+ else
+ fprintf (stderr, "raw diff is %ld (?)\n", diff);
+ }
+}
+
+void
+record_for_spin_delay (char *file, int line)
+{
+ Microseconds (&last_microseconds);
+ last_spin_file = file;
+ last_spin_line = line;
+}
+
+void
+mpw_start_progress (char *str, int n, char *file, int line)
+{
+ int i;
+ char *measure, *threshold;
+
+ if (!cursor_inited)
+ {
+ InitCursorCtl (nil);
+ cursor_inited = 1;
+ record_for_spin_delay (file, line);
+ measure = getenv ("MEASURE_SPIN");
+ if (measure != NULL && measure[0] != '\0')
+ {
+ measure_spin = 1;
+ if (strcmp (measure, "all") == 0)
+ dump_spin_data = 1;
+ }
+ threshold = getenv ("SPIN_WARN_THRESHOLD");
+ if (threshold != NULL && threshold[0] != '\0')
+ warning_threshold = atol (threshold);
+ if (dump_spin_data)
+ {
+ if (delay_counts == NULL)
+ delay_counts = (int *) malloc (numbuckets * sizeof (int));
+ for (i = 0; i < numbuckets; ++i)
+ delay_counts[i] = 0;
+ overflow_count = 0;
+ }
+ }
+ current_progress = str;
+
+ sys_nerr = errno_max ();
+
+ mpw_special_init (str);
+}
+
+void
+mpw_progress (int n)
+{
+ SpinCursor (32);
+}
+
+void
+mpw_progress_measured (int n, char *file, int line)
+{
+ if (measure_spin)
+ warn_if_spin_delay (file, line);
+ SpinCursor (32);
+ if (measure_spin)
+ record_for_spin_delay (file, line);
+}
+
+void
+mpw_end_progress (char *str, char *file, int line)
+{
+ long i, delay, count = 0, sum = 0, avgdelay, spinrate;
+ long curpower = 0, curgroup = 0;
+
+ /* Warn if it's been a while since the last spin. */
+ if (measure_spin)
+ warn_if_spin_delay (file, line);
+
+ /* Dump all the nonzero delay counts and an approximation of the delay. */
+ if (dump_spin_data && delay_counts != NULL)
+ {
+ for (i = 0; i < numbuckets; ++i)
+ {
+ delay = (i + 1) * bucket_size;
+ sum += delay_counts[i] * (i + 1);
+ count += delay_counts[i];
+ if (delay <= (1 << curpower))
+ {
+ curgroup += delay_counts[i];
+ }
+ else
+ {
+ if (curgroup > 0)
+ fprintf (stderr,
+ "# %s: %d delays between %ld.%06ld and %ld.%06ld sec\n",
+ (str ? str : ""),
+ curgroup,
+ (1 << curpower) / 1000000,
+ (1 << curpower) % 1000000,
+ (1 << (curpower + 1)) / 1000000,
+ (1 << (curpower + 1)) % 1000000);
+ ++curpower;
+ curgroup = 0;
+ }
+ }
+ if (count > 0)
+ {
+ avgdelay = (sum * bucket_size) / count;
+ spinrate = 1000000 / avgdelay;
+ fprintf (stderr, "# %s: Average spin rate is %d times/sec\n",
+ (str ? str : ""), spinrate);
+ }
+ }
+}
+
+#ifdef PROGRESS_TEST
+
+/* Test program. */
+
+main ()
+{
+ int i, j;
+ double x = 1.0, y = 2.4;
+ long start = Microseconds (), tm; FIXME
+
+ START_PROGRESS ("hi", 0);
+
+ for (i = 0; i < 1000; ++i)
+ {
+ PROGRESS (1);
+
+ for (j = 0; j < (i * 100); ++j)
+ {
+ x += (x * y) / j;
+ }
+ }
+
+ END_PROGRESS ("hi");
+
+ tm = Microseconds () - start;
+
+ printf ("Total time is %d.%d secs\n", tm / 1000000, tm % 1000000);
+}
+
+#endif
+
+#ifdef USE_MW_HEADERS
+/* Empty definitions for Metrowerks' SIOUX console library. */
+
+#ifndef __CONSOLE__
+#include <console.h>
+#endif
+
+short
+InstallConsole(short fd)
+{
+#pragma unused (fd)
+ return 0;
+}
+
+void
+RemoveConsole(void)
+{
+}
+
+long
+WriteCharsToConsole(char *buf, long n)
+{
+#pragma unused (buf, n)
+ return 0;
+}
+
+long ReadCharsFromConsole(char *buf, long n)
+{
+#pragma unused (buf, n)
+ return 0;
+}
+
+extern char *
+__ttyname(long fd)
+{
+ static char *__devicename = "null device";
+
+ if (fd >= 0 && fd <= 2)
+ return (__devicename);
+ return NULL;
+}
+
+#endif