/* * libs.c - Component libraries * * Copyright 2012 by Werner Almesberger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. */ #define _GNU_SOURCE /* for strcasecmp */ #include #include #include #include #include #include #include "util.h" #include "libs.h" struct entry { struct name *names; int units; struct entry *next; }; static struct lib { const char *path; struct entry *comps; struct lib *next; } *libs = NULL; const char *lookup_sym(const char *name, const struct name **names, int *units) { const struct lib *lib; const struct entry *e; for (lib = libs; lib; lib = lib->next) for (e = lib->comps; e; e = e->next) if (!strcasecmp(e->names->s, name)) { if (names) *names = e->names; if (units) *units = e->units; return lib->path; } return NULL; } static const char *field(const char *s, int n) { while (n-- && *s) { while (*s && !isspace(*s)) s++; while (*s && isspace(*s)) s++; } return *s ? s : NULL; } static void add_name(struct entry *e, char *s) { char *nl; struct name **p; nl = strchr(s, '\n'); if (nl) *nl = 0; for (p = &e->names; *p; p = &(*p)->next); *p = alloc_type(struct name); (*p)->s = stralloc(s); (*p)->next = NULL; } void add_lib(const char *path) { FILE *file; struct lib *lib; struct entry *e = NULL; char buf[1024]; /* @@@ */ char *name, *spc; const char *s; file = fopen(path, "r"); if (!file) { perror(path); exit(1); } lib = alloc_type(struct lib); lib->path = stralloc(path); lib->comps = NULL; lib->next = libs; libs = lib; while (fgets(buf, sizeof(buf), file)) { if (!strncmp(buf, "ALIAS ", 6) && e) add_name(e, buf+6); if (strncmp(buf, "DEF ", 4)) continue; s = field(buf, 7); if (!s) { fprintf(stderr, "DEF record lacks units field in %s\n", path); exit(1); } name = buf+4; if (*name == '~') name++; spc = strchr(name, ' '); if (!spc) { fprintf(stderr, "invalid DEF line in %s\n", path); exit(1); } *spc = 0; e = alloc_type(struct entry); e->names = NULL; add_name(e, name); e->units = atoi(s); if (!e->units) { fprintf(stderr, "invalid number of units in %s\n", path); exit(1); } e->next = lib->comps; lib->comps = e; } fclose(file); } void add_libdir(const char *path) { DIR *dir; const struct dirent *de; size_t len; char *tmp; dir = opendir(path); if (!dir) { perror(path); exit(1); } while (1) { de = readdir(dir); if (!de) break; len = strlen(de->d_name); if (len < 4) continue; if (strcmp(de->d_name+len-4, ".lib")) continue; if (asprintf(&tmp, "%s/%s", path, de->d_name) < 0) { perror("asprintf"); exit(1); } add_lib(tmp); } closedir(dir); }