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) 590 { 591 fprintf (stderr, " -> %d", rslt); 592 if (rslt != 0) 593 fprintf (stderr, " (errno is %d)", errnum); 594 fprintf (stderr, "\n"); 595 fflush (stderr); 596 } 597 if (rslt != 0) 598 errno = errnum; 599 return rslt; 600} 601 602int 603fstat (int fd, struct stat *buf) 604{ 605 FCBPBRec fcb; 606 FILE *fp; 607 Str255 pathname; 608 long dirid = 0L, temp; 609 long rslt, errnum; 610 short err; 611 612 if (DebugPI < 0) 613 DebugPI = (*(getenv ("DEBUG_PATHNAMES")) == '1' ? 1 : 0); 614 if (DebugPI) 615 fprintf (stderr, "# fstat (%d, %x)", fd, buf); 616 PROGRESS (1); 617 pathname[0] = 0; 618#ifdef FIOFNAME 619 /* Use an MPW-specific ioctl to get the pathname associated with 620 the file descriptor. */ 621 ioctl (fd, FIOFNAME, (long *) pathname); 622#else 623 you lose 624#endif 625 if (DebugPI) 626 fprintf (stderr, " (name is %s)", pathname); 627 dirid = 0L /* fcb.ioFCBParID */ ; 628 rslt = _stat ((char *) pathname, dirid, buf); 629 errnum = errno; 630 if (DebugPI) 631 { 632 fprintf (stderr, " -> %d", rslt); 633 if (rslt != 0) 634 fprintf (stderr, " (errno is %d)", errnum); 635 fprintf (stderr, "\n"); 636 fflush (stderr); 637 } 638 if (rslt != 0) 639 errno = errnum; 640 return rslt; 641} 642 643#endif /* n USE_MW_HEADERS */ 644 645chdir () 646{ 647 errno = ENOSYS; 648 return (-1); 649} 650 651char * 652getcwd (char *buf, int size) 653{ 654 if (buf == NULL) 655 buf = (char *) malloc (size); 656 strcpy(buf, ":"); 657 return buf; 658} 659 660/* This should probably be more elaborate for MPW. */ 661 662char * 663getpwd () 664{ 665 return ":"; 666} 667 668int 669mpw_open (char *filename, int arg2, int arg3) 670{ 671#undef open 672 int fd, errnum = 0; 673 char tmpname[256]; 674 675 mpwify_filename (filename, tmpname); 676 fd = open (tmpname, arg2); 677 errnum = errno; 678 679 if (DebugPI) 680 { 681 fprintf (stderr, "# open (%s, %d, %d)", tmpname, arg2, arg3); 682 fprintf (stderr, " -> %d", fd); 683 if (fd == -1) 684 fprintf (stderr, " (errno is %d)", errnum); 685 fprintf (stderr, "\n"); 686 } 687 if (fd == -1) 688 errno = errnum; 689 return fd; 690} 691 692int 693mpw_access (char *filename, unsigned int cmd) 694{ 695#undef access 696 697 int rslt, errnum = 0; 698 struct stat st; 699 char tmpname[256]; 700 701 mpwify_filename (filename, tmpname); 702 if (cmd & R_OK || cmd & X_OK) 703 { 704 rslt = stat (tmpname, &st); 705 errnum = errno; 706 if (rslt >= 0) 707 { 708 if ((((st.st_mode & 004) == 0) && (cmd & R_OK)) 709 || (((st.st_mode & 002) == 0) && (cmd & W_OK)) 710 || (((st.st_mode & 001) == 0) && (cmd & X_OK))) 711 { 712 rslt = -1; 713 errnum = EACCES; 714 } 715 } 716 } 717 if (DebugPI) 718 { 719 fprintf (stderr, "# mpw_access (%s, %d)", tmpname, cmd); 720 fprintf (stderr, " -> %d", rslt); 721 if (rslt != 0) 722 fprintf (stderr, " (errno is %d)", errnum); 723 fprintf (stderr, "\n"); 724 } 725 if (rslt != 0) 726 errno = errnum; 727 return rslt; 728} 729 730/* The MPW library creat() has no mode argument. */ 731 732int 733mpw_creat (char *path, /* mode_t */ int mode) 734{ 735#undef creat 736 737#ifdef USE_MW_HEADERS 738 return creat (path, mode); 739#else 740 return creat (path); 741#endif 742} 743 744/* This is a hack to get control in an MPW tool before it crashes the 745 machine. */ 746 747mpw_special_init (name) 748 char *name; 749{ 750 if (strstr (name, "DEBUG")) 751 DebugStr("\pat beginning of program"); 752} 753 754static int current_umask; 755 756int 757umask(int mask) 758{ 759 int oldmask = current_umask; 760 761 current_umask = mask; 762 return oldmask; 763} 764 765/* Cursor-spinning stuff that includes metering of spin rate and delays. */ 766 767/* Nonzero when cursor spinning has been set up properly. */ 768 769int cursor_inited; 770 771/* Nonzero if spin should be measured and excessive delays reported. */ 772 773int measure_spin; 774 775/* Nonzero if spin histogram and rate data should be written out. */ 776 777int dump_spin_data; 778 779long warning_threshold = 400000; 780 781long bucket_size = 1024; 782 783long bucket_power = 10; 784 785long numbuckets = 300; 786 787int *delay_counts; 788 789int overflow_count; 790 791char *current_progress; 792 793static UnsignedWide last_microseconds; 794 795static char *last_spin_file = ""; 796 797static int last_spin_line; 798 799void 800warn_if_spin_delay (char *file, int line) 801{ 802 long diff, ix; 803 UnsignedWide now; 804 805 Microseconds(&now); 806 807 diff = now.lo - last_microseconds.lo; 808 809 if (diff > warning_threshold) 810 fprintf (stderr, "# %s: %ld.%06ld sec delay getting from %s:%d to %s:%d\n", 811 (current_progress ? current_progress : ""), 812 diff / 1000000, diff % 1000000, 813 last_spin_file, last_spin_line, file, line); 814 if (dump_spin_data) 815 { 816 if (diff >= 0) 817 { 818 ix = diff >> bucket_power; 819 if (ix >= 0 && ix < numbuckets && delay_counts != NULL) 820 ++delay_counts[ix]; 821 else 822 ++overflow_count; 823 } 824 else 825 fprintf (stderr, "raw diff is %ld (?)\n", diff); 826 } 827} 828 829void 830record_for_spin_delay (char *file, int line) 831{ 832 Microseconds (&last_microseconds); 833 last_spin_file = file; 834 last_spin_line = line; 835} 836 837void 838mpw_start_progress (char *str, int n, char *file, int line) 839{ 840 int i; 841 char *measure, *threshold; 842 843 if (!cursor_inited) 844 { 845 InitCursorCtl (nil); 846 cursor_inited = 1; 847 record_for_spin_delay (file, line); 848 measure = getenv ("MEASURE_SPIN"); 849 if (measure != NULL && measure[0] != '\0') 850 { 851 measure_spin = 1; 852 if (strcmp (measure, "all") == 0) 853 dump_spin_data = 1; 854 } 855 threshold = getenv ("SPIN_WARN_THRESHOLD"); 856 if (threshold != NULL && threshold[0] != '\0') 857 warning_threshold = atol (threshold); 858 if (dump_spin_data) 859 { 860 if (delay_counts == NULL) 861 delay_counts = (int *) malloc (numbuckets * sizeof (int)); 862 for (i = 0; i < numbuckets; ++i) 863 delay_counts[i] = 0; 864 overflow_count = 0; 865 } 866 } 867 current_progress = str; 868 869 sys_nerr = errno_max (); 870 871 mpw_special_init (str); 872} 873 874void 875mpw_progress (int n) 876{ 877 SpinCursor (32); 878} 879 880void 881mpw_progress_measured (int n, char *file, int line) 882{ 883 if (measure_spin) 884 warn_if_spin_delay (file, line); 885 SpinCursor (32); 886 if (measure_spin) 887 record_for_spin_delay (file, line); 888} 889 890void 891mpw_end_progress (char *str, char *file, int line) 892{ 893 long i, delay, count = 0, sum = 0, avgdelay, spinrate; 894 long curpower = 0, curgroup = 0; 895 896 /* Warn if it's been a while since the last spin. */ 897 if (measure_spin) 898 warn_if_spin_delay (file, line); 899 900 /* Dump all the nonzero delay counts and an approximation of the delay. */ 901 if (dump_spin_data && delay_counts != NULL) 902 { 903 for (i = 0; i < numbuckets; ++i) 904 { 905 delay = (i + 1) * bucket_size; 906 sum += delay_counts[i] * (i + 1); 907 count += delay_counts[i]; 908 if (delay <= (1 << curpower)) 909 { 910 curgroup += delay_counts[i]; 911 } 912 else 913 { 914 if (curgroup > 0) 915 fprintf (stderr, 916 "# %s: %d delays between %ld.%06ld and %ld.%06ld sec\n", 917 (str ? str : ""), 918 curgroup, 919 (1 << curpower) / 1000000, 920 (1 << curpower) % 1000000, 921 (1 << (curpower + 1)) / 1000000, 922 (1 << (curpower + 1)) % 1000000); 923 ++curpower; 924 curgroup = 0; 925 } 926 } 927 if (count > 0) 928 { 929 avgdelay = (sum * bucket_size) / count; 930 spinrate = 1000000 / avgdelay; 931 fprintf (stderr, "# %s: Average spin rate is %d times/sec\n", 932 (str ? str : ""), spinrate); 933 } 934 } 935} 936 937#ifdef PROGRESS_TEST 938 939/* Test program. */ 940 941main () 942{ 943 int i, j; 944 double x = 1.0, y = 2.4; 945 long start = Microseconds (), tm; FIXME 946 947 START_PROGRESS ("hi", 0); 948 949 for (i = 0; i < 1000; ++i) 950 { 951 PROGRESS (1); 952 953 for (j = 0; j < (i * 100); ++j) 954 { 955 x += (x * y) / j; 956 } 957 } 958 959 END_PROGRESS ("hi"); 960 961 tm = Microseconds () - start; 962 963 printf ("Total time is %d.%d secs\n", tm / 1000000, tm % 1000000); 964} 965 966#endif 967 968#ifdef USE_MW_HEADERS 969/* Empty definitions for Metrowerks' SIOUX console library. */ 970 971#ifndef __CONSOLE__ 972#include <console.h> 973#endif 974 975short 976InstallConsole(short fd) 977{ 978#pragma unused (fd) 979 return 0; 980} 981 982void 983RemoveConsole(void) 984{ 985} 986 987long 988WriteCharsToConsole(char *buf, long n) 989{ 990#pragma unused (buf, n) 991 return 0; 992} 993 994long ReadCharsFromConsole(char *buf, long n) 995{ 996#pragma unused (buf, n) 997 return 0; 998} 999 1000extern char * 1001__ttyname(long fd) 1002{ 1003 static char *__devicename = "null device"; 1004 1005 if (fd >= 0 && fd <= 2) 1006 return (__devicename); 1007 return NULL; 1008} 1009 1010#endif 1011