/*====================================================================
 *
 * FILE:
 *	pprint.c
 *
 * $Header: /private/postgres/src/test/RCS/pprint.c,v 1.1 1990/11/15 16:27:24 sp Exp $
 *
 * DESCRIPTION:
 *
 * This file reads from its input a plan (genearated by 'PlanToString')
 * and attempts to pretty-print it.
 *
 * NOTE:
 *	Newlines are ignored, so you can use the xterm cut and paste...
 *	The plan contents are not altered in any way. The only thing that
 *	this program does is to insert some spaces and newlines.
 *	Therefore its output can be re-readed by 'StringToPlan'.
 */
#include <stdio.h>
#include <strings.h>

/*
 * Is it a standalone program, or just part of postgres
 * code ??
 */
#define STANDALONE

#ifdef STANDALONE
#define MY_ALLOC(x)	malloc(x)
#define MY_FREE(x)	free(x)
#else
#define MY_ALLOC(x)	palloc(x)
#define MY_FREE(x)	pfree(x)
#endif STANDALONE

char *MY_ALLOC();
void MY_FREE();

char *pprint_plan();
char *addCharToString();


/*==================== ROUTINES ====================================*/
#ifdef STANDALONE
/*-----------------------------------------------------------------
 * main()
 *
 */
main(argc, argv)
int argc;
char *argv[];
{
    FILE *fpin, *fpout;
    char *sin, *sout;
    int c;
    int maxlength;
    int currentlength;

    /*
     * Sorry, no options yet...
     * Read from stdin and print to stdout...
     */
    fpin = stdin;
    fpout = stdout;

    /*
     * read the input to a string
     */
    maxlength = 0;
    currentlength = 0;
    sin = NULL;
    while ((c=getc(fpin)) != EOF) {
	/*
	 * ignore newlines
	 */
	if (c!= '\n')
	    sin = addCharToString(sin, &maxlength, &currentlength, (char)c);
    }

    sout = pprint_plan(sin);

    fprintf(fpout, "%s\n", sout);
}
#endif STANDALONE

/*-----------------------------------------------------------------
 * pprint_plan()
 *
 * This is the routine that does the job.
 * 
 *
 * For every left parenthesis we find we increase indentation.
 * For every right parenthesis we decrease it.
 * We change to a new line every time we find a '#S(' or
 * a word beginning with ':' (a node field).
 */

char *
pprint_plan(s)
char *s;
{
    register int i;
    int indentation;
    int c;
    char *res;
    int maxlength, currentlength ;

    /*
     * initialize output string data
     */
    maxlength = 0;
    currentlength = 0;
    res = NULL;

    indentation = 0;

    while (*s != '\0') {
	if (*s=='#' && *(s+1)=='S' && *(s+2)=='(') {
	    res = addCharToString(res, &maxlength, &currentlength, '\n');
	    for (i=0; i<indentation; i++)
		res = addCharToString(res, &maxlength, &currentlength, ' ');
	    res = addCharToString(res, &maxlength, &currentlength, *s);
	} else if (*s == ':') {
	    res = addCharToString(res, &maxlength, &currentlength, '\n');
	    for (i=0; i<indentation; i++)
		res = addCharToString(res, &maxlength, &currentlength, ' ');
	    res = addCharToString(res, &maxlength, &currentlength, *s);
	} else if (*s == '(') {
	    indentation++;
	    res = addCharToString(res, &maxlength, &currentlength, *s);
	} else if (*s == ')') {
		indentation--;
	    res = addCharToString(res, &maxlength, &currentlength, *s);
	} else {
	    res = addCharToString(res, &maxlength, &currentlength, *s);
	}
	/*
	 * go to the next char
	 */
	s++;
    }

    return(res);
}

/*-----------------------------------------------------------------
 *
 * addCharToString
 *
 * Append a character to a string and return the new string.
 * It always leaves a null terminated string.
 * If the string has not sufficient length,
 * the original string is freed and a larger string is allocated.
 */
char *
addCharToString(s, maxLength, currentLength, c)
char *s;
int *maxLength;
int *currentLength;
char c;
{
    char *res;

    if (s==NULL || (*currentLength+1) >= *maxLength) {
	/*
	 * need to allocate some (new) space
	 */
	*maxLength += 1000;
	res = MY_ALLOC(*maxLength);
	if (s!=NULL) {
	    bcopy(s, res, *currentLength);
	    MY_FREE(s);
	}
    } else {
	res = s;
    }

    res[*currentLength] = c;
    *currentLength += 1;
    res[*currentLength] = '\0';

    return(res);
}

