/*
 *                            COPYRIGHT
 *
 *  sch-rnd - modular/flexible schematics editor - spice target
 *  Copyright (C) 2023 Tibor 'Igor2' Palinkas
 *
 *  (Supported by NLnet NGI0 Entrust in 2023)
 *
 *  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., 31 Milk Street, # 960789 Boston, MA 02196 USA.
 *
 *  Contact:
 *    Project page: http://repo.hu/projects/sch-rnd
 *    contact lead developer: http://www.repo.hu/projects/sch-rnd/contact.html
 *    mailing list: http://www.repo.hu/projects/sch-rnd/contact.html
 */

/*** spice module parser ***/

static void parse_error(void *ectx, lht_node_t *n, const char *msg)
{
	rnd_message(RND_MSG_ERROR, "spicelib: parse error '%s' near %ld:%ld\n", msg, n->line, n->col);
}

static ldch_data_t *spicelib_parse(ldch_high_parser_t *parser, void *call_ctx, ldch_file_t *file)
{
	gds_t *low = (gds_t *)&file->low_payload;
	ldch_data_t *data = NULL;
	spicelib_t *spicelib;

	data = ldch_data_alloc(file, parser, sizeof(spicelib_t));
	spicelib = (spicelib_t *)&data->payload;
	spicelib->text = low;
	return data;
}

static void spicelib_free_payload(ldch_data_t *data)
{
	spicelib_t *spicelib = (spicelib_t *)&data->payload;
	gds_uninit(spicelib->text);
}


/* called when the file is first loaded; should allocate (ldch_file_t *) */
static ldch_file_t *ldspice_parse_alloc(ldch_low_parser_t *parser, void *call_ctx, const char *fn)
{
	return ldch_file_alloc(parser->ctx, parser, sizeof(gds_t));
}

/* called after parse_alloc() on initial load or after free_payload() on reload */
static int ldspice_parse(ldch_low_parser_t *parser, void *call_ctx, ldch_file_t *file, const char *fn)
{
	FILE *f;
	gds_t *payload = (gds_t *)&file->low_payload;

	f = rnd_fopen(NULL, fn, "r");
	if (f == NULL)
		return -1;

	for(;;) {
		char tmp[4096];
		size_t len;

		len = fread(tmp, 1, sizeof(tmp), f);
		if (len <= 0)
			break;

		gds_append_len(payload, tmp, len);
	}

	fclose(f);
	return 0;
}

/* should free the in-memory document/parse-tree; a call to parse() may follow when reloading */
static void ldspice_free_payload(ldch_low_parser_t *low, ldch_file_t *file)
{
	gds_t *payload = (gds_t *)&file->low_payload;
	gds_uninit(payload);
}

static ldch_low_parser_t *spicelib_reg_low_parser(ldch_ctx_t *ctx)
{
	ldch_low_parser_t *p = ldch_reg_low_parser(ctx, "spice");

	p->parse_alloc  = ldspice_parse_alloc;
	p->parse        = ldspice_parse;
	p->free_payload = ldspice_free_payload;

	return p;
}
