view ueda/libuschem/wrschem.c @ 139:bf188727e606

donl-rename-parts reader: no tEDAx-style escapes
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 07 Sep 2020 04:25:11 +0000
parents cd92449fdb51
children
line wrap: on
line source

/*
 * Schematic write-out
 */

#include <sys/types.h>
#include <stdio.h>
#include "schemstruct.h"
#include "writerint.h"

extern FILE *reopen_schem_for_graphblocks();

extern struct drawing_size_kwtab drawing_size_keywords[];

struct schem_write_state schem_write_state;

write_schem(schem, outf)
	struct schem *schem;
	FILE *outf;
{
	register struct schemobj *obj;

	schem_write_state.schem = schem;
	schem_write_state.outf = outf;
	schem_write_state.orig_file = reopen_schem_for_graphblocks(schem);
	wrschem_emit_schemline(schem);
	putc('\n', outf);

	for (obj = schem->obj_next; obj != (struct schemobj *)schem;
	     obj = obj->obj_next)
		wrschem_emit_object(obj);

	if (schem_write_state.orig_file)
		fclose(schem_write_state.orig_file);
}

wrschem_emit_schemline(schem)
	register struct schem *schem;
{
	register struct drawing_size_kwtab *kwp;

	if (!schem->is_graph) {
		fprintf(schem_write_state.outf, "Schem nograph;\n");
		return;
	}
	for (kwp = drawing_size_keywords; kwp->keyword; kwp++)
		if (schem->graph_xsize == kwp->xdim &&
		    schem->graph_ysize == kwp->ydim) {
			fprintf(schem_write_state.outf, "Schem graph %s;\n",
				kwp->keyword);
			return;
		}
	fprintf(schem_write_state.outf, "Schem graph %dx%d;\n",
		schem->graph_xsize, schem->graph_ysize);
}

wrschem_emit_qstring(str)
	char *str;
{
	register char *cp;
	register int c;

	putc('\"', schem_write_state.outf);
	for (cp = str; c = *cp; cp++) {
		if (c == '\"' || c == '\\')
			putc('\\', schem_write_state.outf);
		putc(c, schem_write_state.outf);
	}
	putc('\"', schem_write_state.outf);
}

wrschem_emit_string(str)
	register char *str;
{
	if (schem_string_needs_quote(str))
		wrschem_emit_qstring(str);
	else
		fputs(str, schem_write_state.outf);
}

schem_string_needs_quote(str)
	char *str;
{
	register char *cp;
	register int c;

	cp = str;
	if (!*cp)
		return(1);	/* null strings can only be quoted */
	while (c = *cp++)
		switch (c) {
		case ' ':
		case '\t':
		case '\n':
		case '"':
		case '%':
		case '(':
		case ')':
		case ',':
		case ';':
		case '=':
		case '{':
		case '}':
			return(1);
		}
	return(0);
}

wrschem_emit_object(obj)
	register struct schemobj *obj;
{
	switch (obj->obj_type) {
	case OBJTYPE_COMPINST:
		fputs("Component ", schem_write_state.outf);
		wrschem_emit_string(obj->compobj_instname);
		if (obj->compobj_isgraph) {
			fputs(" graph ", schem_write_state.outf);
			wrschem_emit_qstring(obj->compobj_graph_symname);
			fprintf(schem_write_state.outf, " %d %d",
				obj->compobj_x, obj->compobj_y);
			if (obj->compobj_rotate)
				fprintf(schem_write_state.outf, " rot %d",
					obj->compobj_rotate);
			if (obj->compobj_mirror)
				fputs(" mirror", schem_write_state.outf);
		}
		if (obj->obj_decorations)
			wrschem_emit_decor_block(obj);
		fputs(";\n", schem_write_state.outf);
		return;

	case OBJTYPE_GRAPHSYM:
		fputs("GraphSym ", schem_write_state.outf);
		wrschem_emit_qstring(obj->compobj_graph_symname);
		fprintf(schem_write_state.outf, " %d %d",
			obj->compobj_x, obj->compobj_y);
		if (obj->compobj_rotate)
			fprintf(schem_write_state.outf, " rot %d",
				obj->compobj_rotate);
		if (obj->compobj_mirror)
			fputs(" mirror", schem_write_state.outf);
		if (obj->obj_decorations)
			wrschem_emit_decor_block(obj);
		fputs(";\n", schem_write_state.outf);
		return;

	case OBJTYPE_NET:
		wrschem_emit_net(obj, "Net", 0);
		return;

	case OBJTYPE_GRAPHNET:
		wrschem_emit_net(obj, "GraphNet", 1);
		return;

	case OBJTYPE_NETLINE:
		fprintf(schem_write_state.outf, "NetLine (%d,%d) (%d,%d)",
			obj->lineobj_x1, obj->lineobj_y1,
			obj->lineobj_x2, obj->lineobj_y2);
		if (obj->obj_decorations)
			wrschem_emit_decor_block(obj);
		fputs(";\n", schem_write_state.outf);
		return;

	case OBJTYPE_BUSSEG:
		fprintf(schem_write_state.outf, "BusSeg (%d,%d) (%d,%d)",
			obj->lineobj_x1, obj->lineobj_y1,
			obj->lineobj_x2, obj->lineobj_y2);
		if (obj->obj_decorations)
			wrschem_emit_decor_block(obj);
		fputs(";\n", schem_write_state.outf);
		return;

	case OBJTYPE_GRAPHBLOCK:
		wrschem_emit_graphblock(obj->graphblockobj_body);
		return;

	case OBJTYPE_COMMENT:
		fputs("Comment ", schem_write_state.outf);
		wrschem_emit_qstring(obj->commentobj_text);
		fputs(";\n", schem_write_state.outf);
		return;

	default:
		fprintf(stderr,
	"Fatal internal error: unknown obj type in wrschem_emit_object()\n");
		abort();
	}
}

/* for Net and GraphNet */
wrschem_emit_net(obj, keyword, isgraphnet)
	register struct schemobj *obj;
	char *keyword;
	int isgraphnet;
{
	register struct netpoint *netpt;

	fprintf(schem_write_state.outf, "%s ", keyword);
	if (obj->netobj_grouphead && obj->netobj_grouphead->netobj_netname)
		wrschem_emit_string(obj->netobj_grouphead->netobj_netname);
	else if (obj->netobj_netname)
		wrschem_emit_string(obj->netobj_netname);
	else
		fputs("\"\"", schem_write_state.outf);

	for (netpt = obj->netobj_points; netpt; netpt = netpt->netpt_next) {
		putc(' ', schem_write_state.outf);
		switch (netpt->netpt_type) {
		case NETPT_TYPE_POINT:
			fprintf(schem_write_state.outf, "(%d,%d)",
				netpt->netpt_x, netpt->netpt_y);
			break;
		case NETPT_TYPE_PIN:
			if (isgraphnet) {
				fputs("Pin", schem_write_state.outf);
				if (netpt->netpt_coord_valid)
					fprintf(schem_write_state.outf,
						"(%d,%d)",
						netpt->netpt_x, netpt->netpt_y);
				if (netpt->netpt_pin_nameref)
					putc('=', schem_write_state.outf);
			}
			if (netpt->netpt_pin_nameref)
				wrschem_emit_string(netpt->netpt_pin_nameref);
			break;
		case NETPT_TYPE_TJOIN:
			fprintf(schem_write_state.outf, "Tjoin(%d,%d)",
				netpt->netpt_x, netpt->netpt_y);
			break;
		case NETPT_TYPE_PSEUDO:
			fprintf(schem_write_state.outf, "Pseudo(%d,%d)",
				netpt->netpt_x, netpt->netpt_y);
			break;
		}
	}

	if (obj->obj_decorations)
		wrschem_emit_decor_block(obj);
	fputs(";\n", schem_write_state.outf);
}

wrschem_emit_graphblock(blk)
	struct graphblock *blk;
{
	char *keyword;

	switch (blk->type) {
	case GRAPHBLOCK_TYPE_PS:
		keyword = "GraphBlockPS";
		break;
	case GRAPHBLOCK_TYPE_GSCHEM:
		keyword = "GraphBlockG";
		break;
	default:
		fprintf(stderr,
	  "Fatal internal error: unknown type in wrschem_emit_graphblock()\n");
		abort();
	}
	fprintf(schem_write_state.outf, "%s {\n", keyword);
	write_graphblock_to_file(blk, schem_write_state.orig_file,
					schem_write_state.outf);
	fputs("}\n", schem_write_state.outf);
}

wrschem_emit_decor_block(obj)
	struct schemobj *obj;
{
	register struct decoration *decor;

	fputs(" {\n", schem_write_state.outf);
	for (decor = obj->obj_decorations; decor; decor = decor->decor_next)
		wrschem_emit_decor(decor);
	putc('}', schem_write_state.outf);
}

wrschem_emit_decor(decor)
	register struct decoration *decor;
{
	switch (decor->decor_type) {
	case DECOR_TYPE_ATTR:
		fputs("\t(", schem_write_state.outf);
		wrschem_emit_string(decor->decorattr_name);
		putc('=', schem_write_state.outf);
		wrschem_emit_qstring(decor->decorattr_value);
		fputs(")\n", schem_write_state.outf);
		return;

	case DECOR_TYPE_DISPLAYATTR:
		fputs("\tDisplayAttr ", schem_write_state.outf);
		wrschem_emit_string(decor->decordisp_attr);
		fprintf(schem_write_state.outf, " %d %d %d %d %d;\n",
			decor->decordisp_x, decor->decordisp_y,
			decor->decordisp_ptsize, decor->decordisp_rotate,
			decor->decordisp_alignment);
		return;

	case DECOR_TYPE_DISPLAYNETNAME:
		fprintf(schem_write_state.outf,
			"\tDisplayNetName %d %d %d %d %d;\n",
			decor->decordisp_x, decor->decordisp_y,
			decor->decordisp_ptsize, decor->decordisp_rotate,
			decor->decordisp_alignment);
		return;

	case DECOR_TYPE_PINTONET:
		fputs("\tPinToNet ", schem_write_state.outf);
		wrschem_emit_string(decor->decorpincon_pin);
		putc(' ', schem_write_state.outf);
		wrschem_emit_string(decor->decorpincon_netname);
		fputs(";\n", schem_write_state.outf);
		return;

	case DECOR_TYPE_NOCONNECT:
		fputs("\tNoConnect ", schem_write_state.outf);
		wrschem_emit_string(decor->decorpincon_pin);
		fputs(";\n", schem_write_state.outf);
		return;

	case DECOR_TYPE_SYMONPIN:
		fputs("\tSymOnPin ", schem_write_state.outf);
		wrschem_emit_string(decor->decorpinsym_pin);
		putc(' ', schem_write_state.outf);
		wrschem_emit_qstring(decor->decorpinsym_symname);
		if (decor->decorpinsym_mirror)
			fputs(" mirror", schem_write_state.outf);
		fputs(";\n", schem_write_state.outf);
		return;

	case DECOR_TYPE_GRAPHBLOCK:
		putc('\t', schem_write_state.outf);
		wrschem_emit_graphblock(decor->decorgraph_body);
		return;

	case DECOR_TYPE_COMMENT:
		fputs("\tComment ", schem_write_state.outf);
		wrschem_emit_qstring(decor->decorcomment_text);
		fputs(";\n", schem_write_state.outf);
		return;

	default:
		fprintf(stderr,
    "Fatal internal error: unknown decoration type in wrschem_emit_decor()\n");
		abort();
	}
}