/*
 *                   DATA STRUCTURES
 *                   ==== ==========
 *
 *                       FOR THE
 *                       === ===
 *
 *               DATA DECLARATION BUILDER
 *               ==== =========== =======
 *
 *      This module provides the internal structures needed
 *      for the data declaration builder.  It is itself the
 *      sort of output generated by the program (although a
 *	bit optimized!)
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "struct.h"

#define Puts(s)	fputs(s,stdout)
#define NEW(t)	(t) malloc( sizeof(struct t) )
#define COPYOF(new,old) {new=malloc(1+strlen(old));if(new)strcpy(new,old);}


declnlist build_declnlist( char *name, shapelist s, declnlist next )
{
        declnlist new = NEW(declnlist);

        COPYOF(new->name, name);
        new->shapes = s;
        new->next   = next;
        return new;
}


void print_declnlist( declnlist d )
{
        for ( ; d; d = d->next)
	{
                Puts(d->name);
		Puts(" = ");
                print_shapelist(d->shapes);
                putchar('\n');
        }
}


shapelist build_shapelist( char *id, paramlist p, printlist pl, shapelist next )
{
        shapelist new = NEW(shapelist);

        COPYOF(new->name, id);
        new->params = p;
        new->pl     = pl;
        new->next   = next;
        return new;
}


void print_shape( shapelist s )
{
	Puts(s->name);
	if (s->params)
	{
		Puts("( ");
		print_paramlist(s->params);
		Puts(" )");
	}
	putchar(' ');
	print_printlist(s->pl);
}


void print_shapelist( shapelist s )
{
        if (s != NULL)
	{
		print_shape(s);
                for (s = s->next; s; s = s->next)
		{
                        Puts("or ");
			print_shape(s);
                }
        }
}


paramlist build_paramlist( BOOL dontfree, char *type, char *id, paramlist next )
{
        paramlist new = NEW(paramlist);

        COPYOF(new->type, type);
        COPYOF(new->name, id);
	new->dontfree = dontfree;
        new->next  = next;

        return new;
}


void print_paramlist( paramlist p )
{
        if (p != NULL)
	{
		if( p->dontfree ) putchar('-');
                printf("%s %s", p->type, p->name);
                for (p = p->next; p; p = p->next)
		{
			fputs(", ",stdout );
			if( p->dontfree ) putchar('-');
			printf( "%s %s", p->type, p->name);
                }
        }
}


printitem build_printitem_str( char *s )
{
	printitem new = NEW( printitem );

	new->tag = printitem_is_str;
	new->str = s;

	return new;
}


printitem build_printitem_num( int n )
{
	printitem new = NEW(printitem);

	new->tag = printitem_is_num;
	new->num = n;

	return new;
}


void print_printitem( printitem i )
{
	switch(i->tag)
	{
	case printitem_is_num:
		printf("%d ", i->num);
		break;
	case printitem_is_str:
		printf("\"%s\" ", i->str);
		break;
	default:
		fprintf( stderr,
			"datadec: print_printitem called with tag = %d\n",
			i->tag );
		exit(1);
	}
}


printlist build_printlist( printitem h, printlist t )
{
        printlist new = NEW(printlist);

        new->item = h;
        new->next = t;
        return new;
}


void print_printlist( printlist p )
{
	for (; p; p = p->next)
	{
		print_printitem(p->item);
	}
}


param findnthparam( int n, paramlist p, char *sname, char *dname )
{
	int m = n;

	for( ; p != NULL && --m; p = p->next );

	if( p == NULL )
	{
		fprintf( stderr,
			"datadec: bad print number %d in shape %s of type %s\n",
			m, sname, dname );
		exit(1);
	}

	return p;
}
