/* * COPYRIGHT * * cschem - modular/flexible schematics editor - libcschem (core library) * Copyright (C) 2019, 2024 Tibor 'Igor2' Palinkas * * (Supported by NLnet NGI0 Entrust in 2023) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 31 Milk Street, # 960789 Boston, MA 02196 USA * * Contact: * Project page: http://repo.hu/projects/sch-rnd * contact lead developer: http://www.repo.hu/projects/sch-rnd/contact.html * mailing list: http://www.repo.hu/projects/sch-rnd/contact.html */ #include "config.h" #include #include #include #include #include #include "hierarchy.h" #include "abstract.h" static const char *atype_names[] = { "", "net", "busnet", "buschan", "port", "busport", "component", "hub" }; const char *csch_atype_name(csch_atype_t type) { if ((type <= 0) || (type >= (sizeof(atype_names)/sizeof(atype_names[0])))) return atype_names[CSCH_ATYPE_INVALID]; return atype_names[type]; } void csch_ahdr_uninit(csch_ahdr_t *hdr) { csch_attrib_uninit(&hdr->attr); vtp0_uninit(&hdr->srcs); } void csch_anet_free_fields(csch_anet_t *net) { vtp0_uninit(&net->conns); free(net->name); free(net->name_loc); csch_ahdr_uninit(&net->hdr); } void csch_aport_free_fields(csch_aport_t *port) { free(port->name); csch_ahdr_uninit(&port->hdr); } void csch_acomp_free_fields(csch_acomp_t *comp) { htsp_entry_t *e; for(e = htsp_first(&comp->ports); e != NULL; e = htsp_next(&comp->ports, e)) { csch_aport_free_fields(e->value); free(e->value); e->value = NULL; } for(e = htsp_first(&comp->busports); e != NULL; e = htsp_next(&comp->busports, e)) { abort(); } htsp_uninit(&comp->ports); htsp_uninit(&comp->busports); free(comp->name); free(comp->name_loc); csch_ahdr_uninit(&comp->hdr); } void csch_abstract_init(csch_abstract_t *abs) { memset(abs, 0, sizeof(csch_abstract_t)); htsp_init(&abs->nets, strhash, strkeyeq); htsp_init(&abs->comps, strhash, strkeyeq); htip_init(&abs->aid2obj, longhash, longkeyeq); abs->hroot = csch_hlevel_new(NULL, NULL, NULL); abs->next_aid = 1; } void csch_abstract_uninit(csch_abstract_t *abs) { htsp_entry_t *e; long n; csch_hlevel_free_tree(abs->hroot); for(e = htsp_first(&abs->nets); e != NULL; e = htsp_next(&abs->nets, e)) { csch_anet_free_fields(e->value); free(e->value); e->value = NULL; } for(e = htsp_first(&abs->comps); e != NULL; e = htsp_next(&abs->comps, e)) { csch_acomp_free_fields(e->value); free(e->value); e->value = NULL; } for(n = 0; n < abs->orphaned_ports.used; n++) { csch_aport_free_fields(abs->orphaned_ports.array[n]); free(abs->orphaned_ports.array[n]); } htsp_uninit(&abs->nets); htsp_uninit(&abs->comps); htip_uninit(&abs->aid2obj); vtp0_uninit(&abs->orphaned_ports); memset(abs, 0, sizeof(csch_abstract_t)); } /* Initialize an object by setting the common header fields; the only purpose of this function is to get compiler warnings at every caller when the header is extended (because the number of args would be extended here) */ RND_INLINE void csch_aobj_init(csch_abstract_t *abs, csch_ahdr_t *dst, csch_atype_t type) { dst->type = type; csch_attrib_init(&dst->attr); dst->abst = abs; /* assign unique aid */ dst->aid = abs->next_aid; abs->next_aid++; if (abs->next_aid < 1) abs->next_aid = 1; htip_set(&abs->aid2obj, dst->aid, dst); switch(type) { case CSCH_ATYPE_INVALID: case CSCH_ATYPE_BUSNET: case CSCH_ATYPE_BUSCHAN: case CSCH_ATYPE_BUSPORT: case CSCH_ATYPE_HUB: break; case CSCH_ATYPE_PORT: abs->new_ports = 1; break; case CSCH_ATYPE_NET: abs->new_nets = 1; break; case CSCH_ATYPE_COMP: abs->new_comps = 1; break; } } csch_ascope_t csch_split_name_scope(const char **name) { const char *nm = *name; if (nm[0] == '/') { (*name) += 1; return CSCH_ASCOPE_GLOBAL; } /* check this so nm[1] is safe to address */ if (nm[0] == '\0') return CSCH_ASCOPE_AUTO; if (nm[1] == '/') { if (nm[0] == '.') { (*name) += 2; return CSCH_ASCOPE_SHEET_LOCAL; } if (nm[0] == '^') { (*name) += 2; return CSCH_ASCOPE_SUBTREE_AUTO; } if (nm[0] == 'v') { (*name) += 2; return CSCH_ASCOPE_SUBTREE_LOCAL; } } /* no usable prefix */ return CSCH_ASCOPE_AUTO; } #include "abs_net.c" #include "abs_comp.c" csch_aport_t *csch_aport_get(csch_abstract_t *abs, csch_acomp_t *comp, const char *name, int alloc) { csch_aport_t *port; if (comp != NULL) { port = htsp_get(&comp->ports, name); if ((port != NULL) || (!alloc)) return port; } port = calloc(sizeof(csch_aport_t), 1); csch_aobj_init(abs, &port->hdr, CSCH_ATYPE_PORT); port->name = rnd_strdup(name); port->parent = comp; if (comp != NULL) htsp_set(&comp->ports, port->name, port); else vtp0_append(&abs->orphaned_ports, port); return port; } static void dump_attr(const csch_attribs_t *attr, FILE *f, const char *prefix1, const char *prefix2) { htsp_entry_t *e; fprintf(f, "%s%sAttributes:\n", prefix1, prefix2); for(e = htsp_first(attr); e != NULL; e = htsp_next(attr, e)) { const csch_attrib_t *a = e->value; if (a->deleted) continue; if (a->val == NULL) { long n; fprintf(f, "%s%s %s={\n", prefix1, prefix2, a->key); for(n = 0; n < a->arr.used; n++) fprintf(f, "%s%s %s\n", prefix1, prefix2, a->arr.array[n]); fprintf(f, "%s%s }\n", prefix1, prefix2); } else fprintf(f, "%s%s %s=%s\n", prefix1, prefix2, a->key, a->val); } } void csch_abstract_dump(const csch_abstract_t *abs, FILE *f, const char *prefix) { htsp_entry_t *e; fprintf(f, "%sNets:\n", prefix); for(e = htsp_first(&abs->nets); e != NULL; e = htsp_next(&abs->nets, e)) { csch_anet_t *net = e->value; long n; fprintf(f, "%s %s\n", prefix, net->name); fprintf(f, "%s ports:\n", prefix); for(n = 0; n < net->conns.used; n++) { csch_aport_t *port = net->conns.array[n]; fprintf(f, "%s %s-%s\n", prefix, APORT_PARENT_NAME(port), port->name); } dump_attr(&net->hdr.attr, f, prefix, " "); } fprintf(f, "%sComponents:\n", prefix); for(e = htsp_first(&abs->comps); e != NULL; e = htsp_next(&abs->comps, e)) { htsp_entry_t *pe; csch_acomp_t *comp = e->value; fprintf(f, "%s %s\n", prefix, comp->name); fprintf(f, "%s Ports:\n", prefix); for(pe = htsp_first(&comp->ports); pe != NULL; pe = htsp_next(&comp->ports, pe)) { csch_aport_t *port = pe->value; fprintf(f, "%s %s\n", prefix, port->name); dump_attr(&port->hdr.attr, f, prefix, " "); } dump_attr(&comp->hdr.attr, f, prefix, " "); } }