#include <stdio.h>
#include <malloc.h>

#define MAXLEN 32768

void *gazinta(FILE * fp, unsigned char ctb, int *gaz)
{
  unsigned long len;
  int neof = 0, i, k;
  unsigned char *bufptr, *bp;
  unsigned long gazouta;

  gazouta = 0;
  if (ctb < 0xc0) {
    i = 1 << (ctb & 3);         /* length of length */
    for (k = 0, len = 0; k < i; k++)
      len = (len << 8) + fgetc(fp);
  } else {
    if ((len = fgetc(fp)) >= 0xc0) {
      if (len >= 0xe0)
        if (len == 0xff)
          for (k = 0, len = 0; k < 4; k++)
            len = (len << 8) + fgetc(fp);
        else
          len = 1 << (len & 31), neof = 1;  /* noteof */
      else
        len = ((len & 31) << 8) + 192 + fgetc(fp);
    }
  }
  if (len > MAXLEN || !len)
    return NULL;
  bufptr = malloc(neof ? MAXLEN + 1 : len + 1);  /* +1 to add final null */

  bp = bufptr;
  for (;;) {
    gazouta += len;
    if (gazouta > MAXLEN) {
      gazouta += fread(bp, 1, MAXLEN - gazouta, fp) - len;
      bufptr[gazouta] = 0;
      if (gaz)
        *gaz = gazouta;
      return bufptr;
    }
    while (len) {
      i = fread(bp, 1, len, fp);
      if (i > 0)
        len -= i, bp += i;
      else {
        free(bufptr);
        return NULL;
      }
    }
    if (!neof) {
      bufptr[gazouta] = 0;
      if (gaz)
        *gaz = gazouta;
      return bufptr;
    }
    neof = 0;
    if ((len = fgetc(fp)) >= 0xc0) {
      if (len >= 0xe0)
        len = 1 << (len & 31), neof += len;  /* noteof */
      else
        len = ((len & 31) << 8) + 192 + fgetc(fp);
    }
  }
}
