#include <stdio.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#ifndef _lint
#include <unistd.h>
#endif
 

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: buildcat.c,v 1.16 1997/09/07 00:31:16 root Exp $";
#endif

#define DATFILE		"catalog.dat"
#define HDRFILE		"catalog.h"
#define CATFILE		"/etc/catalog.cat"
#define LABEL		"CATALOG_H"

#define NULLFILE	((FILE *)0)
#define NULLCHAR	((char *)0)
#define CTL		'@'
#define DOSEOF		('Z' - CTL)

int CATALOGPADDING = 10;


int
main (int argc, char *argv[])
{
int theindex = 1;
int firstfile = 1;
char buffer[256];
char input[1024];
char *cp, *cp2;
FILE *in, *cat, *header;
time_t now;
int padding;
long originalsize = 0;
char *lastfilename = NULLCHAR;


	/* check to see if an optional padding override is being given */
	if (argc > 1)	{
		CATALOGPADDING = atoi (argv[1]);
		if (!CATALOGPADDING)
			CATALOGPADDING = 1;
	}
	if (CATALOGPADDING != 1)
		printf ("--- buildcat: Using padding offset of %d...\n", CATALOGPADDING);
	
	/* open the input data file */
	if ((in = fopen (DATFILE, "rt")) == NULLFILE)	{
		printf ("buildcat: can't open '%s'\n", DATFILE);
		return (1);
	}

	/* now, look for an existing file. If found, save it's size */
	if ((cat  = fopen (NOSDIR CATFILE, "rb")) != NULLFILE)	{
		fseek (cat, 0, SEEK_END);
		originalsize = ftell (cat);
		fclose (cat);
		originalsize /= 256;
	}

	/* open the output catalog file */
	if ((cat = fopen (NOSDIR CATFILE, "wb")) == NULLFILE)	{
		printf ("buildcat: can't open '%s'\n", NOSDIR CATFILE);
		return (1);
	}

	/* open the output header file */
	if ((header = fopen (HDRFILE, "wt")) == NULLFILE)	{
		printf ("buildcat: can't open '%s'\n", HDRFILE);
		return (1);
	}

	/* place the initial information in the header file */
	(void) time (&now);
	fprintf (header, "\n#ifndef %s\n#define %s\n\n/*\n"
		" * Catalog header file for TNOS %s\n *\n * Built on %s *\n * Do NOT modify this file!\n *\n"
		" * Instead, properly modify the '%s' file and execute 'buildcat'\n *\n */\n\n",
		LABEL, LABEL, VERSION, ctime (&now), DATFILE);

	if (CATALOGPADDING != 1)
		fprintf (header, "/* Padding each file to a multiple of %d */\n\n", CATALOGPADDING);

	/* and place an identification record as the first one in the cat file */
	memset (buffer, 0, 256);
	sprintf (buffer, "TNOS catalog file, based on TNOS %s\nCatalog built on %s"
		"\n\n\n\n\n\n\n\n%c", VERSION, ctime (&now), DOSEOF);
	fwrite (buffer, 1, 256, cat);

	/* loop while there is data left in the data file */
	while (fgets (input, 1024, in))	{
		/* if it is a comment, skip it */
		if (*input == '\n' || *input == '#')
			continue;

		/* if it is a string entry, but we haven't seen the first filename, then error */
		if (*input != '[' && firstfile)	{
			printf ("buildcat: parsing error. First filename not defined before "
				"first data line\n> %s\n", input);
			return (1);
		}

		/* is this a new filename ? */
		if (*input == '[')	{	/* new filename */
			if ((cp = strchr(&input[1], '.')) != NULLCHAR)
				*cp = 0;
			/* add it to the header file */
			padding = 0;
			if (theindex != 1)	{
				while (theindex % CATALOGPADDING)	{
					memset (buffer, 0, 256);
					strcpy (buffer, "Undefined catalog string!\n");
					fwrite (buffer, 1, 256, cat);
					theindex++;
					padding++;
				}
			}
			if (padding)
				fprintf (header, "\t/* There are %d available strings in %s.c - filled with padding */\n",
					padding, lastfilename);
			if (lastfilename)
				free (lastfilename);
			lastfilename = strdup (&input[1]);
			fprintf (header, "#define %s_catalog %d\n", &input[1], theindex);
			firstfile = 0;
			continue;
		}

		/* make sure there is a string in quotation marks */
		if ((cp = strchr (input, '\"')) == NULLCHAR || (cp2 = strrchr (++cp, '\"')) == NULLCHAR)	{
			printf ("buildcat: parsing error. Line missing quotation marks!\n"
				"> %s\n", input);
			return(1);
		}
		*cp2 = 0;

		/* check the length for < 256 bytes */
		if (strlen (cp) > 255)	{
			printf ("buildcat: parsing error. Line exceeds maximum length!\n"
				"> %s\n", input);
			return (1);
		}

		/* initialize the buffer to zeros, first, then copy the string */
		memset (buffer, 0, 256);
		cp2 = buffer;
		while (*cp)	{
			if (*cp == '\\')	{
				switch (cp[1])	{
					case 'n':	*cp2++ = '\n';
							cp += 2;
							break;
					case 'r':	*cp2++ = '\r';
							cp += 2;
							break;
					case 'b':	*cp2++ = '\b';
							cp += 2;
							break;
					case '\"':	*cp2++ = '\"';
							cp += 2;
							break;
					default:	*cp2++ = *cp++;
				}
			} else
				*cp2++ = *cp++;
		}

		/* now write it to the catalog file */
		fwrite (buffer, 1, 256, cat);
		theindex++;
	}
	/* write trailer to header file */
	fprintf (header, "\n\nchar * catalog (int base, int theindex);"
		"\nint catalog_check (void);"
		"\n\n#endif /* %s */\n\n/* File complete */\n", LABEL);

	/* and close the files */
	fclose (header);
	fclose (cat);
	fclose (in);

	/* tell the user all is well */
	if (originalsize && originalsize != theindex)
		printf ("--- buildcat: new catalog file size differs from previous one!\n");
	printf ("--- buildcat: catalog file building complete!\n");
	return 0;
}


