FreeCalypso > hg > ueda-linux
diff ueda/libuschem/rdschem_parse.c @ 0:cd92449fdb51
initial import of ueda and ifctf-part-lib from ifctfvax CVS
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 20 Jul 2015 00:24:37 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ueda/libuschem/rdschem_parse.c Mon Jul 20 00:24:37 2015 +0000 @@ -0,0 +1,696 @@ +/* + * uschem schematic parser + */ + +#include <sys/types.h> +#include <stdio.h> +#include <strings.h> +#include "schemstruct.h" +#include "parserint.h" + +extern char *copystr(); + +extern struct schem_parse_state schem_parse_state; + +extern struct schemobj *parser_alloc_obj(); +extern struct decoration *parser_alloc_decor(); +extern struct netpoint *parser_alloc_netpoint(); +extern struct xypair parse_drawing_size_spec(); +extern struct graphblock *rdschem_graphblock(); + +rdschem_parse_schemline() +{ + register int t; + struct xypair drawing_size; + + t = rdschem_token(); + if (t != STRING || strcmp(schem_parse_state.string, "Schem")) { + fprintf(stderr, + "%s is not a uschem schematic (doesn't begin with Schem)\n", + schem_parse_state.schem->orig_filename); + exit(1); + } + + t = rdschem_token(); + if (t != STRING) +inv: rdschem_error("Schem line: syntax error"); + if (!strcmp(schem_parse_state.string, "graph")) { + schem_parse_state.schem->is_graph = 1; + t = rdschem_token(); + if (t != STRING && t != QSTRING) + goto inv; + drawing_size = + parse_drawing_size_spec(schem_parse_state.string); + schem_parse_state.schem->graph_xsize = drawing_size.x; + schem_parse_state.schem->graph_ysize = drawing_size.y; + } else if (!strcmp(schem_parse_state.string, "nograph")) + schem_parse_state.schem->is_graph = 0; + else + goto inv; + + t = rdschem_token(); + if (t != ';') + goto inv; +} + +static struct decoration * +parse_decor_attr() +{ + register struct decoration *decor; + register int t; + + decor = parser_alloc_decor(DECOR_TYPE_ATTR); + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(attribute definition decoration) syntax error"); + if (!schem_parse_state.string[0]) + rdschem_error("attribute name may not be a null string"); + decor->decorattr_name = copystr(schem_parse_state.string); + t = rdschem_token(); + if (t != '=') + goto syntaxerr; + t = rdschem_token(); + if (t != STRING && t != QSTRING) + goto syntaxerr; + if (!schem_parse_state.string[0]) + rdschem_error("attribute value may not be a null string"); + decor->decorattr_value = copystr(schem_parse_state.string); + t = rdschem_token(); + if (t != ')') + goto syntaxerr; + return(decor); +} + +static struct decoration * +parse_decor_displayattr() +{ + register struct decoration *decor; + register int t; + + decor = parser_alloc_decor(DECOR_TYPE_DISPLAYATTR); + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(DisplayAttr decoration) syntax error"); + if (!schem_parse_state.string[0]) + rdschem_error("attribute name may not be a null string"); + decor->decordisp_attr = copystr(schem_parse_state.string); + decor->decordisp_x = parse_number(); + decor->decordisp_y = parse_number(); + decor->decordisp_ptsize = parse_number(); + decor->decordisp_rotate = parse_number(); + decor->decordisp_alignment = parse_number(); + t = rdschem_token(); + if (t != ';') + goto syntaxerr; + return(decor); +} + +static struct decoration * +parse_decor_displaynetname() +{ + register struct decoration *decor; + register int t; + + decor = parser_alloc_decor(DECOR_TYPE_DISPLAYNETNAME); + decor->decordisp_x = parse_number(); + decor->decordisp_y = parse_number(); + decor->decordisp_ptsize = parse_number(); + decor->decordisp_rotate = parse_number(); + decor->decordisp_alignment = parse_number(); + t = rdschem_token(); + if (t != ';') + rdschem_error("(DisplayNetName decoration) syntax error"); + return(decor); +} + +static struct decoration * +parse_decor_pintonet() +{ + register struct decoration *decor; + register int t; + + decor = parser_alloc_decor(DECOR_TYPE_PINTONET); + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(PinToNet decoration) syntax error"); + if (!schem_parse_state.string[0]) + rdschem_error("pin ID may not be a null string"); + if (!strcmp(schem_parse_state.string, "#")) + rdschem_error("pin ID \"#\" is invalid"); + decor->decorpincon_pin = copystr(schem_parse_state.string); + t = rdschem_token(); + if (t != STRING && t != QSTRING) + goto syntaxerr; + if (!schem_parse_state.string[0]) + rdschem_error("net name may not be a null string"); + decor->decorpincon_netname = copystr(schem_parse_state.string); + t = rdschem_token(); + if (t != ';') + goto syntaxerr; + return(decor); +} + +static struct decoration * +parse_decor_noconnect() +{ + register struct decoration *decor; + register int t; + + decor = parser_alloc_decor(DECOR_TYPE_NOCONNECT); + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(NoConnect decoration) syntax error"); + if (!schem_parse_state.string[0]) + rdschem_error("pin ID may not be a null string"); + if (!strcmp(schem_parse_state.string, "#")) + rdschem_error("pin ID \"#\" is invalid"); + decor->decorpincon_pin = copystr(schem_parse_state.string); + t = rdschem_token(); + if (t != ';') + goto syntaxerr; + return(decor); +} + +static struct decoration * +parse_decor_symonpin() +{ + register struct decoration *decor; + register int t; + + decor = parser_alloc_decor(DECOR_TYPE_SYMONPIN); + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(SymOnPin decoration) syntax error"); + if (!schem_parse_state.string[0]) + rdschem_error("pin ID may not be a null string"); + if (!strcmp(schem_parse_state.string, "#")) + rdschem_error("pin ID \"#\" is invalid"); + decor->decorpinsym_pin = copystr(schem_parse_state.string); + t = rdschem_token(); + if (t != STRING && t != QSTRING) + goto syntaxerr; + if (!schem_parse_state.string[0]) + rdschem_error("graphical symbol name may not be a null string"); + decor->decorpinsym_symname = copystr(schem_parse_state.string); + t = rdschem_token(); + if (t == STRING && !strcmp(schem_parse_state.string, "mirror")) { + decor->decorpinsym_mirror = 1; + t = rdschem_token(); + } + if (t != ';') + goto syntaxerr; + return(decor); +} + +static struct decoration * +parse_decor_graphblock(type) +{ + register int t; + register struct decoration *decor; + register struct graphblock *blk; + + t = rdschem_token(); + if (t != '{') + rdschem_error("GraphBlockG/GraphBlockPS must be followed by '{'"); + blk = rdschem_graphblock(type); + decor = parser_alloc_decor(DECOR_TYPE_GRAPHBLOCK); + decor->decorgraph_body = blk; + schem_parse_state.schem->has_graphblocks = 1; + return(decor); +} + +static struct decoration * +parse_decor_comment() +{ + register int t; + register struct decoration *decor; + + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(Comment decoration) syntax error"); + if (!schem_parse_state.string[0]) + rdschem_error("schematic comment may not be a null string"); + decor = parser_alloc_decor(DECOR_TYPE_COMMENT); + decor->decorcomment_text = copystr(schem_parse_state.string); + t = rdschem_token(); + if (t != ';') + goto syntaxerr; + return(decor); +} + +struct decoration * +rdschem_parse_decor_block() +{ + struct decoration *decor, *head, **tailp; + register int t; + char errbuf[256]; + + for (head = NULL, tailp = &head; ; ) { + t = rdschem_token(); + switch (t) { + case 0: + rdschem_error("EOF in a decoration block"); + case '(': + decor = parse_decor_attr(); + goto addit; + case ';': + /* "null statement" */ + continue; + case '}': + return(head); + } + if (t != STRING) + rdschem_error("syntax error: decoration keyword expected"); + if (!strcmp(schem_parse_state.string, "DisplayAttr")) + decor = parse_decor_displayattr(); + else if (!strcmp(schem_parse_state.string, "DisplayNetName")) + decor = parse_decor_displaynetname(); + else if (!strcmp(schem_parse_state.string, "PinToNet")) + decor = parse_decor_pintonet(); + else if (!strcmp(schem_parse_state.string, "NoConnect")) + decor = parse_decor_noconnect(); + else if (!strcmp(schem_parse_state.string, "SymOnPin")) + decor = parse_decor_symonpin(); + else if (!strcmp(schem_parse_state.string, "GraphBlockG")) + decor = parse_decor_graphblock(GRAPHBLOCK_TYPE_GSCHEM); + else if (!strcmp(schem_parse_state.string, "GraphBlockPS")) + decor = parse_decor_graphblock(GRAPHBLOCK_TYPE_PS); + else if (!strcmp(schem_parse_state.string, "Comment")) + decor = parse_decor_comment(); + else { + sprintf(errbuf, + "%s is not a recognized decoration keyword", + schem_parse_state.string); + rdschem_error(errbuf); + } +addit: *tailp = decor; + tailp = &decor->decor_next; + } +} + +rdschem_parse_object() +{ + register int t; + char errbuf[256]; + + t = rdschem_token(); + if (!t) /* EOF aka end of schematic */ + return(1); + if (t == ';') /* "null statement" */ + return(0); + if (t != STRING) + rdschem_error("syntax error: object keyword expected"); + + if (!strcmp(schem_parse_state.string, "Component")) + return(rdschem_parse_compinst()); + if (!strcmp(schem_parse_state.string, "GraphSym")) + return(rdschem_parse_graphsym()); + if (!strcmp(schem_parse_state.string, "Net")) + return(rdschem_parse_net()); + if (!strcmp(schem_parse_state.string, "GraphNet")) + return(rdschem_parse_graphnet()); + if (!strcmp(schem_parse_state.string, "NetLine")) + return(rdschem_parse_netline()); + if (!strcmp(schem_parse_state.string, "BusSeg")) + return(rdschem_parse_busseg()); + if (!strcmp(schem_parse_state.string, "GraphBlockG")) + return(rdschem_parse_graphblock_obj(GRAPHBLOCK_TYPE_GSCHEM)); + if (!strcmp(schem_parse_state.string, "GraphBlockPS")) + return(rdschem_parse_graphblock_obj(GRAPHBLOCK_TYPE_PS)); + if (!strcmp(schem_parse_state.string, "Comment")) + return(rdschem_parse_comment_obj()); + + sprintf(errbuf, "%s is not a recognized object keyword", + schem_parse_state.string); + rdschem_error(errbuf); +} + +rdschem_parse_compinst() +{ + register int t; + register struct schemobj *obj; + + obj = parser_alloc_obj(OBJTYPE_COMPINST); + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(Component object) syntax error"); + if (!schem_parse_state.string[0]) + rdschem_error("component instance name may not be a null string"); + obj->compobj_instname = copystr(schem_parse_state.string); + + t = rdschem_token(); + if (t == STRING && !strcmp(schem_parse_state.string, "graph")) { + obj->compobj_isgraph = 1; + t = rdschem_token(); + if (t != STRING && t != QSTRING) + goto syntaxerr; + if (!schem_parse_state.string[0]) + rdschem_error("graphical symbol name may not be a null string"); + obj->compobj_graph_symname = copystr(schem_parse_state.string); + obj->compobj_x = parse_number(); + obj->compobj_y = parse_number(); + t = rdschem_token(); + if (t == STRING && !strcmp(schem_parse_state.string, "rot")) { + obj->compobj_rotate = parse_number(); + t = rdschem_token(); + } + if (t == STRING && !strcmp(schem_parse_state.string, "mirror")){ + obj->compobj_mirror = 1; + t = rdschem_token(); + } + } + + if (t == '{') { + obj->obj_decorations = rdschem_parse_decor_block(); + t = rdschem_token(); + } + + if (t != ';') + goto syntaxerr; + parser_add_object(obj); + return(0); +} + +rdschem_parse_graphsym() +{ + register int t; + register struct schemobj *obj; + + obj = parser_alloc_obj(OBJTYPE_GRAPHSYM); + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(GraphSym object) syntax error"); + if (!schem_parse_state.string[0]) + rdschem_error("graphical symbol name may not be a null string"); + obj->compobj_graph_symname = copystr(schem_parse_state.string); + + obj->compobj_x = parse_number(); + obj->compobj_y = parse_number(); + t = rdschem_token(); + if (t == STRING && !strcmp(schem_parse_state.string, "rot")) { + obj->compobj_rotate = parse_number(); + t = rdschem_token(); + } + if (t == STRING && !strcmp(schem_parse_state.string, "mirror")) { + obj->compobj_mirror = 1; + t = rdschem_token(); + } + if (t == '{') { + obj->obj_decorations = rdschem_parse_decor_block(); + t = rdschem_token(); + } + + if (t != ';') + goto syntaxerr; + parser_add_object(obj); + return(0); +} + +rdschem_parse_net() +{ + register int t; + register struct schemobj *obj; + register struct netpoint *netpt; + struct netpoint *head, **tailp; + + obj = parser_alloc_obj(OBJTYPE_NET); + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(Net object) syntax error"); + if (schem_parse_state.string[0]) + obj->netobj_netname = copystr(schem_parse_state.string); + + head = NULL; + tailp = &head; + for (;;) { + t = rdschem_token(); + if (t == ';' || t == '{') + break; + if (t != STRING && t != QSTRING) + goto syntaxerr; + if (!schem_parse_state.string[0]) + goto syntaxerr; + netpt = parser_alloc_netpoint(NETPT_TYPE_PIN); + netpt->netpt_pin_nameref = copystr(schem_parse_state.string); + *tailp = netpt; + tailp = &netpt->netpt_next; + } + obj->netobj_points = head; + + if (t == '{') { + obj->obj_decorations = rdschem_parse_decor_block(); + t = rdschem_token(); + } + if (t != ';') + goto syntaxerr; + + if (obj->netobj_points) + parser_add_object(obj); + else { + fprintf(stderr, "%s: line %d: null Net object ignored\n", + schem_parse_state.schem->orig_filename, + schem_parse_state.lineno); + free(obj); + } + return(0); +} + +static struct xypair +parse_coord_pair() +{ + register int t; + struct xypair retval; + + retval.x = parse_number(); + t = rdschem_token(); + if (t != ',') +syntaxerr: rdschem_error("syntax error in coordinate pair"); + retval.y = parse_number(); + t = rdschem_token(); + if (t != ')') + goto syntaxerr; + return(retval); +} + +static struct netpoint * +parse_graphnet_point() +{ + register int t; + register struct netpoint *netpt; + struct xypair coord_pair; + + t = rdschem_token(); + if (t == '(') { + netpt = parser_alloc_netpoint(NETPT_TYPE_POINT); + coord_pair = parse_coord_pair(); + netpt->netpt_x = coord_pair.x; + netpt->netpt_y = coord_pair.y; + netpt->netpt_coord_valid = 1; + return(netpt); + } else if (t == STRING && !strcmp(schem_parse_state.string, "Pin")) { + netpt = parser_alloc_netpoint(NETPT_TYPE_PIN); + t = rdschem_token(); + if (t == '(') { + coord_pair = parse_coord_pair(); + netpt->netpt_x = coord_pair.x; + netpt->netpt_y = coord_pair.y; + netpt->netpt_coord_valid = 1; + t = rdschem_token(); + } + if (t == '=') { + t = rdschem_token(); + if (t != STRING && t != QSTRING || + !schem_parse_state.string[0]) + rdschem_error("syntax error: pin name reference expected"); + netpt->netpt_pin_nameref = + copystr(schem_parse_state.string); + } else if (netpt->netpt_coord_valid) + schem_parse_state.pushback_token = t; + else + rdschem_error("syntax error: Pin must be followed by coordinates or name reference"); + return(netpt); + } else if (t == STRING && !strcmp(schem_parse_state.string, "Tjoin")) { + netpt = parser_alloc_netpoint(NETPT_TYPE_TJOIN); + t = rdschem_token(); + if (t != '(') + rdschem_error("syntax error: Tjoin must be followed by coordinates"); + coord_pair = parse_coord_pair(); + netpt->netpt_x = coord_pair.x; + netpt->netpt_y = coord_pair.y; + netpt->netpt_coord_valid = 1; + return(netpt); + } else if (t == STRING && !strcmp(schem_parse_state.string, "Pseudo")) { + netpt = parser_alloc_netpoint(NETPT_TYPE_PSEUDO); + t = rdschem_token(); + if (t != '(') + rdschem_error("syntax error: Pseudo must be followed by coordinates"); + coord_pair = parse_coord_pair(); + netpt->netpt_x = coord_pair.x; + netpt->netpt_y = coord_pair.y; + netpt->netpt_coord_valid = 1; + return(netpt); + } + schem_parse_state.pushback_token = t; + return(NULL); +} + +rdschem_parse_graphnet() +{ + register int t; + register struct schemobj *obj; + register struct netpoint *netpt; + struct netpoint *head, **tailp; + + obj = parser_alloc_obj(OBJTYPE_GRAPHNET); + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(GraphNet object) syntax error"); + if (schem_parse_state.string[0]) + obj->netobj_netname = copystr(schem_parse_state.string); + + head = NULL; + tailp = &head; + for (;;) { + netpt = parse_graphnet_point(); + if (!netpt) + break; + *tailp = netpt; + tailp = &netpt->netpt_next; + } + obj->netobj_points = head; + + t = rdschem_token(); + if (t == '{') { + obj->obj_decorations = rdschem_parse_decor_block(); + t = rdschem_token(); + } + if (t != ';') + goto syntaxerr; + + if (obj->netobj_points) + parser_add_object(obj); + else { + fprintf(stderr, "%s: line %d: null GraphNet object ignored\n", + schem_parse_state.schem->orig_filename, + schem_parse_state.lineno); + free(obj); + } + return(0); +} + +rdschem_parse_netline() +{ + register int t; + register struct schemobj *obj; + struct xypair coord_pair; + + obj = parser_alloc_obj(OBJTYPE_NETLINE); + + t = rdschem_token(); + if (t != '(') +syntaxerr: rdschem_error("(NetLine object) syntax error"); + coord_pair = parse_coord_pair(); + obj->lineobj_x1 = coord_pair.x; + obj->lineobj_y1 = coord_pair.y; + t = rdschem_token(); + if (t != '(') + goto syntaxerr; + coord_pair = parse_coord_pair(); + obj->lineobj_x2 = coord_pair.x; + obj->lineobj_y2 = coord_pair.y; + + t = rdschem_token(); + if (t == '{') { + obj->obj_decorations = rdschem_parse_decor_block(); + t = rdschem_token(); + } + if (t != ';') + goto syntaxerr; + parser_add_object(obj); + return(0); +} + +rdschem_parse_busseg() +{ + register int t; + register struct schemobj *obj; + struct xypair coord_pair; + + obj = parser_alloc_obj(OBJTYPE_BUSSEG); + + t = rdschem_token(); + if (t != '(') +syntaxerr: rdschem_error("(BusSeg object) syntax error"); + coord_pair = parse_coord_pair(); + obj->lineobj_x1 = coord_pair.x; + obj->lineobj_y1 = coord_pair.y; + t = rdschem_token(); + if (t != '(') + goto syntaxerr; + coord_pair = parse_coord_pair(); + obj->lineobj_x2 = coord_pair.x; + obj->lineobj_y2 = coord_pair.y; + + t = rdschem_token(); + if (t == '{') { + obj->obj_decorations = rdschem_parse_decor_block(); + t = rdschem_token(); + } + if (t != ';') + goto syntaxerr; + parser_add_object(obj); + return(0); +} + +rdschem_parse_graphblock_obj(type) +{ + register int t; + register struct schemobj *obj; + register struct graphblock *blk; + + t = rdschem_token(); + if (t != '{') + rdschem_error("GraphBlockG/GraphBlockPS must be followed by '{'"); + blk = rdschem_graphblock(type); + obj = parser_alloc_obj(OBJTYPE_GRAPHBLOCK); + obj->graphblockobj_body = blk; + parser_add_object(obj); + schem_parse_state.schem->has_graphblocks = 1; + return(0); +} + +rdschem_parse_comment_obj() +{ + register int t; + register struct schemobj *obj; + + t = rdschem_token(); + if (t != STRING && t != QSTRING) +syntaxerr: rdschem_error("(Comment object) syntax error"); + if (!schem_parse_state.string[0]) + rdschem_error("schematic comment may not be a null string"); + obj = parser_alloc_obj(OBJTYPE_COMMENT); + obj->commentobj_text = copystr(schem_parse_state.string); + t = rdschem_token(); + if (t != ';') + goto syntaxerr; + parser_add_object(obj); + return(0); +} + +static int +parse_number() +{ + register int t; + char errbuf[256]; + + t = rdschem_token(); + if (t != STRING) + rdschem_error("syntax error (number expected)"); + if (!string_is_valid_decnum(schem_parse_state.string)) { + sprintf(errbuf, "\"%s\" is not a valid decimal number", + schem_parse_state.string); + rdschem_error(errbuf); + } + return(atoi(schem_parse_state.string)); +}