Index: trunk/scconfig/Rev.h =================================================================== --- trunk/scconfig/Rev.h (revision 10570) +++ trunk/scconfig/Rev.h (revision 10571) @@ -1 +1 @@ -static const int myrev = 10444; +static const int myrev = 10571; Index: trunk/scconfig/Rev.tab =================================================================== --- trunk/scconfig/Rev.tab (revision 10570) +++ trunk/scconfig/Rev.tab (revision 10571) @@ -1,4 +1,4 @@ -10444 configure new IO plugins: io_eeschema and io_easyeda +10571 configure new IO plugins: io_eeschema and io_easyeda 10230 configure new plugin for hierarchic library from file system 10028 configure hierarchy support 9983 configure io_orcad: enable by default Index: trunk/src/plugins/io_easyeda/read_low.c =================================================================== --- trunk/src/plugins/io_easyeda/read_low.c (revision 10570) +++ trunk/src/plugins/io_easyeda/read_low.c (nonexistent) @@ -1,972 +0,0 @@ -/* - easyeda file format parser - low level, sch-specific - Copyright (C) 2023,2024 Tibor 'Igor2' Palinkas - - (Supported by NLnet NGI0 Entrust Fund in 2024) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. -*/ - -/* These functions parse the easyeda-specific packged string fields into - DoM subtrees so the high level parser won't need to deal with string - parsing. */ - -#include "read_low.h" - -#include -#include - -#include - -#include -#include -#include - -#define SEP3 "#@$" - -#include "io_easyeda_conf.h" -extern conf_io_easyeda_t io_easyeda_conf; - -/*** helpers ***/ -static void fixup_poly_coords(gdom_node_t *parent) -{ - gdom_node_t *coords, *old_coords; - static const str_tab_t ctab[] = { - {easy_crd, GDOM_DOUBLE}, - {-1} - }; - - /* parse coords */ - old_coords = gdom_hash_get(parent, easy_coords); - if (old_coords != NULL) { - coords = gdom_alloc(easy_coords, GDOM_ARRAY); - parse_str_by_tab(old_coords->value.str, coords, ctab, ' '); - replace_node(old_coords, coords); - } -} - -/*** shapes ***/ - -static int parse_shape_any(gdom_node_t **shape); - -/* Process wires: - W~80 -65 80 -245 150 -245 150 -350~#008800~1~0~none~gge232~0 - W~x1 -y1 x2 -y2 x3 -y3 x4 -y4 ~stroke ~stroke-width ~stroke-style? ~fill ~ID ~locked? -*/ -static int parse_shape_wire(char *str, gdom_node_t **shape) -{ - gdom_node_t *wire; - static const str_tab_t fields[] = { - {easy_coords, GDOM_STRING}, - {easy_stroke_color, GDOM_STRING}, - {easy_stroke_width, GDOM_DOUBLE}, - {easy_stroke_style, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {-1} - }; - - wire = gdom_alloc(easy_wire, GDOM_HASH); - parse_str_by_tab(str, wire, fields, '~'); - - fixup_poly_coords(wire); - - replace_node(*shape, wire); - - return 0; -} - -/* Process polylines: - PL~1059.63 -50.75 1059.63 -30.75~#880000~1~0~none~gge139~0 - PG~1335 106 1345 100 1335 94~#880000~1~0~#880000~gge56049~0 - W~x1 -y1 x2 -y2 x3 -y3 x4 -y4 ~stroke ~stroke-width ~stroke-style? ~fill ~ID ~locked? -*/ -static int parse_shape_polyline_(char *str, gdom_node_t **shape, easy_keys_t name) -{ - gdom_node_t *polyline; - static const str_tab_t fields[] = { - {easy_coords, GDOM_STRING}, - {easy_stroke_color, GDOM_STRING}, - {easy_stroke_width, GDOM_DOUBLE}, - {easy_stroke_style, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - polyline = gdom_alloc(name, GDOM_HASH); - parse_str_by_tab(str, polyline, fields, '~'); - - fixup_poly_coords(polyline); - - replace_node(*shape, polyline); - - return 0; -} - -static int parse_shape_polyline(char *str, gdom_node_t **shape) -{ - return parse_shape_polyline_(str, shape, easy_polyline); -} - - -static int parse_shape_polygon(char *str, gdom_node_t **shape) -{ - return parse_shape_polyline_(str, shape, easy_polygon); -} - -static int parse_shape_bus(char *str, gdom_node_t **shape) -{ - return parse_shape_polyline_(str, shape, easy_bus); -} - -/* bus entry: BE~0~660~150~670~140~gge15 */ -static int parse_shape_busentry(char *str, gdom_node_t **shape) -{ - gdom_node_t *busentry; - static const str_tab_t fields[] = { - {easy_rot, GDOM_LONG}, - {easy_x1, GDOM_DOUBLE}, - {easy_y1, GDOM_DOUBLE}, - {easy_x2, GDOM_DOUBLE}, - {easy_y2, GDOM_DOUBLE}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - busentry = gdom_alloc(easy_busentry, GDOM_HASH); - parse_str_by_tab(str, busentry, fields, '~'); - - replace_node(*shape, busentry); - - return 0; -} - - -/* Process paths: PT~M 206 -796 L 206 -806...~#880000~1~0~none~gge10~0~frame_tick */ -static int parse_shape_path(char *str, gdom_node_t **shape) -{ - gdom_node_t *path; - static const str_tab_t fields[] = { - {easy_path, GDOM_STRING}, - {easy_stroke_color, GDOM_STRING}, - {easy_stroke_width, GDOM_DOUBLE}, - {easy_stroke_style, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - path = gdom_alloc(easy_path, GDOM_HASH); - parse_str_by_tab(str, path, fields, '~'); - - replace_node(*shape, path); - - return 0; -} - -/* Process arc: A~M380.41,-245.31 A170,75 0 1 1 484.18,-373.48~~#000000~1~0~none~gge236~0 */ -static int parse_shape_arc(char *str, gdom_node_t **shape) -{ - gdom_node_t *arc; - static const str_tab_t fields[] = { - {easy_path, GDOM_STRING}, - {easy_helper_dots, GDOM_STRING}, - {easy_stroke_color, GDOM_STRING}, - {easy_stroke_width, GDOM_DOUBLE}, - {easy_stroke_style, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - - arc = gdom_alloc(easy_arc, GDOM_HASH); - parse_str_by_tab(str, arc, fields, '~'); - - replace_node(*shape, arc); - - return 0; -} - -/* Process pie: PI~M 970 40 L 1189.9 34.4509 A 220 180 0 0 1 923.103 215.863 Z~970,40,1190,220,1327.7106323242188,30.973068237304688,923.1032104492188,215.86282348632812~#FF0000~3~0~#CCCCCC~gge22 */ -static int parse_shape_pie(char *str, gdom_node_t **shape) -{ - gdom_node_t *pie; - static const str_tab_t fields[] = { - {easy_path, GDOM_STRING}, - {easy_helper_dots, GDOM_STRING}, - {easy_stroke_color, GDOM_STRING}, - {easy_stroke_width, GDOM_DOUBLE}, - {easy_stroke_style, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - pie = gdom_alloc(easy_pie, GDOM_HASH); - parse_str_by_tab(str, pie, fields, '~'); - - replace_node(*shape, pie); - - return 0; -} - -/* Process arrowhead: AR~part_arrowhead~1060~120~gge23~180~M 1060 120 L 1063 126 L 1055 120 L 1063 114 Z~#FF0000 */ -static int parse_shape_arrowhead(char *str, gdom_node_t **shape) -{ - gdom_node_t *arrowhead; - static const str_tab_t fields[] = { - {easy_part_type, GDOM_STRING}, - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_id, GDOM_STRING}, - {easy_rot, GDOM_LONG}, - {easy_path, GDOM_STRING}, - {easy_fill_color, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - arrowhead = gdom_alloc(easy_arrowhead, GDOM_HASH); - parse_str_by_tab(str, arrowhead, fields, '~'); - - replace_node(*shape, arrowhead); - - return 0; -} - - - -/* Process rectangles: R~694.99995~-90~~~444~80~#880000~1~0~none~gge127~0~frame_hitarea */ -static int parse_shape_rect(char *str, gdom_node_t **shape) -{ - gdom_node_t *rect; - static const str_tab_t fields[] = { - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_rx, GDOM_DOUBLE}, - {easy_ry, GDOM_DOUBLE}, - {easy_width, GDOM_DOUBLE}, - {easy_height, GDOM_DOUBLE}, - {easy_coords, GDOM_STRING}, - {easy_stroke_color, GDOM_STRING}, - {easy_stroke_width, GDOM_DOUBLE}, - {easy_stroke_style, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - rect = gdom_alloc(easy_rect, GDOM_HASH); - parse_str_by_tab(str, rect, fields, '~'); - - replace_node(*shape, rect); - - return 0; -} - - -/* Process line: L~360~160~510~160~#FF0000~2~0~none~gge11 */ -static int parse_shape_line(char *str, gdom_node_t **shape) -{ - gdom_node_t *line; - static const str_tab_t fields[] = { - {easy_x1, GDOM_DOUBLE}, - {easy_y1, GDOM_DOUBLE}, - {easy_x2, GDOM_DOUBLE}, - {easy_y2, GDOM_DOUBLE}, - {easy_stroke_color, GDOM_STRING}, - {easy_stroke_width, GDOM_DOUBLE}, - {easy_stroke_style, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - line = gdom_alloc(easy_line, GDOM_HASH); - parse_str_by_tab(str, line, fields, '~'); - - replace_node(*shape, line); - - return 0; -} - -/* Process circle: C~710~170~105~#FF0000~2~0~#0000FF~gge12 */ -static int parse_shape_circle(char *str, gdom_node_t **shape) -{ - gdom_node_t *circle; - static const str_tab_t fields[] = { - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_r, GDOM_DOUBLE}, - {easy_stroke_color, GDOM_STRING}, - {easy_stroke_width, GDOM_DOUBLE}, - {easy_stroke_style, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - circle = gdom_alloc(easy_circle, GDOM_HASH); - parse_str_by_tab(str, circle, fields, '~'); - - replace_node(*shape, circle); - - return 0; -} - - -/* Process ellipse: E~420~-367.5~140~47.5~#000000~1~0~none~gge242~0 */ -static int parse_shape_ellipse(char *str, gdom_node_t **shape) -{ - gdom_node_t *ellipse; - static const str_tab_t fields[] = { - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_rx, GDOM_DOUBLE}, - {easy_ry, GDOM_DOUBLE}, - {easy_stroke_color, GDOM_STRING}, - {easy_stroke_width, GDOM_DOUBLE}, - {easy_stroke_style, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - ellipse = gdom_alloc(easy_ellipse, GDOM_HASH); - parse_str_by_tab(str, ellipse, fields, '~'); - - replace_node(*shape, ellipse); - - return 0; -} - -/* Process text objects: T~L~892~-1.5~0~#880000~~~~~~comment~5~1~start~gge115~0~frame_tick */ -static int parse_shape_text(char *str, gdom_node_t **shape) -{ - gdom_node_t *text; - static const str_tab_t fields[] = { - {easy_mark, GDOM_STRING}, - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_rot, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_font_family, GDOM_STRING}, - {easy_font_size, GDOM_STRING}, - {easy_font_weight, GDOM_STRING}, - {easy_font_style, GDOM_STRING}, - {easy_dominant_baseline, GDOM_STRING}, - {easy_text_type, GDOM_STRING}, - {easy_text, GDOM_STRING}, - {easy_visible, GDOM_LONG}, - {easy_text_anchor, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - text = gdom_alloc(easy_text, GDOM_HASH); - parse_str_by_tab(str, text, fields, '~'); - - replace_node(*shape, text); - - return 0; -} - -static void not_locked(gdom_node_t *subtree) -{ - gdom_node_t *locked = gdom_alloc(easy_locked, GDOM_LONG); - locked->value.lng = 0; - - assert(subtree->type == GDOM_HASH); - - gdom_append(subtree, locked); -} - -/* Process Pimage objects: Pimage~L~1~gge217~0~gge229~696~-40.5~102~20~data:image/svg+xml;base64,PD94b...g== */ -static int parse_shape_pimage(char *str, gdom_node_t **shape) -{ - gdom_node_t *pimage; - static const str_tab_t fields[] = { - {easy_mark, GDOM_STRING}, - {easy_visible, GDOM_LONG}, - {easy_id, GDOM_STRING}, - {easy_visible2, GDOM_LONG}, - {easy_id2, GDOM_STRING}, - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_width, GDOM_DOUBLE}, - {easy_height, GDOM_DOUBLE}, - {easy_data, GDOM_STRING}, - {-1} - }; - - pimage = gdom_alloc(easy_pimage, GDOM_HASH); - parse_str_by_tab(str, pimage, fields, '~'); - - not_locked(pimage); - - replace_node(*shape, pimage); - - return 0; -} - -/* Process image objects: "I~1350~-25~794~1123~0~data:image/svg+xml;base64,PD9...Pgo=~gge117920~0~" */ -static int parse_shape_image(char *str, gdom_node_t **shape) -{ - gdom_node_t *image; - static const str_tab_t fields[] = { - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_width, GDOM_DOUBLE}, - {easy_height, GDOM_DOUBLE}, - {easy_rot, GDOM_DOUBLE}, - {easy_data, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - image = gdom_alloc(easy_image, GDOM_HASH); - parse_str_by_tab(str, image, fields, '~'); - - replace_node(*shape, image); - - return 0; -} - -/* Process noconn: O~210~-245~gge325~M 206 -249 L 214 -241 M 214 -249 L 206 -241~#33cc33~0 */ -static int parse_shape_noconn(char *str, gdom_node_t **shape) -{ - gdom_node_t *noconn; - static const str_tab_t fields[] = { - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_id, GDOM_STRING}, - {easy_path, GDOM_STRING}, - {easy_stroke_color, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - noconn = gdom_alloc(easy_noconn, GDOM_HASH); - parse_str_by_tab(str, noconn, fields, '~'); - - replace_node(*shape, noconn); - - return 0; -} - -/* Process junction: J~150~-245~2.5~#CC0000~gge304~0 */ -static int parse_shape_junction(char *str, gdom_node_t **shape) -{ - gdom_node_t *junction; - static const str_tab_t fields[] = { - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_r, GDOM_DOUBLE}, - {easy_fill_color, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - junction = gdom_alloc(easy_junction, GDOM_HASH); - parse_str_by_tab(str, junction, fields, '~'); - - replace_node(*shape, junction); - - return 0; -} - - -/* Process netlabel: N~123~456~0~#FF0000~VCC~gge13~start~131~466~Times New Roman~ */ -static int parse_shape_netlabel(char *str, gdom_node_t **shape) -{ - gdom_node_t *netlabel; - static const str_tab_t fields[] = { - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_rot, GDOM_LONG}, - {easy_fill_color, GDOM_STRING}, - {easy_text, GDOM_STRING}, - {easy_id, GDOM_STRING}, - {easy_text_anchor, GDOM_STRING}, - {easy_text_x, GDOM_DOUBLE}, - {easy_text_y, GDOM_DOUBLE}, - {easy_font_family, GDOM_STRING}, - {easy_font_size, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - netlabel = gdom_alloc(easy_netlabel, GDOM_HASH); - parse_str_by_tab(str, netlabel, fields, '~'); - - replace_node(*shape, netlabel); - - return 0; -} - -/*** net flags ***/ - -/* generic/config fields: "part_netLabel_VCC~150~-350~0~gge236~~0" */ -static int parse_shape_netflag_0_cfg(char *str, gdom_node_t *nf) -{ - static const str_tab_t fields[] = { - {easy_part_id, GDOM_STRING}, - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_rot, GDOM_LONG}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - return parse_str_by_tab(str, nf, fields, '~'); -} - -/* dot fields: "150~-350" */ -static int parse_shape_netflag_1_dot(char *str, gdom_node_t *nf) -{ - static const str_tab_t fields[] = { - {easy_dot_x, GDOM_DOUBLE}, - {easy_dot_y, GDOM_DOUBLE}, - {-1} - }; - - return parse_str_by_tab(str, nf, fields, '~'); -} - - -/* mark string fields: "VCC~#000000~138~-362~0~start~1~Times New Roman~9pt~flag_gge13" */ -static int parse_shape_netflag_2_mark(char *str, gdom_node_t *nf) -{ - gdom_node_t *label; - static const str_tab_t fields[] = { - {easy_text, GDOM_STRING}, - {easy_color, GDOM_STRING}, - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_rot, GDOM_LONG}, - {easy_text_anchor, GDOM_STRING}, - {easy_visible, GDOM_LONG}, - {easy_font_family, GDOM_STRING}, - {easy_font_size, GDOM_STRING}, - {-1} - }; - - label = gdom_alloc(easy_label, GDOM_HASH); - gdom_hash_put(nf, label); - - not_locked(label); - - return parse_str_by_tab(str, label, fields, '~'); -} - -static int parse_shape_netflag_shape(char *str, gdom_node_t *shapes) -{ - gdom_node_t *tmp = gdom_alloc(easy_shape, GDOM_STRING); - tmp->value.str = rnd_strdup(str); - if (gdom_array_append(shapes, tmp) != 0) - return -1; - - return parse_shape_any(&tmp); -} - -/* Process pins: G~ cfg ^^ dot ^^ mark ^^ shapes */ -static int parse_shape_netflag(char *str, gdom_node_t **nf_orig) -{ - gdom_node_t *nf, *shp = NULL; - char *s, *next; - int n, res = 0; - - nf = gdom_alloc(easy_netflag, GDOM_HASH); - for(n = 0, s = str; s != NULL; n++, s = next) { - next = strstr(s, "^^"); - if (next != NULL) { - *next = '\0'; - next += 2; - } - switch(n) { - case 0: res |= parse_shape_netflag_0_cfg(s, nf); break; - case 1: res |= parse_shape_netflag_1_dot(s, nf); break; - case 2: res |= parse_shape_netflag_2_mark(s, nf); break; - default: - if (shp == NULL) { - shp = gdom_alloc(easy_shapes, GDOM_ARRAY); - gdom_hash_put(nf, shp); - } - res |= parse_shape_netflag_shape(s, shp); - break; - } - } - - replace_node(*nf_orig, nf); - - return res; -} - - - -/*** pin ***/ - -/* generic/config fields: "show~0~1~670~30~~gge23" */ -static int parse_shape_pin_0_cfg(char *str, gdom_node_t *pin) -{ - static const str_tab_t fields[] = { - {easy_show, GDOM_STRING}, /* shoow or empty */ - {easy_electric, GDOM_STRING}, /* 0, "Undefined", "Input", "Output", "I/O" or "Power" */ - {easy_spice_pinno, GDOM_LONG}, - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_rot, GDOM_LONG}, - {easy_id, GDOM_STRING}, - {easy_locked, GDOM_LONG}, - {-1} - }; - - return parse_str_by_tab(str, pin, fields, '~'); -} - -/* dot at the end of the pin: "670~30" */ -static int parse_shape_pin_1_dot(char *str, gdom_node_t *pin) -{ - static const str_tab_t fields[] = { - {easy_dot_x, GDOM_DOUBLE}, - {easy_dot_y, GDOM_DOUBLE}, - {-1} - }; - - return parse_str_by_tab(str, pin, fields, '~'); -} - -/* M 670 30 h -20~#880000 */ -static int parse_shape_pin_2_path(char *str, gdom_node_t *pin) -{ - static const str_tab_t fields[] = { - {easy_pin_path, GDOM_STRING}, - {easy_pin_path_color, GDOM_STRING}, - {-1} - }; - - return parse_str_by_tab(str, pin, fields, '~'); -} - -/* 1~648~33~0~1~end~~11pt */ -static int parse_shape_pin_34(char *str, gdom_node_t *pin, long type) -{ - gdom_node_t *subtree; - static const str_tab_t fields[] = { - {easy_visible, GDOM_LONG}, - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_rot, GDOM_LONG}, - {easy_text, GDOM_STRING}, - {easy_text_anchor, GDOM_STRING}, - {easy_font_family, GDOM_STRING}, - {easy_font_size, GDOM_STRING}, - {-1} - }; - - subtree = gdom_alloc(type, GDOM_HASH); - gdom_hash_put(pin, subtree); - not_locked(subtree); - return parse_str_by_tab(str, subtree, fields, '~'); -} - -/* 1~648~33~0~1~end~~11pt */ -static int parse_shape_pin_3_name(char *str, gdom_node_t *pin) -{ - return parse_shape_pin_34(str, pin, easy_name); -} - -/* 1~655~29~0~1~start~~11pt */ -static int parse_shape_pin_4_num(char *str, gdom_node_t *pin) -{ - return parse_shape_pin_34(str, pin, easy_num); -} - -/* 0~653~30 */ -static int parse_shape_pin_5_not(char *str, gdom_node_t *pin) -{ - static const str_tab_t fields[] = { - {easy_not_visible, GDOM_LONG}, - {easy_not_x, GDOM_DOUBLE}, - {easy_not_y, GDOM_DOUBLE}, - {-1} - }; - - return parse_str_by_tab(str, pin, fields, '~'); -} - -/* 0~M 650 27 L 647 30 L 650 33 */ -static int parse_shape_pin_6_clk(char *str, gdom_node_t *pin) -{ - static const str_tab_t fields[] = { - {easy_clk_visible, GDOM_LONG}, - {easy_clk_path, GDOM_STRING}, - {easy_not_y, GDOM_LONG}, - {-1} - }; - - return parse_str_by_tab(str, pin, fields, '~'); -} - - -/* Process pins: P~ cfg ^^ dot ^^ path ^^ name ^^ num ^^ not ^^ clk */ -static int parse_shape_pin(char *str, gdom_node_t **pin_orig) -{ - gdom_node_t *pin; - char *s, *next; - int n, res = 0; - - pin = gdom_alloc(easy_pin, GDOM_HASH); - for(n = 0, s = str; s != NULL; n++, s = next) { - next = strstr(s, "^^"); - if (next != NULL) { - *next = '\0'; - next += 2; - } - switch(n) { - case 0: res |= parse_shape_pin_0_cfg(s, pin); break; - case 1: res |= parse_shape_pin_1_dot(s, pin); break; - case 2: res |= parse_shape_pin_2_path(s, pin); break; - case 3: res |= parse_shape_pin_3_name(s, pin); break; - case 4: res |= parse_shape_pin_4_num(s, pin); break; - case 5: res |= parse_shape_pin_5_not(s, pin); break; - case 6: res |= parse_shape_pin_6_clk(s, pin); break; - } - } - - replace_node(*pin_orig, pin); - - return res; -} - -/*** symbol (LIB) ***/ - -/* mark string fields: "0~-806~package`NONE`Manufacturer Part`?`spicePre`.`~~0~frame_lib_1~~~0~72e832730d5a64f9~yes~yes~~~" */ -static int parse_shape_lib_0_cfg(char *str, gdom_node_t *sym) -{ - static const str_tab_t fields[] = { - {easy_x, GDOM_DOUBLE}, - {easy_y, GDOM_DOUBLE}, - {easy_attributes, GDOM_STRING}, - {easy_rot, GDOM_LONG}, - {easy_import, GDOM_LONG}, - {easy_id, GDOM_STRING}, - {easy_id2, GDOM_STRING}, /* the spec doesn't have id2 and id3 ... */ - {easy_id3, GDOM_STRING}, /* ... but editorVersion==6.5.37 writes these */ - {easy_locked, GDOM_LONG}, - {-1} - }; - - return parse_str_by_tab(str, sym, fields, '~'); -} - -static int parse_shape_lib_shape(char *str, gdom_node_t *shapes) -{ - gdom_node_t *tmp = gdom_alloc(easy_shape, GDOM_STRING); - tmp->value.str = rnd_strdup(str); - if (gdom_array_append(shapes, tmp) != 0) - return -1; - - return parse_shape_any(&tmp); -} - -/* Process LIBs: LIB~ cfg SEP3 shape SEP3 shape ... SEP3 shape */ -static int parse_shape_lib(char *str, gdom_node_t **lib) -{ - gdom_node_t *sym = NULL, *shapes = NULL; - char *s, *next; - int n, res = 0; - - for(n = 0, s = str; s != NULL; n++, s = next) { - next = strstr(s, SEP3); - if (next != NULL) { - *next = '\0'; - next += 3; - } - if (n == 0) { - sym = gdom_alloc(easy_symbol, GDOM_HASH); - shapes = gdom_alloc(easy_shapes, GDOM_ARRAY); - if (gdom_hash_put(sym, shapes) != 0) - res = -1; - parse_shape_lib_0_cfg(s, sym); - } - else - res |= parse_shape_lib_shape(s, shapes); - } - - if (sym == NULL) - return res; - - replace_node(*lib, sym); - - return res; -} - -/* CA~1000~1000~#FFFFFF~yes~#CCCCCC~5~1000~1000~line~5~pixel~5~0~0 */ -static int parse_canvas(gdom_node_t **canvas_orig) -{ - gdom_node_t *canvas; - static const str_tab_t fields[] = { - {easy_viewbox_width, GDOM_DOUBLE}, - {easy_viewbox_height, GDOM_DOUBLE}, - {easy_bg_color, GDOM_STRING}, - {easy_visible, GDOM_STRING}, - {easy_grid_color, GDOM_STRING}, - {easy_grid_size, GDOM_DOUBLE}, - {easy_canvas_width, GDOM_DOUBLE}, - {easy_canvas_height, GDOM_DOUBLE}, - {easy_grid_style, GDOM_STRING}, - {easy_snap_size, GDOM_DOUBLE}, - {easy_grid_unit, GDOM_STRING}, - {easy_snap_size_alt, GDOM_DOUBLE}, - {easy_origin_x, GDOM_DOUBLE}, - {easy_origin_y, GDOM_DOUBLE}, - {-1} - }; - - canvas = gdom_alloc(easy_canvas, GDOM_HASH); - parse_str_by_tab((*canvas_orig)->value.str+3, canvas, fields, '~'); - - replace_node(*canvas_orig, canvas); - - return 0; -} - - -/*** entry ***/ - -/* Dispatch shape by content, replace shape node with parsed one in the tree */ -static int parse_shape_any(gdom_node_t **shape) -{ - char *str; - - if ((*shape)->type != GDOM_STRING) - return -1; - - str = (*shape)->value.str; - if (str[0] == '\0') - return -1; - - if (str[1] == '~') { - if (str[0] == 'W') return parse_shape_wire(str+2, shape); - if (str[0] == 'R') return parse_shape_rect(str+2, shape); - if (str[0] == 'P') return parse_shape_pin(str+2, shape); - if (str[0] == 'T') return parse_shape_text(str+2, shape); - if (str[0] == 'E') return parse_shape_ellipse(str+2, shape); - if (str[0] == 'A') return parse_shape_arc(str+2, shape); - if (str[0] == 'N') return parse_shape_netlabel(str+2, shape); - if (str[0] == 'F') return parse_shape_netflag(str+2, shape); - if (str[0] == 'O') return parse_shape_noconn(str+2, shape); - if (str[0] == 'J') return parse_shape_junction(str+2, shape); - if (str[0] == 'I') return parse_shape_image(str+2, shape); - if (str[0] == 'B') return parse_shape_bus(str+2, shape); - if (str[0] == 'L') return parse_shape_line(str+2, shape); - if (str[0] == 'C') return parse_shape_circle(str+2, shape); - } - else { - if (strncmp(str, "PL~", 3) == 0) return parse_shape_polyline(str+3, shape); - if (strncmp(str, "PG~", 3) == 0) return parse_shape_polygon(str+3, shape); - if (strncmp(str, "PT~", 3) == 0) return parse_shape_path(str+3, shape); - if (strncmp(str, "PI~", 3) == 0) return parse_shape_pie(str+3, shape); - if (strncmp(str, "BE~", 3) == 0) return parse_shape_busentry(str+3, shape); - if (strncmp(str, "AR~", 3) == 0) return parse_shape_arrowhead(str+3, shape); - if (strncmp(str, "LIB~", 4) == 0) return parse_shape_lib(str+4, shape); - if (strncmp(str, "Pimage~", 7) == 0) return parse_shape_pimage(str+7, shape); - } - - return -1; -} - -/* Replace string encoded nodes with dom subtrees */ -static void parse_sch_strs(gdom_node_t *sch) -{ - gdom_node_t *shape, *canvas, *data_str; - long n; - - data_str = gdom_hash_get(sch, easy_dataStr); - if (data_str == NULL) - return; - - shape = gdom_hash_get(data_str, easy_shape); - if ((shape != NULL) && (shape->type == GDOM_ARRAY)) - for(n = 0; n < shape->value.array.used; n++) - parse_shape_any(&shape->value.array.child[n]); - - canvas = gdom_hash_get(data_str, easy_canvas); - if ((canvas != NULL) && (canvas->type == GDOM_STRING)) - parse_canvas(&canvas); -} - -static long easyeda_str2name(const char *str) -{ - return easy_sphash(str); -} - -gdom_node_t *easyeda_low_sch_parse(FILE *f) -{ - gdom_node_t *root, *schs; - - /* low level json parse -> initial dom */ - root = gdom_json_parse(f, easyeda_str2name); - if (root == NULL) - return NULL; - - /* parse strings into dom subtrees */ - schs = gdom_hash_get(root, easy_schematics); - if ((schs != NULL) && (schs->type == GDOM_ARRAY)) { - long n; - for(n = 0; n < schs->value.array.used; n++) - parse_sch_strs(schs->value.array.child[n]); - } - - return root; -} - - - -static const char *name2str(long name) -{ - return easy_keyname(name); -} - -void easyeda_dump_tree(FILE *f, gdom_node_t *tree) -{ - gdom_dump(f, tree, 0, name2str); -} - -gdom_node_t *easyeda_low_parse(FILE *f) -{ - gdom_node_t *tree = easyeda_low_sch_parse(f); - - if (io_easyeda_conf.plugins.io_easyeda.debug.dump_dom) - easyeda_dump_tree(stdout, tree); - - return tree; -} Index: trunk/src/plugins/io_easyeda/read_low.h =================================================================== --- trunk/src/plugins/io_easyeda/read_low.h (revision 10570) +++ trunk/src/plugins/io_easyeda/read_low.h (nonexistent) @@ -1,10 +0,0 @@ -#include -#include "easyeda_sphash.h" -#include - -/* Parse an open file into a gdom tree; call gdom_free() to discard it - after use */ -gdom_node_t *easyeda_low_parse(FILE *f); - - - Index: trunk/src/plugins/io_easyeda/Plug.tmpasm =================================================================== --- trunk/src/plugins/io_easyeda/Plug.tmpasm (revision 10570) +++ trunk/src/plugins/io_easyeda/Plug.tmpasm (revision 10571) @@ -2,7 +2,7 @@ put /local/rnd/mod/OBJS [@ $(PLUGDIR)/io_easyeda/io_easyeda.o $(PLUGDIR)/io_easyeda/read.o - $(PLUGDIR)/io_easyeda/read_low.o + $(PLUGDIR)/io_easyeda/read_low_std.o $(PLUGDIR)/io_easyeda/easyeda_sphash.o $(PLUGDIR)/io_easyeda/svgpath.o @] Index: trunk/src/plugins/io_easyeda/read.c =================================================================== --- trunk/src/plugins/io_easyeda/read.c (revision 10570) +++ trunk/src/plugins/io_easyeda/read.c (revision 10571) @@ -60,7 +60,7 @@ #include "io_easyeda_conf.h" extern conf_io_easyeda_t io_easyeda_conf; -#include "read_low.h" +#include "read_low_std.h" #include "read.h" Index: trunk/src/plugins/io_easyeda/read_low_std.c =================================================================== --- trunk/src/plugins/io_easyeda/read_low_std.c (nonexistent) +++ trunk/src/plugins/io_easyeda/read_low_std.c (revision 10571) @@ -0,0 +1,972 @@ +/* + easyeda file format parser - low level, sch-specific + Copyright (C) 2023,2024 Tibor 'Igor2' Palinkas + + (Supported by NLnet NGI0 Entrust Fund in 2024) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* These functions parse the easyeda-specific packged string fields into + DoM subtrees so the high level parser won't need to deal with string + parsing. */ + +#include "read_low_std.h" + +#include +#include + +#include + +#include +#include +#include + +#define SEP3 "#@$" + +#include "io_easyeda_conf.h" +extern conf_io_easyeda_t io_easyeda_conf; + +/*** helpers ***/ +static void fixup_poly_coords(gdom_node_t *parent) +{ + gdom_node_t *coords, *old_coords; + static const str_tab_t ctab[] = { + {easy_crd, GDOM_DOUBLE}, + {-1} + }; + + /* parse coords */ + old_coords = gdom_hash_get(parent, easy_coords); + if (old_coords != NULL) { + coords = gdom_alloc(easy_coords, GDOM_ARRAY); + parse_str_by_tab(old_coords->value.str, coords, ctab, ' '); + replace_node(old_coords, coords); + } +} + +/*** shapes ***/ + +static int parse_shape_any(gdom_node_t **shape); + +/* Process wires: + W~80 -65 80 -245 150 -245 150 -350~#008800~1~0~none~gge232~0 + W~x1 -y1 x2 -y2 x3 -y3 x4 -y4 ~stroke ~stroke-width ~stroke-style? ~fill ~ID ~locked? +*/ +static int parse_shape_wire(char *str, gdom_node_t **shape) +{ + gdom_node_t *wire; + static const str_tab_t fields[] = { + {easy_coords, GDOM_STRING}, + {easy_stroke_color, GDOM_STRING}, + {easy_stroke_width, GDOM_DOUBLE}, + {easy_stroke_style, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {-1} + }; + + wire = gdom_alloc(easy_wire, GDOM_HASH); + parse_str_by_tab(str, wire, fields, '~'); + + fixup_poly_coords(wire); + + replace_node(*shape, wire); + + return 0; +} + +/* Process polylines: + PL~1059.63 -50.75 1059.63 -30.75~#880000~1~0~none~gge139~0 + PG~1335 106 1345 100 1335 94~#880000~1~0~#880000~gge56049~0 + W~x1 -y1 x2 -y2 x3 -y3 x4 -y4 ~stroke ~stroke-width ~stroke-style? ~fill ~ID ~locked? +*/ +static int parse_shape_polyline_(char *str, gdom_node_t **shape, easy_keys_t name) +{ + gdom_node_t *polyline; + static const str_tab_t fields[] = { + {easy_coords, GDOM_STRING}, + {easy_stroke_color, GDOM_STRING}, + {easy_stroke_width, GDOM_DOUBLE}, + {easy_stroke_style, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + polyline = gdom_alloc(name, GDOM_HASH); + parse_str_by_tab(str, polyline, fields, '~'); + + fixup_poly_coords(polyline); + + replace_node(*shape, polyline); + + return 0; +} + +static int parse_shape_polyline(char *str, gdom_node_t **shape) +{ + return parse_shape_polyline_(str, shape, easy_polyline); +} + + +static int parse_shape_polygon(char *str, gdom_node_t **shape) +{ + return parse_shape_polyline_(str, shape, easy_polygon); +} + +static int parse_shape_bus(char *str, gdom_node_t **shape) +{ + return parse_shape_polyline_(str, shape, easy_bus); +} + +/* bus entry: BE~0~660~150~670~140~gge15 */ +static int parse_shape_busentry(char *str, gdom_node_t **shape) +{ + gdom_node_t *busentry; + static const str_tab_t fields[] = { + {easy_rot, GDOM_LONG}, + {easy_x1, GDOM_DOUBLE}, + {easy_y1, GDOM_DOUBLE}, + {easy_x2, GDOM_DOUBLE}, + {easy_y2, GDOM_DOUBLE}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + busentry = gdom_alloc(easy_busentry, GDOM_HASH); + parse_str_by_tab(str, busentry, fields, '~'); + + replace_node(*shape, busentry); + + return 0; +} + + +/* Process paths: PT~M 206 -796 L 206 -806...~#880000~1~0~none~gge10~0~frame_tick */ +static int parse_shape_path(char *str, gdom_node_t **shape) +{ + gdom_node_t *path; + static const str_tab_t fields[] = { + {easy_path, GDOM_STRING}, + {easy_stroke_color, GDOM_STRING}, + {easy_stroke_width, GDOM_DOUBLE}, + {easy_stroke_style, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + path = gdom_alloc(easy_path, GDOM_HASH); + parse_str_by_tab(str, path, fields, '~'); + + replace_node(*shape, path); + + return 0; +} + +/* Process arc: A~M380.41,-245.31 A170,75 0 1 1 484.18,-373.48~~#000000~1~0~none~gge236~0 */ +static int parse_shape_arc(char *str, gdom_node_t **shape) +{ + gdom_node_t *arc; + static const str_tab_t fields[] = { + {easy_path, GDOM_STRING}, + {easy_helper_dots, GDOM_STRING}, + {easy_stroke_color, GDOM_STRING}, + {easy_stroke_width, GDOM_DOUBLE}, + {easy_stroke_style, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + + arc = gdom_alloc(easy_arc, GDOM_HASH); + parse_str_by_tab(str, arc, fields, '~'); + + replace_node(*shape, arc); + + return 0; +} + +/* Process pie: PI~M 970 40 L 1189.9 34.4509 A 220 180 0 0 1 923.103 215.863 Z~970,40,1190,220,1327.7106323242188,30.973068237304688,923.1032104492188,215.86282348632812~#FF0000~3~0~#CCCCCC~gge22 */ +static int parse_shape_pie(char *str, gdom_node_t **shape) +{ + gdom_node_t *pie; + static const str_tab_t fields[] = { + {easy_path, GDOM_STRING}, + {easy_helper_dots, GDOM_STRING}, + {easy_stroke_color, GDOM_STRING}, + {easy_stroke_width, GDOM_DOUBLE}, + {easy_stroke_style, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + pie = gdom_alloc(easy_pie, GDOM_HASH); + parse_str_by_tab(str, pie, fields, '~'); + + replace_node(*shape, pie); + + return 0; +} + +/* Process arrowhead: AR~part_arrowhead~1060~120~gge23~180~M 1060 120 L 1063 126 L 1055 120 L 1063 114 Z~#FF0000 */ +static int parse_shape_arrowhead(char *str, gdom_node_t **shape) +{ + gdom_node_t *arrowhead; + static const str_tab_t fields[] = { + {easy_part_type, GDOM_STRING}, + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_id, GDOM_STRING}, + {easy_rot, GDOM_LONG}, + {easy_path, GDOM_STRING}, + {easy_fill_color, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + arrowhead = gdom_alloc(easy_arrowhead, GDOM_HASH); + parse_str_by_tab(str, arrowhead, fields, '~'); + + replace_node(*shape, arrowhead); + + return 0; +} + + + +/* Process rectangles: R~694.99995~-90~~~444~80~#880000~1~0~none~gge127~0~frame_hitarea */ +static int parse_shape_rect(char *str, gdom_node_t **shape) +{ + gdom_node_t *rect; + static const str_tab_t fields[] = { + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_rx, GDOM_DOUBLE}, + {easy_ry, GDOM_DOUBLE}, + {easy_width, GDOM_DOUBLE}, + {easy_height, GDOM_DOUBLE}, + {easy_coords, GDOM_STRING}, + {easy_stroke_color, GDOM_STRING}, + {easy_stroke_width, GDOM_DOUBLE}, + {easy_stroke_style, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + rect = gdom_alloc(easy_rect, GDOM_HASH); + parse_str_by_tab(str, rect, fields, '~'); + + replace_node(*shape, rect); + + return 0; +} + + +/* Process line: L~360~160~510~160~#FF0000~2~0~none~gge11 */ +static int parse_shape_line(char *str, gdom_node_t **shape) +{ + gdom_node_t *line; + static const str_tab_t fields[] = { + {easy_x1, GDOM_DOUBLE}, + {easy_y1, GDOM_DOUBLE}, + {easy_x2, GDOM_DOUBLE}, + {easy_y2, GDOM_DOUBLE}, + {easy_stroke_color, GDOM_STRING}, + {easy_stroke_width, GDOM_DOUBLE}, + {easy_stroke_style, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + line = gdom_alloc(easy_line, GDOM_HASH); + parse_str_by_tab(str, line, fields, '~'); + + replace_node(*shape, line); + + return 0; +} + +/* Process circle: C~710~170~105~#FF0000~2~0~#0000FF~gge12 */ +static int parse_shape_circle(char *str, gdom_node_t **shape) +{ + gdom_node_t *circle; + static const str_tab_t fields[] = { + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_r, GDOM_DOUBLE}, + {easy_stroke_color, GDOM_STRING}, + {easy_stroke_width, GDOM_DOUBLE}, + {easy_stroke_style, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + circle = gdom_alloc(easy_circle, GDOM_HASH); + parse_str_by_tab(str, circle, fields, '~'); + + replace_node(*shape, circle); + + return 0; +} + + +/* Process ellipse: E~420~-367.5~140~47.5~#000000~1~0~none~gge242~0 */ +static int parse_shape_ellipse(char *str, gdom_node_t **shape) +{ + gdom_node_t *ellipse; + static const str_tab_t fields[] = { + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_rx, GDOM_DOUBLE}, + {easy_ry, GDOM_DOUBLE}, + {easy_stroke_color, GDOM_STRING}, + {easy_stroke_width, GDOM_DOUBLE}, + {easy_stroke_style, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + ellipse = gdom_alloc(easy_ellipse, GDOM_HASH); + parse_str_by_tab(str, ellipse, fields, '~'); + + replace_node(*shape, ellipse); + + return 0; +} + +/* Process text objects: T~L~892~-1.5~0~#880000~~~~~~comment~5~1~start~gge115~0~frame_tick */ +static int parse_shape_text(char *str, gdom_node_t **shape) +{ + gdom_node_t *text; + static const str_tab_t fields[] = { + {easy_mark, GDOM_STRING}, + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_rot, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_font_family, GDOM_STRING}, + {easy_font_size, GDOM_STRING}, + {easy_font_weight, GDOM_STRING}, + {easy_font_style, GDOM_STRING}, + {easy_dominant_baseline, GDOM_STRING}, + {easy_text_type, GDOM_STRING}, + {easy_text, GDOM_STRING}, + {easy_visible, GDOM_LONG}, + {easy_text_anchor, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + text = gdom_alloc(easy_text, GDOM_HASH); + parse_str_by_tab(str, text, fields, '~'); + + replace_node(*shape, text); + + return 0; +} + +static void not_locked(gdom_node_t *subtree) +{ + gdom_node_t *locked = gdom_alloc(easy_locked, GDOM_LONG); + locked->value.lng = 0; + + assert(subtree->type == GDOM_HASH); + + gdom_append(subtree, locked); +} + +/* Process Pimage objects: Pimage~L~1~gge217~0~gge229~696~-40.5~102~20~data:image/svg+xml;base64,PD94b...g== */ +static int parse_shape_pimage(char *str, gdom_node_t **shape) +{ + gdom_node_t *pimage; + static const str_tab_t fields[] = { + {easy_mark, GDOM_STRING}, + {easy_visible, GDOM_LONG}, + {easy_id, GDOM_STRING}, + {easy_visible2, GDOM_LONG}, + {easy_id2, GDOM_STRING}, + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_width, GDOM_DOUBLE}, + {easy_height, GDOM_DOUBLE}, + {easy_data, GDOM_STRING}, + {-1} + }; + + pimage = gdom_alloc(easy_pimage, GDOM_HASH); + parse_str_by_tab(str, pimage, fields, '~'); + + not_locked(pimage); + + replace_node(*shape, pimage); + + return 0; +} + +/* Process image objects: "I~1350~-25~794~1123~0~data:image/svg+xml;base64,PD9...Pgo=~gge117920~0~" */ +static int parse_shape_image(char *str, gdom_node_t **shape) +{ + gdom_node_t *image; + static const str_tab_t fields[] = { + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_width, GDOM_DOUBLE}, + {easy_height, GDOM_DOUBLE}, + {easy_rot, GDOM_DOUBLE}, + {easy_data, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + image = gdom_alloc(easy_image, GDOM_HASH); + parse_str_by_tab(str, image, fields, '~'); + + replace_node(*shape, image); + + return 0; +} + +/* Process noconn: O~210~-245~gge325~M 206 -249 L 214 -241 M 214 -249 L 206 -241~#33cc33~0 */ +static int parse_shape_noconn(char *str, gdom_node_t **shape) +{ + gdom_node_t *noconn; + static const str_tab_t fields[] = { + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_id, GDOM_STRING}, + {easy_path, GDOM_STRING}, + {easy_stroke_color, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + noconn = gdom_alloc(easy_noconn, GDOM_HASH); + parse_str_by_tab(str, noconn, fields, '~'); + + replace_node(*shape, noconn); + + return 0; +} + +/* Process junction: J~150~-245~2.5~#CC0000~gge304~0 */ +static int parse_shape_junction(char *str, gdom_node_t **shape) +{ + gdom_node_t *junction; + static const str_tab_t fields[] = { + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_r, GDOM_DOUBLE}, + {easy_fill_color, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + junction = gdom_alloc(easy_junction, GDOM_HASH); + parse_str_by_tab(str, junction, fields, '~'); + + replace_node(*shape, junction); + + return 0; +} + + +/* Process netlabel: N~123~456~0~#FF0000~VCC~gge13~start~131~466~Times New Roman~ */ +static int parse_shape_netlabel(char *str, gdom_node_t **shape) +{ + gdom_node_t *netlabel; + static const str_tab_t fields[] = { + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_rot, GDOM_LONG}, + {easy_fill_color, GDOM_STRING}, + {easy_text, GDOM_STRING}, + {easy_id, GDOM_STRING}, + {easy_text_anchor, GDOM_STRING}, + {easy_text_x, GDOM_DOUBLE}, + {easy_text_y, GDOM_DOUBLE}, + {easy_font_family, GDOM_STRING}, + {easy_font_size, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + netlabel = gdom_alloc(easy_netlabel, GDOM_HASH); + parse_str_by_tab(str, netlabel, fields, '~'); + + replace_node(*shape, netlabel); + + return 0; +} + +/*** net flags ***/ + +/* generic/config fields: "part_netLabel_VCC~150~-350~0~gge236~~0" */ +static int parse_shape_netflag_0_cfg(char *str, gdom_node_t *nf) +{ + static const str_tab_t fields[] = { + {easy_part_id, GDOM_STRING}, + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_rot, GDOM_LONG}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + return parse_str_by_tab(str, nf, fields, '~'); +} + +/* dot fields: "150~-350" */ +static int parse_shape_netflag_1_dot(char *str, gdom_node_t *nf) +{ + static const str_tab_t fields[] = { + {easy_dot_x, GDOM_DOUBLE}, + {easy_dot_y, GDOM_DOUBLE}, + {-1} + }; + + return parse_str_by_tab(str, nf, fields, '~'); +} + + +/* mark string fields: "VCC~#000000~138~-362~0~start~1~Times New Roman~9pt~flag_gge13" */ +static int parse_shape_netflag_2_mark(char *str, gdom_node_t *nf) +{ + gdom_node_t *label; + static const str_tab_t fields[] = { + {easy_text, GDOM_STRING}, + {easy_color, GDOM_STRING}, + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_rot, GDOM_LONG}, + {easy_text_anchor, GDOM_STRING}, + {easy_visible, GDOM_LONG}, + {easy_font_family, GDOM_STRING}, + {easy_font_size, GDOM_STRING}, + {-1} + }; + + label = gdom_alloc(easy_label, GDOM_HASH); + gdom_hash_put(nf, label); + + not_locked(label); + + return parse_str_by_tab(str, label, fields, '~'); +} + +static int parse_shape_netflag_shape(char *str, gdom_node_t *shapes) +{ + gdom_node_t *tmp = gdom_alloc(easy_shape, GDOM_STRING); + tmp->value.str = rnd_strdup(str); + if (gdom_array_append(shapes, tmp) != 0) + return -1; + + return parse_shape_any(&tmp); +} + +/* Process pins: G~ cfg ^^ dot ^^ mark ^^ shapes */ +static int parse_shape_netflag(char *str, gdom_node_t **nf_orig) +{ + gdom_node_t *nf, *shp = NULL; + char *s, *next; + int n, res = 0; + + nf = gdom_alloc(easy_netflag, GDOM_HASH); + for(n = 0, s = str; s != NULL; n++, s = next) { + next = strstr(s, "^^"); + if (next != NULL) { + *next = '\0'; + next += 2; + } + switch(n) { + case 0: res |= parse_shape_netflag_0_cfg(s, nf); break; + case 1: res |= parse_shape_netflag_1_dot(s, nf); break; + case 2: res |= parse_shape_netflag_2_mark(s, nf); break; + default: + if (shp == NULL) { + shp = gdom_alloc(easy_shapes, GDOM_ARRAY); + gdom_hash_put(nf, shp); + } + res |= parse_shape_netflag_shape(s, shp); + break; + } + } + + replace_node(*nf_orig, nf); + + return res; +} + + + +/*** pin ***/ + +/* generic/config fields: "show~0~1~670~30~~gge23" */ +static int parse_shape_pin_0_cfg(char *str, gdom_node_t *pin) +{ + static const str_tab_t fields[] = { + {easy_show, GDOM_STRING}, /* shoow or empty */ + {easy_electric, GDOM_STRING}, /* 0, "Undefined", "Input", "Output", "I/O" or "Power" */ + {easy_spice_pinno, GDOM_LONG}, + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_rot, GDOM_LONG}, + {easy_id, GDOM_STRING}, + {easy_locked, GDOM_LONG}, + {-1} + }; + + return parse_str_by_tab(str, pin, fields, '~'); +} + +/* dot at the end of the pin: "670~30" */ +static int parse_shape_pin_1_dot(char *str, gdom_node_t *pin) +{ + static const str_tab_t fields[] = { + {easy_dot_x, GDOM_DOUBLE}, + {easy_dot_y, GDOM_DOUBLE}, + {-1} + }; + + return parse_str_by_tab(str, pin, fields, '~'); +} + +/* M 670 30 h -20~#880000 */ +static int parse_shape_pin_2_path(char *str, gdom_node_t *pin) +{ + static const str_tab_t fields[] = { + {easy_pin_path, GDOM_STRING}, + {easy_pin_path_color, GDOM_STRING}, + {-1} + }; + + return parse_str_by_tab(str, pin, fields, '~'); +} + +/* 1~648~33~0~1~end~~11pt */ +static int parse_shape_pin_34(char *str, gdom_node_t *pin, long type) +{ + gdom_node_t *subtree; + static const str_tab_t fields[] = { + {easy_visible, GDOM_LONG}, + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_rot, GDOM_LONG}, + {easy_text, GDOM_STRING}, + {easy_text_anchor, GDOM_STRING}, + {easy_font_family, GDOM_STRING}, + {easy_font_size, GDOM_STRING}, + {-1} + }; + + subtree = gdom_alloc(type, GDOM_HASH); + gdom_hash_put(pin, subtree); + not_locked(subtree); + return parse_str_by_tab(str, subtree, fields, '~'); +} + +/* 1~648~33~0~1~end~~11pt */ +static int parse_shape_pin_3_name(char *str, gdom_node_t *pin) +{ + return parse_shape_pin_34(str, pin, easy_name); +} + +/* 1~655~29~0~1~start~~11pt */ +static int parse_shape_pin_4_num(char *str, gdom_node_t *pin) +{ + return parse_shape_pin_34(str, pin, easy_num); +} + +/* 0~653~30 */ +static int parse_shape_pin_5_not(char *str, gdom_node_t *pin) +{ + static const str_tab_t fields[] = { + {easy_not_visible, GDOM_LONG}, + {easy_not_x, GDOM_DOUBLE}, + {easy_not_y, GDOM_DOUBLE}, + {-1} + }; + + return parse_str_by_tab(str, pin, fields, '~'); +} + +/* 0~M 650 27 L 647 30 L 650 33 */ +static int parse_shape_pin_6_clk(char *str, gdom_node_t *pin) +{ + static const str_tab_t fields[] = { + {easy_clk_visible, GDOM_LONG}, + {easy_clk_path, GDOM_STRING}, + {easy_not_y, GDOM_LONG}, + {-1} + }; + + return parse_str_by_tab(str, pin, fields, '~'); +} + + +/* Process pins: P~ cfg ^^ dot ^^ path ^^ name ^^ num ^^ not ^^ clk */ +static int parse_shape_pin(char *str, gdom_node_t **pin_orig) +{ + gdom_node_t *pin; + char *s, *next; + int n, res = 0; + + pin = gdom_alloc(easy_pin, GDOM_HASH); + for(n = 0, s = str; s != NULL; n++, s = next) { + next = strstr(s, "^^"); + if (next != NULL) { + *next = '\0'; + next += 2; + } + switch(n) { + case 0: res |= parse_shape_pin_0_cfg(s, pin); break; + case 1: res |= parse_shape_pin_1_dot(s, pin); break; + case 2: res |= parse_shape_pin_2_path(s, pin); break; + case 3: res |= parse_shape_pin_3_name(s, pin); break; + case 4: res |= parse_shape_pin_4_num(s, pin); break; + case 5: res |= parse_shape_pin_5_not(s, pin); break; + case 6: res |= parse_shape_pin_6_clk(s, pin); break; + } + } + + replace_node(*pin_orig, pin); + + return res; +} + +/*** symbol (LIB) ***/ + +/* mark string fields: "0~-806~package`NONE`Manufacturer Part`?`spicePre`.`~~0~frame_lib_1~~~0~72e832730d5a64f9~yes~yes~~~" */ +static int parse_shape_lib_0_cfg(char *str, gdom_node_t *sym) +{ + static const str_tab_t fields[] = { + {easy_x, GDOM_DOUBLE}, + {easy_y, GDOM_DOUBLE}, + {easy_attributes, GDOM_STRING}, + {easy_rot, GDOM_LONG}, + {easy_import, GDOM_LONG}, + {easy_id, GDOM_STRING}, + {easy_id2, GDOM_STRING}, /* the spec doesn't have id2 and id3 ... */ + {easy_id3, GDOM_STRING}, /* ... but editorVersion==6.5.37 writes these */ + {easy_locked, GDOM_LONG}, + {-1} + }; + + return parse_str_by_tab(str, sym, fields, '~'); +} + +static int parse_shape_lib_shape(char *str, gdom_node_t *shapes) +{ + gdom_node_t *tmp = gdom_alloc(easy_shape, GDOM_STRING); + tmp->value.str = rnd_strdup(str); + if (gdom_array_append(shapes, tmp) != 0) + return -1; + + return parse_shape_any(&tmp); +} + +/* Process LIBs: LIB~ cfg SEP3 shape SEP3 shape ... SEP3 shape */ +static int parse_shape_lib(char *str, gdom_node_t **lib) +{ + gdom_node_t *sym = NULL, *shapes = NULL; + char *s, *next; + int n, res = 0; + + for(n = 0, s = str; s != NULL; n++, s = next) { + next = strstr(s, SEP3); + if (next != NULL) { + *next = '\0'; + next += 3; + } + if (n == 0) { + sym = gdom_alloc(easy_symbol, GDOM_HASH); + shapes = gdom_alloc(easy_shapes, GDOM_ARRAY); + if (gdom_hash_put(sym, shapes) != 0) + res = -1; + parse_shape_lib_0_cfg(s, sym); + } + else + res |= parse_shape_lib_shape(s, shapes); + } + + if (sym == NULL) + return res; + + replace_node(*lib, sym); + + return res; +} + +/* CA~1000~1000~#FFFFFF~yes~#CCCCCC~5~1000~1000~line~5~pixel~5~0~0 */ +static int parse_canvas(gdom_node_t **canvas_orig) +{ + gdom_node_t *canvas; + static const str_tab_t fields[] = { + {easy_viewbox_width, GDOM_DOUBLE}, + {easy_viewbox_height, GDOM_DOUBLE}, + {easy_bg_color, GDOM_STRING}, + {easy_visible, GDOM_STRING}, + {easy_grid_color, GDOM_STRING}, + {easy_grid_size, GDOM_DOUBLE}, + {easy_canvas_width, GDOM_DOUBLE}, + {easy_canvas_height, GDOM_DOUBLE}, + {easy_grid_style, GDOM_STRING}, + {easy_snap_size, GDOM_DOUBLE}, + {easy_grid_unit, GDOM_STRING}, + {easy_snap_size_alt, GDOM_DOUBLE}, + {easy_origin_x, GDOM_DOUBLE}, + {easy_origin_y, GDOM_DOUBLE}, + {-1} + }; + + canvas = gdom_alloc(easy_canvas, GDOM_HASH); + parse_str_by_tab((*canvas_orig)->value.str+3, canvas, fields, '~'); + + replace_node(*canvas_orig, canvas); + + return 0; +} + + +/*** entry ***/ + +/* Dispatch shape by content, replace shape node with parsed one in the tree */ +static int parse_shape_any(gdom_node_t **shape) +{ + char *str; + + if ((*shape)->type != GDOM_STRING) + return -1; + + str = (*shape)->value.str; + if (str[0] == '\0') + return -1; + + if (str[1] == '~') { + if (str[0] == 'W') return parse_shape_wire(str+2, shape); + if (str[0] == 'R') return parse_shape_rect(str+2, shape); + if (str[0] == 'P') return parse_shape_pin(str+2, shape); + if (str[0] == 'T') return parse_shape_text(str+2, shape); + if (str[0] == 'E') return parse_shape_ellipse(str+2, shape); + if (str[0] == 'A') return parse_shape_arc(str+2, shape); + if (str[0] == 'N') return parse_shape_netlabel(str+2, shape); + if (str[0] == 'F') return parse_shape_netflag(str+2, shape); + if (str[0] == 'O') return parse_shape_noconn(str+2, shape); + if (str[0] == 'J') return parse_shape_junction(str+2, shape); + if (str[0] == 'I') return parse_shape_image(str+2, shape); + if (str[0] == 'B') return parse_shape_bus(str+2, shape); + if (str[0] == 'L') return parse_shape_line(str+2, shape); + if (str[0] == 'C') return parse_shape_circle(str+2, shape); + } + else { + if (strncmp(str, "PL~", 3) == 0) return parse_shape_polyline(str+3, shape); + if (strncmp(str, "PG~", 3) == 0) return parse_shape_polygon(str+3, shape); + if (strncmp(str, "PT~", 3) == 0) return parse_shape_path(str+3, shape); + if (strncmp(str, "PI~", 3) == 0) return parse_shape_pie(str+3, shape); + if (strncmp(str, "BE~", 3) == 0) return parse_shape_busentry(str+3, shape); + if (strncmp(str, "AR~", 3) == 0) return parse_shape_arrowhead(str+3, shape); + if (strncmp(str, "LIB~", 4) == 0) return parse_shape_lib(str+4, shape); + if (strncmp(str, "Pimage~", 7) == 0) return parse_shape_pimage(str+7, shape); + } + + return -1; +} + +/* Replace string encoded nodes with dom subtrees */ +static void parse_sch_strs(gdom_node_t *sch) +{ + gdom_node_t *shape, *canvas, *data_str; + long n; + + data_str = gdom_hash_get(sch, easy_dataStr); + if (data_str == NULL) + return; + + shape = gdom_hash_get(data_str, easy_shape); + if ((shape != NULL) && (shape->type == GDOM_ARRAY)) + for(n = 0; n < shape->value.array.used; n++) + parse_shape_any(&shape->value.array.child[n]); + + canvas = gdom_hash_get(data_str, easy_canvas); + if ((canvas != NULL) && (canvas->type == GDOM_STRING)) + parse_canvas(&canvas); +} + +static long easyeda_str2name(const char *str) +{ + return easy_sphash(str); +} + +gdom_node_t *easyeda_low_sch_parse(FILE *f) +{ + gdom_node_t *root, *schs; + + /* low level json parse -> initial dom */ + root = gdom_json_parse(f, easyeda_str2name); + if (root == NULL) + return NULL; + + /* parse strings into dom subtrees */ + schs = gdom_hash_get(root, easy_schematics); + if ((schs != NULL) && (schs->type == GDOM_ARRAY)) { + long n; + for(n = 0; n < schs->value.array.used; n++) + parse_sch_strs(schs->value.array.child[n]); + } + + return root; +} + + + +static const char *name2str(long name) +{ + return easy_keyname(name); +} + +void easyeda_dump_tree(FILE *f, gdom_node_t *tree) +{ + gdom_dump(f, tree, 0, name2str); +} + +gdom_node_t *easyeda_low_parse(FILE *f) +{ + gdom_node_t *tree = easyeda_low_sch_parse(f); + + if (io_easyeda_conf.plugins.io_easyeda.debug.dump_dom) + easyeda_dump_tree(stdout, tree); + + return tree; +} Index: trunk/src/plugins/io_easyeda/read_low_std.h =================================================================== --- trunk/src/plugins/io_easyeda/read_low_std.h (nonexistent) +++ trunk/src/plugins/io_easyeda/read_low_std.h (revision 10571) @@ -0,0 +1,10 @@ +#include +#include "easyeda_sphash.h" +#include + +/* Parse an open file into a gdom tree; call gdom_free() to discard it + after use */ +gdom_node_t *easyeda_low_parse(FILE *f); + + + Index: trunk/src/sch-rnd/Makefile.dep =================================================================== --- trunk/src/sch-rnd/Makefile.dep (revision 10570) +++ trunk/src/sch-rnd/Makefile.dep (revision 10571) @@ -353,14 +353,18 @@ ../libcschem/concrete.h ../libcschem/operation.h ../libcschem/project.h \ ../libcschem/engine.h ../libcschem/abstract.h ../libcschem/TODO.h \ ../libcschem/util_parse.h ../../src_3rd/load_cache/load_cache.h \ - ../sch-rnd/buffer.h ../plugins/lib_alien/read_helper.h \ - ../plugins/lib_alien/read_postproc.h \ - ../plugins/io_easyeda/io_easyeda_conf.h ../plugins/io_easyeda/read_low.h \ + ../libcschem/util_wirenet.h ../sch-rnd/buffer.h \ + ../../src_3rd/rnd_inclib/lib_svgpath/svgpath.h \ + ../plugins/lib_alien/read_helper.h ../plugins/lib_alien/read_postproc.h \ + ../plugins/io_easyeda/io_easyeda_conf.h \ + ../plugins/io_easyeda/read_low_std.h \ ../plugins/io_easyeda/easyeda_sphash.h \ ../../src_3rd/rnd_inclib/lib_easyeda/gendom.h \ ../plugins/io_easyeda/read.h ../libcschem/plug_io.h -../plugins/io_easyeda/read_low.o: ../plugins/io_easyeda/read_low.c \ - ../plugins/io_easyeda/read_low.h ../plugins/io_easyeda/easyeda_sphash.h \ +../plugins/io_easyeda/read_low_std.o: \ + ../plugins/io_easyeda/read_low_std.c \ + ../plugins/io_easyeda/read_low_std.h \ + ../plugins/io_easyeda/easyeda_sphash.h \ ../../src_3rd/rnd_inclib/lib_easyeda/gendom.h \ ../../src_3rd/libnanojson/nanojson.c \ ../../src_3rd/libnanojson/nanojson.h \ @@ -369,7 +373,11 @@ ../../src_3rd/rnd_inclib/lib_easyeda/gendom_json.c \ ../../src_3rd/rnd_inclib/lib_easyeda/gendom_json.h \ ../../src_3rd/libnanojson/nanojson.h \ - ../../src_3rd/rnd_inclib/lib_easyeda/easyeda_low.c + ../../src_3rd/rnd_inclib/lib_easyeda/easyeda_low.c \ + ../plugins/io_easyeda/io_easyeda_conf.h +../plugins/io_easyeda/svgpath.o: ../plugins/io_easyeda/svgpath.c \ + ../../src_3rd/rnd_inclib/lib_svgpath/svgpath.c \ + ../../src_3rd/rnd_inclib/lib_svgpath/svgpath.h ../plugins/io_eeschema/io_eeschema.o: \ ../plugins/io_eeschema/io_eeschema.c ../libcschem/config.h \ ../libcschem/plug_io.h ../libcschem/concrete.h \