173 lines · 4.7 KB · C
RawDownload
/* Structured input, compact format */ #include "debugger.h"#include "fail.h"#include "gc.h"#include "intext.h"#include "io.h"#include "memory.h"#include "mlvalues.h"#include "reverse.h" static header_t * intern_ptr;static asize_t obj_counter;static value * intern_obj_table;static unsigned int intern_color;static header_t intern_header;static value intern_block; static long input_bytes(struct channel * chan, int nbytes, int sign_extend){  long res;  int i;  res = getch(chan);  if (sign_extend)    res = (res << ((sizeof(long) - 1) * 8)) >> ((sizeof(long) - 1) * 8);  for (i = 1; i < nbytes; i++)    res = (res << 8) + getch(chan);  return res;} static void read_compact(struct channel * chan, value * dest){  unsigned int code;  tag_t tag;  mlsize_t size, len, ofs_ind;  value v = Val_unit;  asize_t ofs;  header_t header;  tailcall:  code = getch(chan);  if (code >= PREFIX_SMALL_INT) {    if (code >= PREFIX_SMALL_BLOCK) {      /* Small block */      tag = code & 0xF;      size = (code >> 4) & 0x7;    read_block:      if (size == 0) {        v = Atom(tag);      } else {        v = Val_hp(intern_ptr);        *dest = v;        intern_obj_table[obj_counter++] = v;        dest = (value *) (intern_ptr + 1);        *intern_ptr = Make_header(size, tag, intern_color);        intern_ptr += 1 + size;        for(/*nothing*/; size > 1; size--, dest++)          read_compact(chan, dest);        goto tailcall;      }    } else {      /* Small integer */      v = Val_int(code & 0x3F);    }  } else {    if (code >= PREFIX_SMALL_STRING) {      /* Small string */      len = (code & 0x1F);    read_string:      size = (len + sizeof(value)) / sizeof(value);      v = Val_hp(intern_ptr);      intern_obj_table[obj_counter++] = v;      *intern_ptr = Make_header(size, String_tag, intern_color);      intern_ptr += 1 + size;      Field(v, size - 1) = 0;      ofs_ind = Bsize_wsize(size) - 1;      Byte(v, ofs_ind) = ofs_ind - len;      really_getblock(chan, String_val(v), len);    } else {      switch(code) {      case CODE_INT8:        v = Val_long(input_bytes(chan, 1, 1));        break;      case CODE_INT16:        v = Val_long(input_bytes(chan, 2, 1));        break;      case CODE_INT32:        v = Val_long(input_bytes(chan, 4, 1));        break;      case CODE_INT64:#ifdef SIXTYFOUR        v = Val_long(input_bytes(chan, 8, 1));        break;#else        stat_free((char *) intern_obj_table);        Hd_val(intern_block) = intern_header; /* Don't confuse the GC */        failwith("input_value: integer too large");        break;#endif      case CODE_SHARED8:        ofs = input_bytes(chan, 1, 0);      read_shared:        Assert(ofs > 0 && ofs <= obj_counter);         v = intern_obj_table[obj_counter - ofs];        break;      case CODE_SHARED16:        ofs = input_bytes(chan, 2, 0);        goto read_shared;      case CODE_SHARED32:        ofs = input_bytes(chan, 4, 0);        goto read_shared;      case CODE_BLOCK32:        header = (header_t) input_bytes(chan, 4, 0);        tag = Tag_hd(header);        size = Wosize_hd(header);        goto read_block;      case CODE_STRING8:        len = input_bytes(chan, 1, 0);        goto read_string;      case CODE_STRING32:        len = input_bytes(chan, 4, 0);        goto read_string;      case CODE_DOUBLE:        if (sizeof(double) != 8) {          stat_free((char *) intern_obj_table);          Hd_val(intern_block) = intern_header; /* Don't confuse the GC */          invalid_argument("input_value: non-standard floats");        }        v = Val_hp(intern_ptr);        intern_obj_table[obj_counter++] = v;        *intern_ptr = Make_header(Double_wosize, Double_tag, intern_color);        intern_ptr += 1 + Double_wosize;        really_getblock(chan, (char *) v, 8);#ifndef MOSML_BIG_ENDIAN        Reverse_double(v);#endif        break;      }    }  }  *dest = v;} value intern_compact_val(struct channel * chan){  mlsize_t num_objects, size_32, size_64, whsize;  value res;   num_objects = getword(chan);  size_32 = getword(chan);  size_64 = getword(chan);#ifdef SIXTYFOUR  whsize = size_64;#else  whsize = size_32;#endif  if (whsize == 0) {    read_compact(chan, &res);  } else {    if (Wosize_whsize(whsize) > Max_wosize)      failwith("intern: structure too big");    intern_block = alloc_shr(Wosize_whsize(whsize), String_tag);    intern_header = Hd_val(intern_block);    intern_color = Color_hd(intern_header);    Assert (intern_color == White || intern_color == Black);    intern_ptr = (header_t *) Hp_val(intern_block);    obj_counter = 0;    intern_obj_table = (value *) stat_alloc(num_objects * sizeof(value));    read_compact(chan, &res);    stat_free((char *) intern_obj_table);  }  return res;}