/*
    c99tree - parse tree output layer: print awk script
    Copyright (C) 2015  Tibor Palinkas

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "tree.h"
#include "tree_print.h"
#include "c99tree.h"
#include "pathgrow.h"
#include "escaping.h"

/* C99F_* names */
static char *fnames[] = {
	"TYPE",
	"NAME",
	"LOCSTR",
	"NEXT",
	"PREV",
	"CHILD",
	"PARENT",
	"CHILDREN",
	"TWIN_PARENT",
	"LOCFORMAT",
	"MAX_UID",
	NULL
};


static void gen_begin()
{
	int n;
	char **s;

	printf("BEGIN {\n");

	for(n = 0; n < T_INVALID; n++)
		printf("	C99T_%s = %d\n", node_type_names[n], n);
	printf("\n");

	for(n = 0, s = fnames; *s != NULL; n++,s++)
		printf("	C99F_%s = %d\n", *s, n+1024);
	printf("\n");

	for(n = 0; n < T_INVALID; n++)
		printf("	C99SYM[%d] = \"%s\"\n", n, node_type_names[n]);
	for(n = 0, s = fnames; *s != NULL; n++,s++)
		printf("	C99SYM[%d] = \"%s\"\n", n+1024, *s);


	printf("}\n\n");
}

typedef struct {
	int uid_max;
} awk_ctx_t;

int Nprint_awk(void **nprint_ctx, const char *prefix, const node_t *node, print_state_t state)
{
	node_t *n;
	int nch;
	awk_ctx_t *ctx;

	ctx = (awk_ctx_t *)*nprint_ctx;

	switch(state) {
		case PS_OPENING:
			if (node->uid > ctx->uid_max)
				ctx->uid_max = node->uid;

			if (node->type == T_GRAMMAR_TREE)
				printf("	TREE[C99T_GRAMMAR_TREE] = %d\n", node->uid);
			else if (node->type == T_TOKEN_TREE)
				printf("	TREE[C99T_TOKEN_TREE] = %d\n", node->uid);

			printf("	TREE[%d, C99F_TYPE]   = C99T_%s\n", node->uid, node_type_names[node->type]);
			if (node->name != NULL) {
				char *esc = escape(node->name);
				printf("	TREE[%d, C99F_NAME]   = \"%s\"\n", node->uid, esc);
				free(esc);
			}
			printf("	TREE[%d, C99F_LOCSTR] = \"%s\"\n", node->uid, loc_print(node));

			if (node->next != NULL) {
				printf("	TREE[%d, C99F_NEXT] = %d\n", node->uid, node->next->uid);
				printf("	TREE[%d, C99F_PREV] = %d\n", node->next->uid, node->uid);
			}

			for(n = node->children, nch = 0; n != NULL; n = n->next, nch++) {
				printf("	TREE[%d, C99F_CHILD, %d] = %d\n", node->uid, nch, n->uid);
				printf("	TREE[%d, C99F_PARENT] = %d\n", n->uid, node->uid);
			}
			printf("	TREE[%d, C99F_CHILDREN] = %d\n", node->uid, nch);

			if (node->loc.twin_parent != NULL)
				printf("	TREE[%d, C99F_TWIN_PARENT] = %d\n", node->uid, node->loc.twin_parent->uid);

			printf("	\n");
			break;
		case PS_HEAD:
			*nprint_ctx = calloc(1, sizeof(awk_ctx_t));
			gen_begin();
			printf("function c99tree_%s(TREE) {\n", "unknown");
			printf("	TREE[C99F_LOCFORMAT] = \"%s\"\n\n", loc_format);
			break;
		case PS_TAIL:
			printf("	TREE[C99F_MAX_UID] = %d\n", ctx->uid_max);
			free(*nprint_ctx);
			printf("}\n\n");
			break;
		case PS_CLOSING:
			break;
	}
	return 0;
}
