home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 2 / goldfish_vol2_cd1.bin / files / comm / misc / elcheapofax / rcs / parse.c,v < prev    next >
Text File  |  1993-12-21  |  11KB  |  485 lines

  1. head    1.2;
  2. access;
  3. symbols
  4.     OCT93:1.2;
  5. locks;
  6. comment    @ * @;
  7.  
  8.  
  9. 1.2
  10. date    93.06.11.16.33.37;    author Rhialto;    state Exp;
  11. branches;
  12. next    1.1;
  13.  
  14. 1.1
  15. date    93.06.11.14.53.53;    author Rhialto;    state Exp;
  16. branches;
  17. next    ;
  18.  
  19.  
  20. desc
  21. @IFF parser driver, using iffparse.library
  22. @
  23.  
  24.  
  25. 1.2
  26. log
  27. @First real RCS checkin
  28. @
  29. text
  30. @/*
  31.  * parse.c - iffparse file IO support module
  32.  *   based on some of looki.c by Leo Schwab
  33.  *
  34.  * The filename for clipboard is -c or -cUnit as in -c0 -c1 etc. (default 0)
  35.  */
  36. /* $Id$
  37.  * $Log$
  38.  */
  39.  
  40. #include <exec/types.h>
  41.  
  42. #include "iffp/iff.h"
  43.  
  44. /* local function prototypes */
  45.  
  46. static LONG stdio_stream(struct Hook *, struct IFFHandle *, struct IFFStreamCmd *);
  47.  
  48. UBYTE *omodes[2] = {"r","w"};
  49.  
  50.  
  51. /* openifile
  52.  *
  53.  * Passed a ParseInfo structure with a not-in-use IFFHandle, filename
  54.  *   ("-c" or -cUnit like "-c1" for clipboard), and IFF open mode
  55.  *   (IFFF_READ or IFFF_WRITE) opens file or clipboard for use with
  56.  *   iffparse.library support modules.
  57.  *
  58.  * Returns 0 for success or an IFFERR (libraries/iffparse.h)
  59.  */
  60.  
  61. LONG openifile(struct ParseInfo *pi, UBYTE *filename, ULONG iffopenmode)
  62. {
  63.     struct IFFHandle    *iff;
  64.     BOOL    cboard;
  65.     ULONG    unit = PRIMARY_CLIP;
  66.     LONG    error;
  67.  
  68.     if(!pi)                 return(CLIENT_ERROR);
  69.     if(!(iff=pi->iff))      return(CLIENT_ERROR);
  70.  
  71.     cboard = (*filename == '-'  &&  filename[1] == 'c');
  72.     if(cboard && filename[2])       unit = atoi(&filename[2]);
  73.  
  74.     if (cboard)
  75.         {
  76.         /*
  77.          * Set up IFFHandle for Clipboard I/O.
  78.          */
  79.         pi->clipboard = TRUE;
  80.         if (!(iff->iff_Stream =
  81.                 (ULONG)OpenClipboard(unit)))
  82.             {
  83. /*            message(SI(MSG_IFFP_NOCLIP_D),unit); */
  84.             return(NOFILE);
  85.             }
  86.         InitIFFasClip(iff);
  87.         }
  88.     else
  89.         {
  90.         pi->clipboard = FALSE;
  91.         /*
  92.          * Set up IFFHandle for buffered stdio I/O.
  93.          */
  94.         if (!(iff->iff_Stream = (ULONG)
  95.            fopen(filename, omodes[iffopenmode & 1])))
  96.             {
  97. /*            message(SI(MSG_IFFP_NOFILE_S),filename); */
  98.             return(NOFILE);
  99.             }
  100.         else initiffasstdio(iff);
  101.         }
  102.  
  103.     D(bug("%s file opened: \n", cboard ? "[Clipboard]" : (char *)filename));
  104.  
  105.     pi->filename = filename;
  106.  
  107.     error=OpenIFF(iff, iffopenmode);
  108.  
  109.     pi->opened = error ? FALSE : TRUE;    /* currently open handle */
  110.  
  111.     D(bug("OpenIFF error = %ld\n",error));
  112.     return(error);
  113. }
  114.  
  115.  
  116. /* closeifile
  117.  *
  118.  * closes file or clipboard opened with openifile, and frees all
  119.  *   iffparse context parsed by parseifile.
  120.  *
  121.  * Note - You should closeifile as soon as possible if using clipboard
  122.  *   ("-c[n]").  You also need to closeifile if, for example, you wish to
  123.  *   reopen the file to write changes back out.  See the copychunks.c
  124.  *   module for routines which allow you clone the chunks iffparse has
  125.  *   gathered so that you can closeifile and still be able to modify and
  126.  *   write back out gathered chunks.
  127.  *
  128.  */
  129.  
  130. void closeifile(struct ParseInfo *pi)
  131. {
  132. struct IFFHandle *iff;
  133.  
  134.     D(bug("closeifile:\n"));
  135.  
  136.     if(!pi)                 return;
  137.     if(!(iff=pi->iff))      return;
  138.  
  139.     DD(bug("closeifile: About to CloseIFF if open, iff=$%lx, opened=%ld\n",
  140.             iff, pi->opened));
  141.  
  142.     if(pi->opened)  CloseIFF(iff);
  143.  
  144.     DD(bug("closeifile: About to close %s, stream=$%lx\n",
  145.             pi->clipboard ? "clipboard" : "file", iff->iff_Stream));
  146.     if(iff->iff_Stream)
  147.         {
  148.         if (pi->clipboard)
  149.            CloseClipboard((struct ClipHandle *)(iff->iff_Stream));
  150.         else
  151.            fclose ((FILE *)(iff->iff_Stream));
  152.         }
  153.  
  154.     iff->iff_Stream = NULL;
  155.     pi->clipboard = NULL;
  156.     pi->opened = NULL;
  157. }
  158.  
  159.  
  160. /* parseifile
  161.  *
  162.  * Passed a ParseInfo with an initialized and open IFFHandle,
  163.  *  grouptype (like ID_FORM), groupid (like ID_ILBM),
  164.  *  and TAG_DONE terminated longword arrays of type,id
  165.  *  for chunks to be grabbed, gathered, and stopped on
  166.  *  (like { ID_ILBM, ID_BMHD, ID_ILBM, ID_CAMG, TAG_DONE })
  167.  *  will parse an IFF file, grabbing/gathering and stopping
  168.  *  on specified chunk.
  169.  *
  170.  * Note - you can call getcontext() (to continue after a stop chunk) or
  171.  *  nextcontext() (after IFFERR_EOC, to parse next form in the same file)
  172.  *  if you wish to continue parsing the same IFF file.    If parseifile()
  173.  *  has to delve into a complex format to find your desired FORM, the
  174.  *  pi->hunt flag will be set.    This should be a signal to you that
  175.  *  you may not have the capability to simply modify and rewrite
  176.  *  the data you have gathered.
  177.  *
  178.  * Returns 0 for success else and IFFERR (libraries/iffparse.h)
  179.  */
  180.  
  181. LONG parseifile(pi,groupid,grouptype,propchks,collectchks,stopchks)
  182. struct    ParseInfo *pi;
  183. LONG groupid, grouptype;
  184. LONG *propchks, *collectchks, *stopchks;
  185. {
  186. struct IFFHandle *iff;
  187. register struct ContextNode    *cn;
  188. LONG            error = 0L;
  189.  
  190.  
  191.     if(!(iff=pi->iff))      return(CLIENT_ERROR);
  192.  
  193.     if(!iff->iff_Stream)    return(IFFERR_READ);
  194.  
  195.     pi->hunt = FALSE;
  196.  
  197.     /*
  198.      * Declare property, collection and stop chunks.
  199.      */
  200.     if (propchks)
  201.       if (error = PropChunks (iff, propchks, chkcnt(propchks)))
  202.         return (error);
  203.     if (collectchks)
  204.       if (error =
  205.           CollectionChunks(iff, collectchks, chkcnt(collectchks)))
  206.         return (error);
  207.     if (stopchks)
  208.       if (error = StopChunks (iff, stopchks, chkcnt(stopchks)))
  209.         return (error);
  210.  
  211.     /*
  212.      * We want to stop at the end of an ILBM context.
  213.      */
  214.     if (grouptype)
  215.       if (error = StopOnExit (iff, grouptype, groupid))
  216.         return(error);
  217.  
  218.     /*
  219.      * Take first parse step to enter main chunk.
  220.      */
  221.     if (error = ParseIFF (iff, IFFPARSE_STEP))
  222.         return(error);
  223.  
  224.     /*
  225.      * Test the chunk info to see if simple form of type we want (ILBM).
  226.      */
  227.     if (!(cn = CurrentChunk (iff)))
  228.         {
  229.         /*
  230.          * This really should never happen.  If it does, it means
  231.          * our parser is broken.
  232.          */
  233. /*        message(SI(MSG_IFFP_NOTOP)); */
  234.         return(NOFILE);
  235.         }
  236.  
  237.     if (cn->cn_ID != groupid  ||  cn->cn_Type != grouptype)
  238.         {
  239.  
  240.         D(bug("This is a(n) %.4s.%.4s.  Looking for embedded %.4s's...\n",
  241.           &cn->cn_Type, &cn->cn_ID, &grouptype));
  242.  
  243.         pi->hunt = TRUE;    /* Warning - this is a complex file */
  244.         }
  245.  
  246.     if(!error)      error = getcontext(iff);
  247.     return(error);
  248. }
  249.  
  250. /* chkcnt
  251.  *
  252.  * simply counts the number of chunk pairs (type,id) in array
  253.  */
  254. LONG chkcnt(LONG *taggedarray)
  255. {
  256. LONG k = 0;
  257.  
  258.     while(taggedarray[k] != TAG_DONE) k++;
  259.     return(k>>1);
  260. }
  261.  
  262.  
  263. /* currentchunkis
  264.  *
  265.  * returns the ID of the current chunk (like ID_CAMG)
  266.  */
  267. LONG currentchunkis(struct IFFHandle *iff, LONG type, LONG id)
  268. {
  269. register struct ContextNode    *cn;
  270. LONG result = 0;
  271.  
  272.     if (cn = CurrentChunk (iff))
  273.         {
  274.         if((cn->cn_Type == type)&&(cn->cn_ID == id)) result = 1;
  275.         }
  276.     return(result);
  277. }
  278.  
  279.  
  280. /* contextis
  281.  *
  282.  * returns the enclosing context of the current chunk (like ID_ILBM)
  283.  */
  284. LONG contextis(struct IFFHandle *iff, LONG type, LONG id)
  285. {
  286. register struct ContextNode    *cn;
  287. LONG result = 0;
  288.  
  289.        if (cn = (CurrentChunk (iff)))
  290.        {
  291.        if (cn = (ParentChunk(cn)))
  292.            {
  293.            if((cn->cn_Type == type)&&(cn->cn_ID == id)) result = 1;
  294.            }
  295.        }
  296.  
  297.     D(bug("This is a %.4s %.4s\n",&cn->cn_Type,&cn->cn_ID));
  298.  
  299.     return(result);
  300. }
  301.  
  302.  
  303. /* getcontext()
  304.  *
  305.  * Continues to gather the context which was specified to parseifile(),
  306.  *  stopping at specified stop chunk, or end of context, or EOF
  307.  *
  308.  * Returns 0 (stopped on a stop chunk)
  309.  *    or IFFERR_EOC (end of context, not an error)
  310.  *    or IFFER_EOF (end of file)
  311.  */
  312. LONG getcontext(iff)
  313. struct    IFFHandle *iff;
  314. {
  315.     LONG error = 0L;
  316.  
  317.     /* Based on our parse initialization,
  318.      * ParseIFF() will return on a stop chunk (error = 0)
  319.      * or end of context for an ILBM FORM (error = IFFERR_EOC)
  320.      * or end of file (error = IFFERR_EOF)
  321.      */
  322.     return(error = ParseIFF(iff, IFFPARSE_SCAN));
  323. }
  324.  
  325.  
  326. /* nextcontext
  327.  *
  328.  * If you have finished parsing and reading your context (IFFERR_EOC),
  329.  *   nextcontext will enter the next context contained in the file
  330.  *   and parse it.
  331.  *
  332.  * Returns 0 or an IFFERR such as IFFERR_EOF (end of file)
  333.  */
  334.  
  335. LONG nextcontext(iff)
  336. struct    IFFHandle *iff;
  337. {
  338.     LONG error = 0L;
  339.  
  340.     error = ParseIFF(iff, IFFPARSE_STEP);
  341.  
  342.     D(bug("nextcontext: Got through next step\n"));
  343.  
  344.     return(error);
  345. }
  346.  
  347.  
  348. /* findpropdata
  349.  *
  350.  * finds specified chunk parsed from IFF file, and
  351.  *   returns pointer to its sp_Data (or 0 for not found)
  352.  */
  353. UBYTE *findpropdata(iff, type, id)
  354. struct IFFHandle    *iff;
  355. LONG type, id;
  356.     {
  357.     register struct StoredProperty    *sp;
  358.  
  359.     if(sp = FindProp (iff, type, id)) return(sp->sp_Data);
  360.     return(0);
  361.     }
  362.  
  363.  
  364. /*
  365.  * File I/O hook functions which the IFF library will call.
  366.  * A return of 0 indicates success (no error).
  367.  *
  368.  * Iffparse.library calls this code via struct Hook and Hook.asm
  369.  */
  370. static LONG
  371. stdio_stream (struct Hook *hook, struct IFFHandle *iff,
  372.             struct IFFStreamCmd *actionpkt)
  373. {
  374.     register FILE    *stream;
  375.     register LONG    nbytes;
  376.     register int    actual;
  377.     register UBYTE    *buf;
  378.     long    len;
  379.  
  380.     stream    = (FILE *) iff->iff_Stream;
  381.     if(!stream)     return(1);
  382.  
  383.     nbytes    = actionpkt->sc_NBytes;
  384.     buf    = (UBYTE *) actionpkt->sc_Buf;
  385.  
  386.     switch (actionpkt->sc_Command) {
  387.     case IFFSCC_READ:
  388.         do {
  389.             actual = nbytes > 32767 ? 32767 : nbytes;
  390.             if ((len=fread (buf, 1, actual, stream)) != actual)
  391.                 break;
  392.             nbytes -= actual;
  393.             buf += actual;
  394.         } while (nbytes > 0);
  395.         return (nbytes ? IFFERR_READ : 0 );
  396.  
  397.     case IFFSCC_WRITE:
  398.         do {
  399.             actual = nbytes > 32767 ? 32767 : nbytes;
  400.             if ((len=fwrite (buf, 1, actual, stream)) != actual)
  401.                 break;
  402.             nbytes -= actual;
  403.             buf += actual;
  404.         } while (nbytes > 0);
  405.         return (nbytes ? IFFERR_WRITE : 0);
  406.  
  407.     case IFFSCC_SEEK:
  408.         return ((fseek (stream, nbytes, 1) == -1) ? IFFERR_SEEK : 0);
  409.  
  410.     default:
  411.         /*  No _INIT or _CLEANUP required.  */
  412.         return (0);
  413.     }
  414. }
  415.  
  416. /* initiffasstdio (ie. init iff as stdio)
  417.  *
  418.  * sets up hook callback for the file stream handler above
  419.  */
  420. void initiffasstdio (iff)
  421. struct IFFHandle *iff;
  422. {
  423.     extern LONG        HookEntry();
  424.     static struct Hook    stdiohook = {
  425.         { NULL },
  426.         (ULONG (*)()) HookEntry,
  427.         (ULONG (*)()) stdio_stream,
  428.         NULL
  429.     };
  430.  
  431.     /*
  432.      * Initialize the IFF structure to point to the buffered I/O
  433.      * routines.  Unbuffered I/O is terribly slow.
  434.      */
  435.     InitIFF (iff, IFFF_FSEEK | IFFF_RSEEK, &stdiohook);
  436. #ifdef _DCC
  437.     setvbuf((FILE *)iff->iff_Stream, NULL, _IOFBF, 16384);
  438. #endif
  439. }
  440.  
  441.  
  442. /*
  443.  * PutCk
  444.  *
  445.  * Writes one chunk of data to an iffhandle
  446.  *
  447.  */
  448. long PutCk(struct IFFHandle *iff, long id, long size, void *data)
  449.     {
  450.     long error = 0, wlen;
  451.  
  452.     D(bug("PutCk: asked to push chunk \"%.4s\" ($%lx) length %ld\n",&id,id,size));
  453.  
  454.     if(error=PushChunk(iff, 0, id, size))
  455.     {
  456.     D(bug("PutCk: PushChunk of %.4s, error = %s, size = %ld\n",
  457.         id, IFFerr(error), id));
  458.     }
  459.     else
  460.     {
  461.     D(bug("PutCk: PushChunk of %.4s, error = %ld\n",&id, error));
  462.  
  463.     /* Write the actual data */
  464.     if((wlen = WriteChunkBytes(iff,data,size)) != size)
  465.         {
  466.         D(bug("WriteChunkBytes error: size = %ld, wrote %ld\n",size,wlen));
  467.         error = IFFERR_WRITE;
  468.         }
  469.     else error = PopChunk(iff);
  470.     D(bug("PutCk: After PopChunk - error = %ld\n",error));
  471.     }
  472.     return(error);
  473.     }
  474.  
  475. @
  476.  
  477.  
  478. 1.1
  479. log
  480. @Initial revision
  481. @
  482. text
  483. @d7 3
  484. @
  485.