FreeCalypso > hg > ueda-linux
view ueda/libuschem/rdschem_parse.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
/* * 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)); }