/*
 * cootxt - The incredible fortune cookie system concatenator program
 */

/* Version T1.00 - 31-Oct-86 - tmk - Initial portable version		*/
/* Version T1.01 - 01-Nov-86 - tmk - Close & re-open files between passes
				     for PDP-11 DECUS C compiler	*/
/* Version T1.02 - 20-Nov-86 - tmk - Add stuff for VAX C, fix problems with
				     with item counts being off if missing
				     leading or trailing %%		*/
/* Version T1.03 - 10-Dec-86 - tmk - Remove pathname for data files from
				     COONO1, add as command line arg.	*/
/* Version T1.04 - 18-Apr-87 - tmk - Cleanup by lint			*/
/* Version T1.05 - 30-Jun-87 - tmk - Speedup code by tmk/gpm		*/
/* Version T1.06 - 02-Jul-87 - tmk - Add support for Turbo C		*/
/* Version T1.07 - 13-Aug-87 - tmk - Fix splats on DECUS via BUGFIX.C	*/
/* Version T1.08 - 27-Nov-87 - tmk - Add function prototypes		*/
/* Version T1.09 - 18-Jul-88 - tmk - Make file I/O errors fatal, set error
				     level on MS-DOS			*/
/* Version V1.20 - 24-Jul-88 - tmk - Official release version (finally)	*/
/* Version V1.21 - 25-Sep-89 - tmk - Tighten the spacing between the parts
				     of the directory so VMS file doesn't
				     cause the screen to wrap		*/
/* Version V1.22 - 21-Dec-89 - tmk - Add support for DEC PDP-11 C V1.0	*/
/* Version V1.23 - 19-Nov-90 - tmk - Add support for 2.10BSD Unix	*/

#define VERSION		"V1.23 19-Nov-90 - tmk"

/*
 * Define module ID for VMS (must go for Turbo C and Unix, else bogus error)
 */
/*ifdef	Pseudo-ifdef for Turbo C and Unix */
#ifdef	vms
#ifdef	__DECC
#pragma	module	cootxt	VERSION
#else
#module	cootxt	VERSION
#endif	/* __DECC */
#endif	/* vms */
/*ifdef	Pseudo-ifdef for Turbo C and Unix */
#ifdef	__pdp11c
#pragma list title VERSION
#endif	/* __pdp11c */

/*
 * Convince Turbo C it's running under MS-DOS (it isn't sure)
 */
#ifdef	__TURBOC__
#define	MSDOS		1
#endif	/* __TURBOC__ */

/*
 * Grab some header files
 */
#include <stdio.h>
#include <ctype.h>
#ifndef	decus
#ifndef	unix
#include <stdlib.h>
#endif	/* unix */
#include <string.h>
#endif	/* decus */

/*
 * Have a fight about function declarations and file modes
 */
#ifdef	decus
#define	w_mode	"w"
#define	void
#else
#ifdef	__pdp11c
#define	w_mode	"w"	/* DEC C forces binary on appends, so don't use */
#else
#define	w_mode	"w+"
#endif	/* __pdp11c */
#endif	/* decus */

/*
 * Define some constants
 */
#define	FALSE	0
#define	TRUE	1
#define	SLINE	sizeof(line)
#define	SNAME	sizeof(name)
#ifdef	vms
#define	IO_SUC	65535
#define	IO_ERR	65535
#else
#define	IO_SUC	0
#define	IO_ERR	1
#endif	/* vms */

/*
 * Global variables
 */
char	line[513];
int	nxtcoo	= 3;
char	*where	= "";			/* Default location for files	*/
char	*ctlfn	= "coono1.src";		/* Default control file name	*/
char	*outfn	= "cookie.txt";		/* Default output file name	*/

/*
 * For 'modern' compilers (all except decus), supply function prototypes
 */
#ifndef	decus
#ifdef	unix
extern	int  main();
extern	void process();
#else
extern	int  main(int, char **);
extern	void process(FILE *, FILE *);
#endif	/* unix */
#endif	/* decus */

/*
 * Actual code starts here
 */
int main(argc, argv)
int	argc;
char	*argv[];
{
	FILE		*ctlfd, *outfd, *coofd;
	register char	*n, *ap;
	char		coofn[100],
			*bfpn;
	char		name[100], finis[16];
	int		fstcoo, lstcoo;
#ifdef	unix
	int		i;
	char		ifpn[100];
#endif	/* unix */

	while (argc > 1) {
	    ap = argv[1];
	    if (*ap != '-') {
		fprintf(stderr, "?Unknown command \"%s\"\n", ap);
#ifdef	unix
		fprintf(stderr, "  do cootxt -z for help.\n\n\n");
#else
		fprintf(stderr, "  do COOTXT -? for help.\n\n\n");
#endif	/* unix */
	    }
	    else for (ap++; *ap; ap++) {
#ifdef	unix
		switch (isupper(*ap) ? tolower(*ap) : *ap) {
#else
		switch (tolower(*ap)) {
#endif	/* unix */
		case 'f':		/* Use different control file	*/
		    if (isgraph(ap[1]) != 0)
			ctlfn = &ap[1];
		    else if (argc > 2) {
			ctlfn = argv[2];
			argv++;
			argc--;
		    }
		    else {
			break;
		    }
		    goto next_arg;

		case 'l':		/* Specify location of infiles	*/
		    if (isgraph(ap[1]) != 0)
			where = &ap[1];
		    else if (argc > 2) {
			where = argv[2];
			argv++;
			argc--;
		    }
		    else {
			break;
		    }
		    goto next_arg;

		case 'o':		/* Use different output file	*/
		    if (isgraph(ap[1]) != 0)
			outfn = &ap[1];
		    else if (argc > 2) {
			outfn = argv[2];
			argv++;
			argc--;
		    }
		    else {
			break;
		    }
		    goto next_arg;

#ifdef	unix
		case 'z':		/* Display help message		*/
#else
		case '?':		/* Display help message		*/
#endif	/* unix */
		    printf("COOTXT %s",VERSION);
#ifdef	unix
		    printf("\n\nUsage is: cootxt option option...\n");
#else
		    printf("\n\nUsage is: COOTXT option option...\n");
#endif	/* unix */
		    printf("Options: -f fn  Use FN as control file\n");
		    printf("         -l pn  Use PN as path for files\n");
		    printf("         -o fn  Write output to file FN\n");
#ifdef	unix
		    printf("         -z     Print this message\n");
#else
		    printf("         -?     Print this message\n");
#endif	/* UNIX */
		    exit(IO_SUC);
		    break;

		default:
		    fprintf(stderr, "?Unknown option '%c'\n", *ap);
#ifdef	unix
		    fprintf(stderr, "  do cootxt -z for help.\n\n\n");
#else
		    fprintf(stderr, "  do COOTXT -? for help.\n\n\n");
#endif	/* unix */
		}
	    }
	    next_arg:
	    argc--;
	    argv++;
	}

/*
 * Pass 1 - collect cookie numbers and create preaamble in output file
 */
	if ((ctlfd = fopen(ctlfn, "r")) == NULL) {
	    perror(ctlfn);
	    exit(IO_ERR);
	}

	fgets(finis, sizeof(finis), ctlfd);
	if ((n=(char *)strchr(finis, '\n')) != NULL)
	    *n = '\0';			/* Get segment delimiter	*/
	if ((outfd = fopen(outfn, w_mode)) == NULL) {
	    perror(outfn);
	    exit(IO_ERR);
	}
	fgets(line, SLINE, ctlfd);	/* Read text line from ctl file	*/
	if ((n=(char *)strchr(line, '\n')) != NULL)
	    *n = '\0';
	while (strncmp(line, finis, 4) != 0) {
	    fputs(line, outfd);		/* Write it out to final file	*/
	    fputs("\n", outfd); 	/* Add in newline		*/
	    fgets(line, SLINE, ctlfd);
	    if ((n=(char *)strchr(line, '\n')) != NULL)
		*n = '\0';
	}

	fprintf(outfd, "  %05d-%05d  This Cookie, Disclaimer and Warning\n",
		1, 2);
	printf("%05d-%05d  This Cookie, Disclaimer and Warning\n",
		1, 2);			/* Print dummy entry for first	*/

	strcpy(coofn, where);
	bfpn = fgets(name, SNAME, ctlfd);
	if ((n=(char *)strchr(name, '\n')) != NULL)
	    *n = '\0';			/* Get next input file name	*/
#ifdef	unix
	strcpy(ifpn, bfpn);
	if (ifpn[0] != '*') {
	    for (i = 0; ifpn[i]; i++) {
		if (isupper(ifpn[i]))
		    ifpn[i] = tolower(ifpn[i]);
	    }
	}
	bfpn = ifpn;
#endif	/* unix */
	strcat(coofn, bfpn);
	while (strncmp(bfpn, finis, 4) != 0) {
	    if ((coofd = fopen(coofn, "r")) == NULL) {
		perror(coofn);
		exit(IO_ERR);
	    }
	    fstcoo = nxtcoo;		/* Get base cookie for file	*/
	    process(coofd, NULL);	/* Process for counts only	*/
	    fgets(line, SLINE, ctlfd); 	/* Read description line	*/
	    if ((n=(char *)strchr(line, '\n')) != NULL)
		*n = '\0';
	    lstcoo = nxtcoo - 1;	/* Last cookie is next minus 1	*/
	    fprintf(outfd, "  %05d-%05d  %-31s %s\n",
		fstcoo, lstcoo, line, coofn);
	    printf("%05d-%05d  %-31s %s\n", fstcoo, lstcoo, line, coofn);
	    fclose(coofd);
	    strcpy(coofn, where);
	    bfpn = fgets(name, SNAME, ctlfd);
	    if ((n=(char *)strchr(name, '\n')) != NULL)
		*n = '\0';		/* Get next input file name	*/
#ifdef	unix
	    strcpy(ifpn, bfpn);
	    if (ifpn[0] != '*') {
		for (i = 0; ifpn[i]; i++) {
		    if (isupper(ifpn[i]))
			ifpn[i] = tolower(ifpn[i]);
		}
	    }
	    bfpn = ifpn;
#endif	/* unix */
	    strcat(coofn, bfpn);
	}
	fgets(line, SLINE, ctlfd);	/* Read text line from ctl file	*/
	if ((n=(char *)strchr(line, '\n')) != NULL)
	    *n = '\0';
	while (strncmp(line, finis, 4) != 0) {
	    fputs(line, outfd);		/* Write it out to final file	*/
	    fputs("\n", outfd);		/* Add in newline		*/
	    fgets(line, SLINE, ctlfd);
	    if ((n=(char *)strchr(line, '\n')) != NULL)
		*n = '\0';
	}
	printf("End of pass 1.\n");

/*
 * Pass 2 - append all cookies to output file
 */
	fclose(ctlfd);
	if ((ctlfd=fopen(ctlfn, "r")) == NULL) {
	    perror(ctlfn);
	    exit(IO_ERR);
	}
	fgets(line, SLINE, ctlfd);	/* Eat the first *END line	*/
	fgets(line, SLINE, ctlfd);	/* Eat text until filename list	*/
	if ((n=(char *)strchr(line, '\n')) != NULL)
	    *n = '\0';
	while (strncmp(line, finis, 4) != 0) {
	    fgets(line, SLINE, ctlfd);
	    if ((n=(char *)strchr(line, '\n')) != NULL)
		*n = '\0';
	}
	nxtcoo = 1;			/* Art for art's sake		*/
#ifndef	decus
	printf(".");			/* First file is already in	*/
#ifdef	__pdp11c
	fflush(stdout);
#endif	/* __pdp11c */
#ifdef	unix
	fflush(stdout);
#endif	/* unix */
#else
	kb_spit(0, '.');		/* First file is already in	*/
#endif	/* decus */
	strcpy(coofn, where);
	bfpn = fgets(name, SNAME, ctlfd);
	if ((n=(char *)strchr(name, '\n')) != NULL)
	    *n = '\0';			/* Get next input file name	*/
#ifdef	unix
	strcpy(ifpn, bfpn);
	if (ifpn[0] != '*') {
	    for (i = 0; ifpn[i]; i++) {
		if (isupper(ifpn[i]))
		    ifpn[i] = tolower(ifpn[i]);
	    }
	}
	bfpn = ifpn;
#endif	/* unix */
	strcat(coofn, bfpn);
	while (strncmp(bfpn, finis, 4) != 0) {
#ifndef	decus
	    printf(".");		/* Show him where we are	*/
#ifdef	__pdp11c
	    fflush(stdout);
#endif	/* __pdp11c */
#ifdef	unix
	    fflush(stdout);
#endif	/* unix */
#else
	    kb_spit(0, '.');		/* Show him where we are	*/
#endif	/* decus */
	    if ((coofd = fopen(coofn, "r")) == NULL) {
		perror(coofn);
		exit(IO_ERR);
	    }
	    process(coofd, outfd);	/* Process 'em into final file	*/
	    fgets(line, SLINE, ctlfd);	/* Read description line (dummy)*/
	    fclose(coofd);
	    strcpy(coofn, where);
	    bfpn = fgets(name, SNAME, ctlfd);
	    if ((n=(char *)strchr(name, '\n')) != NULL)
		*n = '\0';		/* Get next input file name	*/
#ifdef	unix
	    strcpy(ifpn, bfpn);
	    if (ifpn[0] != '*') {
		for (i = 0; ifpn[i]; i++) {
		    if (isupper(ifpn[i]))
			ifpn[i] = tolower(ifpn[i]);
		}
	    }
	    bfpn = ifpn;
#endif	/* unix */
	    strcat(coofn, bfpn);
	}

	fclose(outfd);			/* Close real output file 	*/
	fclose(ctlfd);			/* and ctl file			*/

	printf("\nEnd of pass 2.\n");
	exit(IO_SUC);
}

void process(infile, outfile)
FILE	*infile, *outfile;		/* File pointer			*/
{
	register int	pflag, cflag;

	cflag = TRUE;			/* Default to flags written	*/
	fgets(line, SLINE, infile);
	if (line[0] != '%' && line[1] != '%') {
	    if (outfile != NULL)
   		fputs(line, outfile);	/* Strip initial flags		*/
	    cflag = FALSE;		/* Say we need flags		*/
	}
	while (fgets(line, SLINE, infile) != NULL) {
	    pflag = cflag;		/* Previous flag = current flag	*/
	    cflag = (line[0] == '%' && line[1] == '%');
	    if (pflag && cflag)		/* If have two flags in a row,	*/
		continue;		/*  don't write the second set	*/
	    if (outfile != NULL)
		fputs(line, outfile);	/* Else write out the line	*/
	    if (cflag)			/* If we have a flag, count it	*/
		nxtcoo++;
	}
	if (!cflag) {
	    if (outfile != NULL)
		fputs("%%\n", outfile);	/* Emit terminating flag if we	*/
	    nxtcoo++;			/* ended file without one	*/
	}
}
