home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / fish / applications / xlispstat / src / src1.lzh / Amiga / iffw.c < prev    next >
C/C++ Source or Header  |  1990-10-05  |  6KB  |  166 lines

  1. #define FDwAT
  2. #include <proto/dos.h>
  3. #include <iff/iff.h>
  4. #include <iff/gio.h>
  5. #define Known(size)   ( (size) != szNotYetKnown )
  6. #define IfIffp(expr)  {if (iffp == IFF_OKAY)  iffp = (expr);}
  7.  
  8. IFFP OpenWIFF(file, new0, limit)
  9. BPTR file; GroupContext *new0; LONG limit; {
  10.     register GroupContext *new = new0;
  11.     register IFFP iffp = IFF_OKAY;
  12.     new->parent       = NULL;
  13.     new->clientFrame  = NULL;
  14.     new->file         = file;
  15.     new->position     = 0;
  16.     new->bound        = limit;
  17.     new->ckHdr.ckID   = NULL_CHUNK;
  18.     new->ckHdr.ckSize = new->bytesSoFar = 0;
  19.     if (0 > Seek(file, 0, OFFSET_BEGINNING))
  20.     iffp = DOS_ERROR;
  21.     else if ( Known(limit) && IS_ODD(limit) )
  22.     iffp = CLIENT_ERROR;
  23.     return(iffp);
  24.     }
  25. IFFP StartWGroup(parent, groupType, groupSize, subtype, new)
  26.       GroupContext *parent, *new; ID groupType, subtype; LONG groupSize;  {
  27.     register IFFP iffp;
  28.  
  29.     iffp = PutCkHdr(parent, groupType, groupSize);
  30.     IfIffp( IFFWriteBytes(parent, (BYTE *)&subtype, sizeof(ID)) );
  31.     IfIffp( OpenWGroup(parent, new) );
  32.     return(iffp);
  33.     }
  34. IFFP OpenWGroup(parent0, new0)  GroupContext *parent0, *new0; {
  35.     register GroupContext *parent = parent0;
  36.     register GroupContext *new    = new0;
  37.     register LONG ckEnd;
  38.     register IFFP iffp = IFF_OKAY;
  39.     new->parent       = parent;
  40.     new->clientFrame  = parent->clientFrame;
  41.     new->file         = parent->file;
  42.     new->position     = parent->position;
  43.     new->bound        = parent->bound;
  44.     new->ckHdr.ckID   = NULL_CHUNK;
  45.     new->ckHdr.ckSize = new->bytesSoFar = 0;
  46.     if ( Known(parent->ckHdr.ckSize) ) {
  47.     ckEnd = new->position + ChunkMoreBytes(parent);
  48.     if ( new->bound == szNotYetKnown || new->bound > ckEnd )
  49.         new->bound = ckEnd;
  50.     };
  51.     if ( parent->ckHdr.ckID == NULL_CHUNK ||
  52.      IS_ODD(new->position) ||
  53.          (Known(new->bound) && IS_ODD(new->bound)) )
  54.     iffp = CLIENT_ERROR;
  55.     return(iffp);
  56.     }
  57. IFFP CloseWGroup(old0)  GroupContext *old0; {
  58.     register GroupContext *old = old0;
  59.     IFFP iffp = IFF_OKAY;
  60.     if ( old->ckHdr.ckID != NULL_CHUNK )  /* didn't close the last chunk */
  61.     iffp = CLIENT_ERROR;
  62.     else if ( old->parent == NULL ) {      /* top level file context */
  63.     if (GWriteFlush(old->file) < 0)  iffp = DOS_ERROR;
  64.     }
  65.     else {                  /* update parent context */
  66.     old->parent->bytesSoFar += old->position - old->parent->position;
  67.     old->parent->position = old->position;
  68.     };
  69.     return(iffp);
  70.     }
  71. IFFP EndWGroup(old)  GroupContext *old;  {
  72.     register GroupContext *parent = old->parent;
  73.     register IFFP iffp;
  74.     iffp = CloseWGroup(old);
  75.     IfIffp( PutCkEnd(parent) );
  76.     return(iffp);
  77.     }
  78. IFFP PutCk(context, ckID, ckSize, data)
  79.       GroupContext *context; ID ckID; LONG ckSize; BYTE *data; {
  80.     register IFFP iffp = IFF_OKAY;
  81.     if ( ckSize == szNotYetKnown )
  82.     iffp = CLIENT_ERROR;
  83.     IfIffp( PutCkHdr(context, ckID, ckSize) );
  84.     IfIffp( IFFWriteBytes(context, data, ckSize) );
  85.     IfIffp( PutCkEnd(context) );
  86.     return(iffp);
  87.     }
  88. IFFP PutCkHdr(context0, ckID, ckSize)
  89.       GroupContext *context0;  ID ckID;  LONG ckSize; {
  90.     register GroupContext *context = context0;
  91.     LONG minPSize = sizeof(ChunkHeader); /* physical chunk >= minPSize bytes*/
  92.     if ( context->ckHdr.ckID != NULL_CHUNK  ||  ckID <= 0 )
  93.     return(CLIENT_ERROR);
  94.     else if (context->parent == NULL)  {
  95.     switch (ckID)  {
  96.         case FORM:  case LIST:  case CAT:  break;
  97.         default: return(CLIENT_ERROR);
  98.         }
  99.     if (context->position != 0)
  100.         return(CLIENT_ERROR);
  101.     }
  102.     if ( Known(ckSize) ) {
  103.     if ( ckSize < 0 )
  104.         return(CLIENT_ERROR);
  105.     minPSize += ckSize;
  106.     };
  107.     if ( Known(context->bound)  &&
  108.          context->position + minPSize > context->bound )
  109.     return(CLIENT_ERROR);
  110.     context->ckHdr.ckID   = ckID;
  111.     context->ckHdr.ckSize = ckSize;
  112.     context->bytesSoFar   = 0;
  113.     if (0 >
  114.     GWrite(context->file, (BYTE *)&context->ckHdr, sizeof(ChunkHeader))
  115.     )
  116.     return(DOS_ERROR);
  117.     context->position += sizeof(ChunkHeader);
  118.     return(IFF_OKAY);
  119.     }
  120. IFFP IFFWriteBytes(context0, data, nBytes)
  121.       GroupContext *context0;  BYTE *data;  LONG nBytes; {
  122.     register GroupContext *context = context0;
  123.  
  124.     if ( context->ckHdr.ckID == NULL_CHUNK  ||    /* not in a chunk */
  125.      nBytes < 0  ||                /* negative nBytes */
  126.      (Known(context->bound)  &&        /* overflow context */
  127.         context->position + nBytes > context->bound)  ||
  128.      (Known(context->ckHdr.ckSize)  &&       /* overflow chunk */
  129.         context->bytesSoFar + nBytes > context->ckHdr.ckSize) )
  130.     return(CLIENT_ERROR);
  131.  
  132.     if (0 > GWrite(context->file, data, nBytes))
  133.     return(DOS_ERROR);
  134.  
  135.     context->bytesSoFar += nBytes;
  136.     context->position   += nBytes;
  137.     return(IFF_OKAY);
  138.     }
  139. IFFP PutCkEnd(context0)  GroupContext *context0; {
  140.     register GroupContext *context = context0;
  141.     WORD zero = 0;    /* padding source */
  142.  
  143.     if ( context->ckHdr.ckID == NULL_CHUNK )  /* not in a chunk */
  144.     return(CLIENT_ERROR);
  145.     if ( context->ckHdr.ckSize == szNotYetKnown ) {
  146.     if ( 0 >
  147. GSeek(context->file, -(context->bytesSoFar + sizeof(LONG)), OFFSET_CURRENT) ||
  148.          0 >
  149. GWrite(context->file, (BYTE *)&context->bytesSoFar, sizeof(LONG))  ||
  150.          0 >
  151. GSeek(context->file, context->bytesSoFar, OFFSET_CURRENT)  )
  152.         return(DOS_ERROR);
  153.     }
  154.     else {
  155.     if ( context->ckHdr.ckSize != context->bytesSoFar )
  156.         return(CLIENT_ERROR);
  157.     };
  158.     if ( IS_ODD(context->bytesSoFar) ) {
  159.     if ( 0 > GWrite(context->file, (BYTE *)&zero, 1) )
  160.         return(DOS_ERROR);
  161.     context->position += 1;
  162.     };
  163.     context->ckHdr.ckID   = NULL_CHUNK;
  164.     context->ckHdr.ckSize = context->bytesSoFar = 0;
  165.     return(IFF_OKAY);
  166.     }