/*
**	CC2GC -- Chord Chart to Guitar Chord conversion
**	psl 12/85
*/
#include	<stdio.h>

#define	MAXCH		256
#define	NAMELEN		16

#define	MINOCT	-1
#define	MAXOCT	9
char	noteval[]	= { 9, 11, 0, 2, 4, 5, 7, };

char	Ebuf[128];
int	Numchords	= 1;		/* "-" already defined */

struct	chstr	{
	char	name[NAMELEN];
	char	chord[64];
} Ch[MAXCH]	= {
	{ "-",	"- - - - - - - -\n", },	/* to allow "-" to be used as a rest */
};

char	*peel(), *copy();

main(argc, argv)
char	*argv[];
{
	register int i;
	FILE *ifp;

	if (argc == 1)
	    process(stdin);
	else {
	    for (i = 1; i < argc; i++) {
		if ((ifp = fopen(argv[i], "r")) == NULL)
		    perror(argv[i]);
		else {
		    process(ifp);
		    fclose(ifp);
		}
	    }
	}
}

process(ifp)
FILE	*ifp;
{
	char *bp, *cp;
	register int chnum, lastchnum, n;
	char buf[512];
	FILE *fp;

	while (fgets(bp = buf, sizeof buf, ifp) != NULL) {
	    cp = peel(&bp);
	    if (*cp == '\n' || *cp == '#') {
		printf("%s %s", cp, bp);
		continue;
	    } else if (wrdcmp(cp, "Include") == 0) {
		if (*bp++ != '"')
		    syntax("Include must use quotes (\")");
		for (cp = bp; *cp && *cp != '"'; cp++);
		if (*cp != '"')
		    syntax("Include must use quotes (\")");
		*cp = '\0';
		if ((fp = fopen(bp, "r")) == NULL) {
		    perror(bp);
		    exit(1);
		}
		process(fp);
		fclose(fp);
	    } else if (wrdcmp(cp, "Style") == 0) {
		if (wrdcmp(bp, "staccato") == 0)
		    printf("#ARTIC\t0.25\n");
		else if (wrdcmp(bp, "normal") == 0)
		    printf("#ARTIC\t0.8\n");
		else if (wrdcmp(bp, "legato") == 0)
		    printf("#ARTIC\t1\n");
		else
		    syntax("Unrecognized \"Style\" arg");
	    } else if (wrdcmp(cp, "Quantum") == 0) {
		if (wrdcmp(bp, "whole") == 0)
		    n = 1;
		else if (wrdcmp(bp, "half") == 0)
		    n = 2;
		else if (wrdcmp(bp, "quarter") == 0)
		    n = 4;
		else if (wrdcmp(bp, "eighth") == 0)
		    n = 8;
		else if (wrdcmp(bp, "sixteenth") == 0)
		    n = 16;
		else {
		    syntax("Unrecognized quantum arg");
		    continue;
		}
		printf("#SPEED\t%d\n", n);
	    } else if (wrdcmp(cp, "Chord") == 0) {
		if ((chnum = Numchords++) >= MAXCH)
		    syntax("Too many chords defined");
		copy(peel(&bp), Ch[chnum].name);
		copy(bp, Ch[chnum].chord);
	    } else {
		lastchnum = -1;
		while (*cp) {
		    if (*cp == '/') {
			if ((chnum = lastchnum) == -1)
			    syntax("Line beginning with '/'");
		    } else {
			if ((chnum = find(cp)) < 0) {
			    sprintf(Ebuf, "Undefined chord: %s", cp);
			    syntax(Ebuf);
			}
		    }
		    printf("%s", Ch[chnum].chord);
		    lastchnum = chnum;
		    cp = peel(&bp);
		}
	    }
	}
}

wrdcmp(ap, bp)
char	*ap, *bp;
{
	while (*bp && *ap == *bp) {
	    ap++;
	    bp++;
	}
	return ((*ap <= ' ' && *bp == '\0')? 0 : *ap - *bp);
}

syntax(msg)
char	*msg;
{
	fprintf(stderr, "Chord chart syntax error: %s\n", msg);
	exit(1);
}

char	*
peel(spp)
char	**spp;
{
	register char *bp, *sp;

	bp = sp = *spp;
	while (*bp > ' ')
	    bp++;
	if (*bp != '\0') {	
	    *bp++ = '\0';
	    while (*bp && *bp <= ' ')
		bp++;
	}
	*spp = bp;
	return(sp);
}

find(name)
char	*name;
{
	register int i;

	for (i = 0; i < Numchords; i++)
	    if (wrdcmp(name, Ch[i].name) == 0)
		return(i);
	return(-1);
}

char	*
copy(f, t)
register char *f, *t;
{
	while (*t++ = *f++);
	return(--t);
}
