home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 541b.lha / OakLisp / src.lzh / worldio.c < prev   
C/C++ Source or Header  |  1991-06-15  |  10KB  |  498 lines

  1. /*  Copyright (C) 1987 Barak Pearlmutter and Kevin Lang    */
  2.  
  3.  
  4. #include <stdio.h>
  5. #include <ctype.h>
  6. #include "emulator.h"
  7.  
  8.  
  9. #ifdef PROTOTYPES
  10.  
  11. extern ref    contig( ref r, bool just_new);
  12. extern long    flread( char *ptr,         
  13.             unsigned int size_of_ptr,         
  14.             long count,         
  15.             FILE *stream);        
  16. extern ref    read_ref(FILE *d);        
  17. extern FILE *    prompt_file(char *the_prompt, char *mode);        
  18. extern void    dump_binary_world(bool just_new);
  19. extern void    dump_ascii_world(bool just_new);
  20. extern void    dump_world(bool just_new);
  21. extern void    reoffset(ref baseAddr, ref *start, long count);
  22. extern void    read_world(char *str);
  23. extern long    string_to_int(char string[]);
  24.  
  25. #endif
  26.  
  27. /* These are for making the world zero-based and contiguous in dumps. */
  28.  
  29. ref contig(r, just_new)
  30.      ref r;
  31.      bool just_new;
  32. {
  33.   ref *p = ANY_TO_PTR(r);
  34.  
  35.   if (just_new)
  36.     if (NEW_PTR(p))
  37.       return (p - new.start)*4 | r&3;
  38.     else
  39.       printf("Non-new pointer %ld found.\n", r);
  40.   else if (SPATIC_PTR(p))
  41.     return (p - spatic.start)*4 | r&3;
  42.   else if (NEW_PTR(p))
  43.     return (p - new.start + spatic.size)*4 | r&3;
  44.   else
  45.     printf("Non-new or spatic pointer %ld found.\n", r);
  46.  
  47.   return r;
  48. }
  49.  
  50. #define contigify(r) ((r)&0x2 ? contig((r),just_new) : (r))
  51. #define CONTIGIFY(v) { if ((v)&2) (v) = contig((v),just_new); }
  52.  
  53.  
  54.  
  55.  
  56.  
  57. bool dump_decimal= FALSE;    /* dumped worlds in base 10 (not 16) */
  58. bool dump_binary = FALSE;    /* dumped worlds in base 2  (not 16) */
  59.  
  60.  
  61. /*
  62.  * Format of Oaklisp world image:
  63.  *
  64.  * UNUSED: <size of value stack>
  65.  * UNUSED: <size of context stack>
  66.  * <reference to method for booting>
  67.  * <number of words to load>
  68.  *
  69.  * <words to load>
  70.  *
  71.  * <size of weak pointer table>
  72.  * <contents of weak pointer table>
  73.  */
  74.  
  75.  
  76. bool input_is_binary;
  77.  
  78. #ifdef Mac_LSC
  79.  
  80. long flread(ptr, size_of_ptr, count, stream)
  81.     char        *ptr;
  82.     unsigned int    size_of_ptr;
  83.     long        count;
  84.     FILE        *stream;
  85. {
  86.   long        result = 0;
  87.   int        block, items;
  88.     
  89.   while (count > 0) {
  90.     block = (count > 32000 ? 32000 : count);
  91.     items = fread(ptr, size_of_ptr, block, stream);
  92.     ptr = (char *) ((long) size_of_ptr * items + (long) ptr);
  93.     count  -= items;
  94.     result += items;
  95.   }
  96.  
  97.   return result;
  98. }
  99.  
  100. #else
  101.  
  102. /* Odd that the 3rd arg of fread is int; long would be more intuitive. */
  103. #define flread(a,b,c,d) fread((a),(b),(int)(c),(d))
  104.  
  105. #endif
  106.  
  107.     
  108. ref read_ref(d)  /* Read a reference from a file: */
  109.      FILE *d;
  110. {
  111.   int c;
  112.   ref a=0;
  113.  
  114.   /* It's easy to read a reference from a binary file. */
  115.   if (input_is_binary) {
  116.     (void)flread((char *)&a, sizeof(ref), 1L, d);
  117.     return a;
  118.   }
  119.  
  120. #ifdef BIG_ENDIAN
  121.   while ( isspace(c=getc(d)) || c=='^' )
  122. #else
  123.   while ( isspace(c=getc(d)) )
  124. #endif
  125.     if (c == EOF)
  126.       {
  127.     (void)printf("Apparently truncated cold load file!\n");
  128.     exit(1);
  129.       }
  130.   {
  131. #ifndef BIG_ENDIAN
  132.     bool swapem = c == '^';
  133.  
  134.     if (swapem)
  135.       if ((c = getc(d)) == EOF)
  136.     {
  137.       (void)printf("Apparently truncated cold load file!\n");
  138.       exit(1);
  139.     }
  140. #endif
  141.  
  142.     while (isxdigit(c))
  143.       {
  144.     a = a<<4;
  145.     if (c <= '9')
  146.       a |= c-'0';
  147.     else if (c <= 'Z')
  148.       a |= c-'A'+10;
  149.     else
  150.       a |= c-'a'+10;
  151.     c = getc(d);
  152.       }
  153.  
  154. #ifndef BIG_ENDIAN
  155.     if (c=='^') (void)ungetc(c,d);
  156.  
  157.     if (swapem)
  158.       a = a<<16 | a>>16;
  159. #endif
  160.     
  161.     return a;
  162.   }
  163. }
  164.  
  165.  
  166.  
  167.  
  168. FILE *prompt_file(the_prompt,mode)
  169.      char *the_prompt, *mode;
  170. {
  171.   char filename[80];
  172.   FILE *fp;
  173.  
  174.   while (TRUE)
  175.     {
  176.       (void)printf(the_prompt);
  177.       if (scanf("%s", filename) == EOF)
  178.     /* Fix the problem with EOF in batch files. */
  179.     {
  180.       (void)fprintf(stderr, "EOF in input.\n");
  181.       exit(1);
  182.     }
  183.       fp = fopen(filename, mode);
  184.       if (fp != NULL)
  185.     return fp;
  186.       else
  187.     (void)fprintf(stderr,"Can't open %s.\n", filename);
  188.     }
  189. }
  190.  
  191.  
  192.  
  193. #define REFBUFSIZ 1024
  194.  
  195. void dump_binary_world(just_new)
  196.      bool just_new;
  197. {
  198.   FILE *wfp = NULL;
  199.   ref *memptr;
  200.   ref theref;
  201.   ref refbuf[REFBUFSIZ];
  202.  
  203.   int imod = 0;
  204.   unsigned long worlsiz = free_point - new.start;
  205.   unsigned long DUMMY = 0;
  206.  
  207. #ifndef AMIGA
  208.   extern fwrite();
  209. #endif
  210.  
  211.   if (dump_file != NULL && ((wfp=fopen(dump_file,WRITE_BINARY_MODE)) == NULL))
  212.     fprintf(stderr, "Can't open \"%s\"; querying user.\n", dump_file);
  213.  
  214.   while (wfp == NULL)
  215.     {
  216.       wfp = prompt_file("Binary world file to write: ", WRITE_BINARY_MODE);
  217.     }
  218.  
  219.   if (!just_new) worlsiz += spatic.size;
  220.  
  221.   (void)putc('\002', wfp); (void)putc('\002', wfp);
  222.   (void)putc('\002', wfp); (void)putc('\002', wfp);
  223.  
  224.   /* Header information. */
  225.   (void)fwrite((char *)&DUMMY, sizeof(ref), 1, wfp);
  226.   (void)fwrite((char *)&DUMMY, sizeof(ref), 1, wfp);
  227.   theref = contigify(e_boot_code);
  228.   (void)fwrite((char *)&theref, sizeof(ref), 1, wfp);
  229.   (void)fwrite((char *)&worlsiz, sizeof(ref), 1, wfp);
  230.  
  231.   /* Dump the heap. */
  232.   /* Maybe dump spatic space. */
  233.   if (!just_new)
  234.     for (memptr = spatic.start; memptr < spatic.end; memptr++)
  235.       {
  236.     theref = *memptr;
  237.     CONTIGIFY(theref);
  238.     refbuf[imod++] = theref;
  239.     if (imod == REFBUFSIZ)
  240.       {
  241.         (void)fwrite((char *)&refbuf[0], sizeof(ref), imod, wfp);
  242.         imod = 0;
  243.       }
  244.       }
  245.   /* Dump new space. */
  246.   for (memptr = new.start; memptr < free_point; memptr++)
  247.     {
  248.       theref = *memptr;
  249.       CONTIGIFY(theref);
  250.       refbuf[imod++] = theref;
  251.       if (imod == REFBUFSIZ)
  252.     {
  253.       (void)fwrite((char *)&refbuf[0], sizeof(ref), imod, wfp);
  254.       imod = 0;
  255.     }
  256.     }
  257.   if (imod != 0)
  258.     (void)fwrite((char *)&refbuf[0], sizeof(ref), imod, wfp);
  259.  
  260.  
  261.   /* Weak pointer table. */
  262.   theref = (ref)wp_index;
  263.   (void)fwrite((char *)&theref, sizeof(ref), 1, wfp);
  264.  
  265.   for (imod = 0; imod<wp_index; imod++)
  266.     {
  267.       theref = wp_table[1+imod];
  268.       CONTIGIFY(theref);
  269.       (void)fwrite((char *)&theref, sizeof(ref), 1, wfp);
  270.     }
  271.  
  272.   (void)fclose(wfp);
  273. }
  274.  
  275.  
  276.  
  277.  
  278.  
  279.  
  280.  
  281. void dump_ascii_world(just_new)
  282.      bool just_new;
  283. {
  284.   ref *memptr, theref;
  285.   long    i;
  286.   int    eighter = 0;
  287.   char *control_string = (dump_decimal ? "%ld " : "%lx ");
  288.   FILE *wfp = NULL;
  289.  
  290.  
  291.   if (dump_file != NULL && ((wfp = fopen(dump_file, WRITE_MODE)) == NULL))
  292.     fprintf(stderr, "Can't open \"%s\"; querying user.\n", dump_file);
  293.  
  294.   while (wfp == NULL)
  295.     {
  296.       wfp = prompt_file("World file to write: ", WRITE_MODE);
  297.     }
  298.  
  299.   (void)fprintf(wfp, control_string, 0 /*val_stk_size*/);
  300.   (void)fprintf(wfp, control_string, 0 /*cxt_stk_size*/);
  301.   (void)fprintf(wfp, control_string, contigify(e_boot_code));
  302.   (void)fprintf(wfp, control_string,
  303.         free_point - new.start + (just_new ? 0 : spatic.size));
  304.  
  305.   /* Maybe dump spatic space. */
  306.   if (!just_new)
  307.     for (memptr = spatic.start; memptr < spatic.end; memptr++)
  308.       {
  309.     if (eighter == 0) (void)fprintf(wfp, "\n");
  310.     theref = *memptr;
  311.     CONTIGIFY(theref);
  312.     (void)fprintf(wfp,control_string, theref);
  313.     eighter = (eighter + 1) % 8;
  314.       }
  315.  
  316.   eighter = 0;
  317.   for (memptr = new.start; memptr < free_point; memptr++)
  318.     {
  319.       if (eighter == 0) (void)fprintf(wfp, "\n");
  320.       theref = *memptr;
  321.       CONTIGIFY(theref);
  322.       (void)fprintf(wfp,control_string, theref);
  323.       eighter = (eighter + 1) % 8;
  324.     }
  325.   (void)fprintf(wfp, "\n");
  326.  
  327.   /* Write the weak pointer table. */
  328.      
  329.   (void)fprintf(wfp, control_string, wp_index);
  330.      
  331.   eighter = 0;
  332.      
  333.   for (i = 0; i<wp_index; i++)
  334.     {
  335.       if (eighter == 0) (void)fprintf(wfp, "\n");
  336.       theref = wp_table[1+i];
  337.       CONTIGIFY(theref);
  338.       (void)fprintf(wfp, control_string, theref);
  339.       eighter = (eighter + 1) % 8;
  340.     }
  341.  
  342.   (void)fclose(wfp);
  343. }
  344.  
  345.  
  346.  
  347.  
  348. void dump_world(just_new)
  349.      bool just_new;
  350. {
  351.   if (dump_binary)
  352.     dump_binary_world(just_new);
  353.   else
  354.     dump_ascii_world(just_new);
  355. }
  356.  
  357.  
  358.  
  359. void reoffset(baseAddr, start, count)
  360.     register ref    baseAddr;
  361.     register ref    *start;
  362.     register long    count;
  363. {
  364.   register long    index;
  365.   register ref    *next;
  366.     
  367.   next = start;
  368.   for (index=0; index<count; index++) {
  369.     if ( *next&2 )
  370.       *next += baseAddr;
  371.     next++;
  372.   }
  373. }
  374.  
  375. void read_world(str)
  376.      char *str;
  377. {
  378.   FILE *d;
  379.   int magichar;
  380.  
  381.   /* Replace "%%" in file name with "ol" on bigendian machines and
  382.      with "lo" on littleendian ones. */
  383.  
  384.   {
  385.     char *p = str;
  386. #ifdef BIG_ENDIAN
  387.     char *next = "ol";
  388. #else
  389.     char *next = "lo";
  390. #endif
  391.  
  392.     while ((*p != '\0') && (*next != '\0'))
  393.       if (*p == '%')
  394.     *p++ = *next++;
  395.       else
  396.     p++;
  397.   }
  398.  
  399.   if ((d = fopen(str, READ_BINARY_MODE)) == NULL)
  400.     {
  401.       (void)printf("Can't open \"%s\".\n", str);
  402.       exit(1);
  403.     }
  404.  
  405.   magichar = getc (d);
  406.   if (magichar == (int)'\002')
  407.     {
  408.       (void)getc(d); (void)getc(d); (void)getc(d);
  409.       input_is_binary = 1;
  410.     }
  411.   else
  412.     {
  413.       (void)ungetc(magichar, d);
  414.       input_is_binary = 0;
  415. #ifdef BIG_ENDIAN
  416.       printf("Big Endian.\n");
  417. #else
  418.       printf("Little Endian.\n");
  419. #endif
  420.     }
  421.  
  422.   /* OBSOLESCENT: read val_space_size and cxt_space_size: */
  423.   (void)read_ref(d);
  424.   (void)read_ref(d);
  425.   
  426.   e_boot_code = read_ref(d);
  427.  
  428.   spatic.size = (unsigned long)read_ref(d);
  429.   alloc_space(&spatic);
  430.  
  431.   e_boot_code += (ref)spatic.start;
  432.  
  433.   {
  434.     long load_count;
  435.     ref *mptr, next;
  436.  
  437.     load_count = spatic.size;
  438.     mptr = spatic.start;
  439.  
  440.     if (input_is_binary) {
  441.       (void)flread((char *)spatic.start, sizeof(ref), load_count, d);
  442.       reoffset((ref) spatic.start, spatic.start, load_count);
  443.     }
  444.     else
  445.       while (load_count != 0)
  446.     {
  447.       next = read_ref(d);
  448.       if ( next&2 ) next += (ref)spatic.start;
  449.       *mptr++ = next;
  450.       --load_count;
  451.     }
  452.     /* Load the weak pointer table. */
  453.     wp_index = read_ref(d);
  454.     (void)flread((char *)&wp_table[1], sizeof(ref), (long)wp_index, d);
  455.     reoffset((ref) spatic.start, &wp_table[1], wp_index);
  456.   }
  457.  
  458.   /* The weak pointer hash table is rebuilt when e_nil is set. */
  459.  
  460.   (void)fclose(d);
  461. }
  462.  
  463.  
  464.  
  465.  
  466.  
  467. /* This is used to decode the -h option on the command line. */
  468. long string_to_int(string)
  469.      char string[];     
  470. {
  471.   long n = 0;
  472.   char *cs = string;
  473.   while(*cs >= '0' && *cs <= '9')
  474.     n = n*10 + *cs++ - '0';
  475.   while (1)
  476.     switch(*cs++)
  477.       {
  478.       case 'K':
  479.       case 'k':
  480.     n *= 1024;
  481.     break;
  482.       case 'M':
  483.       case 'm':
  484.     n *= (1024 * 1024);
  485.     break;
  486.       case 'W':
  487.       case 'w':
  488.     n *= sizeof(ref);
  489.     break;
  490.       case '\0':
  491.     return(n);
  492.       default:
  493.     printf("Unable to parse %s as a number.\n", string);
  494.     exit(1);
  495.       }
  496. }
  497.  
  498.