/* iffar - IFF CAT archiver table of contents functions

   By Karl Lehenbauer, version 1.2, release date 5/9/88.
   This code is released to the public domain.
   See the README file for more information.

*/

#include <exec/types.h>
#include <exec/memory.h>
#include <stdio.h>
#include <fcntl.h>
#include "assert.h"
#include "iff.h"

#define ID_NAME MakeID('N','A','M','E')
#define ID_AUTH MakeID('A','U','T','H')
#define ID_ANNO MakeID('A','N','N','O')
#define ID_Copyright MakeID('(','c',')',' ')

extern long lseek();

extern ULONG nextchunk();

int table_of_contents(fname)
char *fname;
{
	int fd;
	ULONG cat_type, chunkid, innerchunkid, subtype;
	long chunksize, innerchunksize, filesize;
	char namebuf[256];

	extern int verbose;

    if ((fd = OpenCAT(fname,&cat_type,&filesize)) == -1)
	{
		fprintf(stderr,"Can't open archive '%s'\n",fname);
		return(0);
	}

	if (verbose)
	{
		fprintf(stderr,"CAT subtype is ");
		PutID(cat_type);
		fprintf(stderr,"\n");
	}

	while ((chunkid = nextCATchunk(fd,&subtype,&namebuf[0],&chunksize,&filesize)) != 0L)
	{
		/* if the chunk type isn't FORM, CAT or LIST, skip it */
		 if (chunkid != ID_FORM && chunkid != ID_CAT && chunkid != ID_LIST)
		 {
		 	if (verbose)
			{
				PutID(chunkid);
				fprintf(stderr," chunk is being skipped\n");
			}
			skipchunk(fd,chunksize,&filesize);
			goto bigchunkdone;
		}

		if (namebuf[0] == '\0')
		{
			fprintf(stderr,"CAT entry didn't contain a FNAM chunk - skipping\n");
			skipchunk(fd,chunksize,&filesize);
			goto bigchunkdone;
		}

		PutID(chunkid);
		fprintf(stderr," ");
		/* print out the chunk length */
		PutID(subtype);
		fprintf(stderr," %6ld  %s\n",chunksize, namebuf);

		/* if verbose isn't selected, skip the rest of the chunks in the
		 * embedded FORM, CAT or LIST
		 */
		if (!verbose)
		{
		 	skipchunk(fd,chunksize,&filesize);
			goto bigchunkdone;
		}

		/* else verbose is selected, dive down into the embedded FORM, 
		 * CAT or LIST and print chunks found there and their contents
		 * when they're known to be text.
		 */

		/* follow a good neighbor policy by reducing our (the parent's)
		 * chunk size by the size we've found - since we'll be moving
		 * through the embedded FORM effectively recursively; that is,
		 * we'll be using the same nextchunk, skipchunk, readchunk
		 * routines on the chunk nextchunk got for us, we'll
		 * decrease parent chunk size by the size we've found,
		 * as, when calling nextchunk, skipchunk and readchunk below,
		 * we'll be concerned with keeping track of the form's chunk length
		 * as a virtual EOF, rather than the whole CAT's as above
		 */
		filesize -= chunksize;
		if (chunksize & 1)
			filesize--;

		while (chunksize != 0)
		{
			/* get the type and size of the inner chunk */
			innerchunkid = nextchunk(fd,&innerchunksize,&chunksize);
			if (chunksize == 0)
				break;


			/* print some presumably useful information */
			fprintf(stderr,"   ");
			PutID(innerchunkid);

			switch(innerchunkid)
			{
				case ID_FNAM:
					panic("more than one FNAM chunk in an embedded FORM");

				case ID_NAME:
				case ID_AUTH:
				case ID_ANNO:
				case ID_Copyright:
						if (innerchunksize >= sizeof(namebuf))
						{
							fprintf(stderr,"[too long]\n");
							skipchunk(fd,innerchunksize,&chunksize);
						}
						else
						{
							if (!readchunk(fd,namebuf,innerchunksize,&chunksize))
							{
								fprintf(stderr,"got into trouble reading chunk text\n");
								return(0);
							}
							namebuf[innerchunksize] = '\0';
							fprintf(stderr,", %s\n",namebuf);
						}
					break;

				default:
					fprintf(stderr,", size %ld\n",innerchunksize);

					/* skip the body of the subchunk */
					skipchunk(fd,innerchunksize,&chunksize);
				}
		}
		/* we make it to here if the length of all the subchunks equalled
		 * the length of their superchunk
		 */
		 bigchunkdone: ;
	}
	close(fd);
}

/* end of toc.c */
