Date:2012-06-26 02:04:59 (11 years 9 months ago)
Author:Werner Almesberger
Commit:e832845a0206a3c0690885b71ef3ba5ecc091491
Message:genex/: renamed genex to gencat

Files: gencat/DESC (1 diff)
gencat/Makefile (1 diff)
gencat/comp.c (1 diff)
gencat/comp.h (1 diff)
gencat/expand-pintype (1 diff)
gencat/gencat (1 diff)
gencat/gencat.c (1 diff)
gencat/gencat.h (1 diff)
gencat/libs.c (1 diff)
gencat/libs.h (1 diff)
gencat/mkgencat-wrapper (1 diff)
gencat/pdf.c (1 diff)
gencat/pdf.h (1 diff)
gencat/run (1 diff)
gencat/sym2xps (1 diff)
gencat/util.h (1 diff)
genex/DESC (1 diff)
genex/Makefile (1 diff)
genex/comp.c (1 diff)
genex/comp.h (1 diff)
genex/expand-pintype (1 diff)
genex/genex (1 diff)
genex/genex.c (1 diff)
genex/genex.h (1 diff)
genex/libs.c (1 diff)
genex/libs.h (1 diff)
genex/mkgenex-wrapper (1 diff)
genex/pdf.c (1 diff)
genex/pdf.h (1 diff)
genex/run (1 diff)
genex/sym2xps (1 diff)
genex/util.h (1 diff)

Change Details

gencat/DESC
1wm9707scft/v: This is a comment.
2  Continuation of the same line.
3
4  Here we have a line break,
5  and so on
6wm9707scft/v: Another comment
7  for the same component.
8WM9707SCFT/V: Component names in comments are case-insensitive.
gencat/Makefile
1#
2# Makefile - Expanded component view generator
3#
4# Copyright 2012 by Werner Almesberger
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11
12PREFIX ?= /usr/local
13
14OBJS = gencat.o comp.o libs.o pdf.o
15
16SHELL = /bin/bash
17CFLAGS = -Wall -g
18
19CC_normal := $(CC)
20DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG
21
22CC_quiet = @echo " CC " $@ && $(CC_normal)
23GEN_quiet = @echo " GENERATE " $@ &&
24DEPEND_quiet = @$(DEPEND_normal)
25
26ifeq ($(V),1)
27    CC = $(CC_normal)
28    GEN =
29    DEPEND = $(DEPEND_normal)
30else
31    CC = $(CC_quiet)
32    GEN = $(GEN_quiet)
33    DEPEND = $(DEPEND_quiet)
34endif
35
36.PHONY: all clean spotless install uninstall
37
38all: gencat-bin
39
40gencat-bin: $(OBJS)
41        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDLIBS)
42
43%.o: %.c
44        $(CC) -c $(CFLAGS) $*.c -o $*.o
45        $(DEPEND) $*.c | \
46          sed -e \
47            '/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \
48            -e '$${g;p;}' -e d >$*.d; \
49          [ "$${PIPESTATUS[*]}" = "0 0" ] || { rm -f $*.d; exit 1; }
50
51-include $(OBJS:.o=.d)
52
53clean:
54        rm -f $(OBJS) $(OBJS:.o=.d)
55
56spotless: clean
57        rm -f gencat-bin
58
59#
60# Note: we use .../lib/gencat/ instead of .../libexec/gencat/ because FHS-3.0
61# does not define libexec under the /usr/local/ hierarchy. (And older versions
62# of FHS don't define libexec at all.)
63#
64
65install: all
66        mkdir -p $(DESTDIR)/$(PREFIX)/bin
67        mkdir -p $(DESTDIR)/$(PREFIX)/lib/gencat
68        ./mkgencat-wrapper -m 755 -p $(DESTDIR)/$(PREFIX)/lib/gencat/ \
69          $(DESTDIR)/$(PREFIX)/bin/gencat
70        install -m 755 gencat-bin $(DESTDIR)/$(PREFIX)/lib/gencat/
71        install -m 755 sym2xps $(DESTDIR)/$(PREFIX)/lib/gencat/
72        install -m 755 expand-pintype $(DESTDIR)/$(PREFIX)/lib/gencat/
73
74uninstall:
75        rm -f $(DESTDIR)/$(PREFIX)/bin/gencat
76        rm -rf $(DESTDIR)/$(PREFIX)/lib/gencat
77
gencat/comp.c
1/*
2 * comp.c - Component hierarchy
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#define _GNU_SOURCE /* for strcasecmp */
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <ctype.h>
17
18#include "util.h"
19#include "comp.h"
20
21
22struct node *tree = NULL;
23
24
25void read_tree(FILE *file)
26{
27    char buf[1100]; /* more than enough */
28    struct node *last = NULL, *node;
29    int depth = -1;
30    const char *s, *p, *e;
31    char *name;
32    int n;
33
34next:
35    while (fgets(buf, sizeof(buf), file)) {
36        n = 0;
37        s = buf;
38        while (1) {
39            switch (*s++) {
40            case ' ':
41                n++;
42                continue;
43            case '\t':
44                n = (n+8) & ~7;
45                continue;
46            case 0:
47            case '#':
48                goto next;
49            default:
50                break;
51            }
52            break;
53        }
54        for (p = e = --s; *p && *p != '#' && *p != '\n'; p++)
55            if (*p != ' ' && *p != '\t')
56                e = p;
57        if (!last && n) {
58            fprintf(stderr, "first entry must not be intended\n");
59            exit(1);
60        }
61        name = malloc(e-s+2);
62        if (!name) {
63            perror("malloc");
64            exit(1);
65        }
66        memcpy(name, s, e-s+1);
67        name[e-s+1] = 0;
68        node = alloc_type(struct node);
69        node->name = name;
70        node->lib = NULL;
71        node->comment = NULL;
72        node->indent = n;
73        node->child = node->next = NULL;
74        if (n > depth) {
75            if (last)
76                last->child = node;
77            else
78                tree = node;
79            node->parent = last;
80        } else {
81            while (last && last->indent != n)
82                last = last->parent;
83            if (!last && n) {
84                fprintf(stderr, "indentation error\n");
85                exit(1);
86            }
87            last->next = node;
88            node->parent = last->parent;
89        }
90        last = node;
91        depth = n;
92    }
93}
94
95
96static struct node *find_comp(struct node *node, const char *name)
97{
98    struct node *found;
99
100    while (node) {
101        if (!strcasecmp(node->name, name))
102            return node;
103        found = find_comp(node->child, name);
104        if (found)
105            return found;
106        node = node->next;
107    }
108    return NULL;
109}
110
111
112static struct line *new_line(char *s)
113{
114    struct line *line;
115
116    line = alloc_type(struct line);
117    line->s = stralloc(s);
118    line->next = NULL;
119    return line;
120}
121
122
123static void append_line(struct line *line, char *s)
124{
125    int len1, len2;
126
127    len1 = strlen(line->s);
128    len2 = strlen(s);
129    line->s = realloc(line->s, len1+len2+1+1); /* separating space */
130    if (!line->s) {
131        perror("realloc");
132        exit(1);
133    }
134    line->s[len1] = ' ';
135    memcpy(line->s+len1+1, s, len2);
136    line->s[len1+len2+1] = 0;
137}
138
139
140void read_desc(FILE *file)
141{
142    struct line **anchor = NULL;
143    char buf[1100]; /* more than enough */
144    struct node *node;
145    char *p, *end;
146    int skip = 0, lineno = 0;
147
148    while (fgets(buf, sizeof(buf), file)) {
149        lineno++;
150        p = strchr(buf, '\n');
151        if (p)
152            *p = 0;
153        p = buf;
154        if (*buf && !isspace(*buf)) {
155            /* tag is ^.*?:\s */
156            while (1) {
157                p = strchr(p, ':');
158                if (!p) {
159                    fprintf(stderr, "no tag in line %d\n",
160                        lineno);
161                    exit(1);
162                }
163                if (!p[1] || isspace(p[1]))
164                    break;
165                p++;
166            }
167            *p++ = 0;
168            node = find_comp(tree, buf);
169            if (!node) {
170                fprintf(stderr,
171                    "component \"%s\" not found in line %d\n",
172                    buf, lineno);
173                skip = 1;
174                continue;
175            }
176            for (anchor = &node->comment; *anchor;
177                anchor = &(*anchor)->next);
178            skip = 0;
179        }
180        if (skip)
181            continue;
182
183        /* remove leading whitespace */
184        while (*p && isspace(*p))
185            p++;
186        if (!*p) {
187            if (*anchor)
188                anchor = &(*anchor)->next;
189            continue;
190        }
191
192        /* remove training whitespace */
193        end = strrchr(p, 0);
194        while (isspace(end[-1]))
195            end--;
196        *end = 0;
197
198        if (*anchor)
199            append_line(*anchor, p);
200        else
201            *anchor = new_line(p);
202    }
203}
204
205
206void set_libs(struct node *node,
207    const char *(*find_lib)(const char *sym, const struct name **names,
208    int *units))
209{
210    while (node) {
211        if (!node->child) {
212            node->lib =
213                find_lib(node->name, &node->names, &node->units);
214            if (!node->lib) {
215                fprintf(stderr, "symbol %s not found\n",
216                    node->name);
217                exit(1);
218            }
219        }
220        set_libs(node->child, find_lib);
221        node = node->next;
222    }
223}
224
225
226static void dump_tree_level(const struct node *tree, int level)
227{
228    const struct node *n;
229    const struct line *line;
230    const struct name *name;
231
232    for (n = tree; n; n = n->next) {
233        printf("%*s%s", 4*level, "", n->name);
234        if (n->lib) {
235            for (name = n->names; name; name = name->next)
236                printf("%s%s",
237                    name == n->names ? " (" : ", ", name->s);
238            printf(")");
239        }
240        printf("\n");
241        for (line = n->comment; line; line = line->next)
242            printf("%*s\"%s\"\n", 4*level+2, "", line->s);
243        dump_tree_level(n->child, level+1);
244    }
245}
246
247
248void dump_tree(void)
249{
250    dump_tree_level(tree, 0);
251}
252
253
254static void dump_comp_level(const struct node *tree)
255{
256    const struct node *n;
257
258    for (n = tree; n; n = n->next) {
259        if (n->lib)
260            printf("%s\n", n->names->s);
261        dump_comp_level(n->child);
262    }
263}
264
265
266void dump_comp(void)
267{
268    dump_comp_level(tree);
269}
gencat/comp.h
1/*
2 * comp.h - Component hierarchy
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef COMP_H
13#define COMP_H
14
15#include "libs.h"
16
17
18struct line {
19    char *s;
20    struct line *next;
21};
22
23struct node {
24    const char *name;
25    const char *lib; /* NULL if intermediate node */
26    const struct name *names;
27                /* canonical name and aliases of component */
28    int units; /* number of units; undefined if intermediate */
29    struct line *comment; /* NULL if intermediate node */
30    int indent; /* level of indentation (characters) */
31    struct node *parent;
32    struct node *child;
33    struct node *next;
34};
35
36
37extern struct node *tree;
38
39
40void read_tree(FILE *file);
41void read_desc(FILE *file);
42void set_libs(struct node *node,
43    const char *(*find_lib)(const char *sym, const struct name **names,
44    int *units));
45void dump_tree(void);
46void dump_comp(void);
47
48#endif /* !COMP_H */
gencat/expand-pintype
1#!/usr/bin/perl
2#
3# expand-pintype - Expand pin types of symbols in a Kicad library
4#
5# Copyright 2010, 2012 by Werner Almesberger
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12
13#
14# usage:
15#
16# expand-pintype input.lib
17# expand-pintype input.lib output.lib
18#
19
20
21$GAP = 50; # gap between pin and type, in mil
22$CHAR_WIDTH = 60; # default character width, in mil
23$NAME_WIDTH = 15; # name field width in ASCII mode, in characters
24
25
26%map = (
27    "I" => "Input",
28    "O" => "Output",
29    "B" => "BiDi",
30    "T" => "3-state",
31    "P" => "Passive",
32    "U" => "Unspec",
33    "W" => "Pwr In",
34    "w" => "Pwr Out",
35    "C" => "OC",
36    "E" => "OE",
37    "N" => "NC",
38);
39
40if (@ARGV < 2) {
41    $out = 0;
42} elsif (@ARGV == 2) {
43    $file = pop @ARGV;
44    $out = 1;
45    open(FILE, ">$file") || die "$file: $!";
46} else {
47    print STDERR "usage: expand-pintype input.lib [output.lib]\n";
48    exit(1);
49}
50
51while (<>) {
52    if ($out) {
53    # make name differ so that KiCad's cache doesn't get confused
54        s/^DEF\s+~?/$&X/;
55        s/^F1\s+"+/$&X/;
56        print FILE || die;
57    }
58    next unless /^X/;
59    @a = split(/\s+/);
60    ($name, $pin, $x, $y, $dir, $unit, $pt) = @a[1, 2, 3, 4, 6, 9, 11];
61    $type = $map{$pt};
62    $type = "???" unless defined $type;
63    if ($out) {
64        $off = $GAP+(length $type)*$CHAR_WIDTH/2;
65        if ($dir eq "U") {
66            ($a, $y) = (90, $y-$off);
67        } elsif ($dir eq "D") {
68            ($a, $y) = (90, $y+$off);
69        } elsif ($dir eq "R") {
70                ($a, $x) = (0, $x-$off);
71        } else {
72            ($a, $x) = (0, $x+$off);
73        }
74        $type =~ y/ /~/;
75        print FILE sprintf("T %d %d %d 60 0 %d 0 %s Normal 0\n",
76            $a*10, $x, $y, $unit, $type);
77    } else {
78        $s = "$name ($pin)";
79        $f = $NAME_WIDTH-length $s;
80        $f = "-" x ($f > 0 ? $f : 0);
81        print "$s $f $type\n";
82    }
83}
84if ($out) {
85    close FILE || die;
86}
gencat/gencat
1#!/bin/sh
2PATH=$PATH:.
3exec gencat-bin "$@"
gencat/gencat.c
1/*
2 * gencat.c - Generate expanded component view
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12
13#include <stdlib.h>
14#include <stdio.h>
15#include <unistd.h>
16#include <string.h>
17
18#include "comp.h"
19#include "libs.h"
20#include "pdf.h"
21#include "gencat.h"
22
23
24int quiet = 0;
25
26
27static void usage(const char *name)
28{
29    fprintf(stderr,
30"usage: %s [-d|-D] [-p] [-P] [-q] [-L libdir ...] [-l lib ...] hierarchy\n"
31" %*s [descriptions ...]\n\n"
32" -d dump the tree instead of generating a PDF\n"
33" -D dump all the canonical component names (without aliases)\n"
34" -L libdir search all libraries in the specified directory\n"
35" -l lib search the specified component library\n"
36" -p use portrait orientation; default: landscape\n"
37" -P generate Postscript instead of PDF (mainly for debugging)\n"
38" -q don't show progress\n"
39    , name, (int) strlen(name), "");
40    exit(1);
41}
42
43
44int main(int argc, char **argv)
45{
46    FILE *file;
47    int c;
48    int opt_dump_tree = 0, opt_dump_comp = 0, postscript = 0, portrait = 0;
49    char **arg;
50
51    while ((c = getopt(argc, argv, "dDL:l:Ppq")) != EOF)
52        switch (c) {
53        case 'd':
54            opt_dump_tree = 1;
55            break;
56        case 'D':
57            opt_dump_comp = 1;
58            break;
59        case 'L':
60            add_libdir(optarg);
61            break;
62        case 'l':
63            add_lib(optarg);
64            break;
65        case 'P':
66            postscript = 1;
67            break;
68        case 'p':
69            portrait = 1;
70            break;
71        case 'q':
72            quiet = 1;
73            break;
74        default:
75            usage(*argv);
76        }
77
78    if (opt_dump_tree && opt_dump_comp)
79        usage(*argv);
80
81    switch (argc-optind) {
82    case 1:
83    case 2:
84        break;
85    default:
86        usage(*argv);
87    }
88
89    file = fopen(argv[optind], "r");
90    if (!file) {
91        perror(argv[optind]);
92        exit(1);
93    }
94    read_tree(file);
95    fclose(file);
96    set_libs(tree, lookup_sym);
97
98    for (arg = argv+optind+1; *arg; arg++) {
99        file = fopen(*arg, "r");
100        if (!file) {
101            perror(*arg);
102            exit(1);
103        }
104        read_desc(file);
105        fclose(file);
106    }
107    if (opt_dump_tree)
108        dump_tree();
109    else if (opt_dump_comp)
110        dump_comp();
111    else
112        make_pdf(!postscript, portrait);
113    return 0;
114}
gencat/gencat.h
1/*
2 * gencat.h - Generate expanded component view
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef GENCAT_H
13#define GENCAT_H
14
15extern int quiet;
16
17#endif /* !GENCAT_H */
gencat/libs.c
1/*
2 * libs.c - Component libraries
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#define _GNU_SOURCE /* for strcasecmp */
13#include <stdlib.h>
14#include <stdio.h>
15#include <ctype.h>
16#include <string.h>
17#include <sys/types.h>
18#include <dirent.h>
19
20#include "util.h"
21#include "libs.h"
22
23
24struct entry {
25    struct name *names;
26    int units;
27    struct entry *next;
28};
29
30static struct lib {
31    const char *path;
32    struct entry *comps;
33    struct lib *next;
34} *libs = NULL;
35
36
37const char *lookup_sym(const char *name, const struct name **names, int *units)
38{
39    const struct lib *lib;
40    const struct entry *e;
41
42    for (lib = libs; lib; lib = lib->next)
43        for (e = lib->comps; e; e = e->next)
44            if (!strcasecmp(e->names->s, name)) {
45                if (names)
46                    *names = e->names;
47                if (units)
48                    *units = e->units;
49                return lib->path;
50            }
51    return NULL;
52}
53
54
55static const char *field(const char *s, int n)
56{
57    while (n-- && *s) {
58        while (*s && !isspace(*s))
59            s++;
60        while (*s && isspace(*s))
61            s++;
62    }
63    return *s ? s : NULL;
64}
65
66
67static void add_name(struct entry *e, char *s)
68{
69    char *nl;
70    struct name **p;
71
72    nl = strchr(s, '\n');
73    if (nl)
74        *nl = 0;
75    for (p = &e->names; *p; p = &(*p)->next);
76    *p = alloc_type(struct name);
77    (*p)->s = stralloc(s);
78    (*p)->next = NULL;
79}
80
81
82void add_lib(const char *path)
83{
84    FILE *file;
85    struct lib *lib;
86    struct entry *e = NULL;
87    char buf[1024]; /* @@@ */
88    char *name, *spc;
89    const char *s;
90
91    file = fopen(path, "r");
92    if (!file) {
93        perror(path);
94        exit(1);
95    }
96
97    lib = alloc_type(struct lib);
98    lib->path = stralloc(path);
99    lib->comps = NULL;
100    lib->next = libs;
101    libs = lib;
102
103    while (fgets(buf, sizeof(buf), file)) {
104        if (!strncmp(buf, "ALIAS ", 6) && e)
105            add_name(e, buf+6);
106        if (strncmp(buf, "DEF ", 4))
107            continue;
108        s = field(buf, 7);
109        if (!s) {
110            fprintf(stderr, "DEF record lacks units field in %s\n",
111                 path);
112            exit(1);
113        }
114        name = buf+4;
115        if (*name == '~')
116            name++;
117        spc = strchr(name, ' ');
118        if (!spc) {
119            fprintf(stderr, "invalid DEF line in %s\n", path);
120            exit(1);
121        }
122        *spc = 0;
123        e = alloc_type(struct entry);
124        e->names = NULL;
125        add_name(e, name);
126        e->units = atoi(s);
127        if (!e->units) {
128            fprintf(stderr, "invalid number of units in %s\n",
129                path);
130            exit(1);
131        }
132        e->next = lib->comps;
133        lib->comps = e;
134    }
135
136    fclose(file);
137}
138
139
140void add_libdir(const char *path)
141{
142    DIR *dir;
143    const struct dirent *de;
144    size_t len;
145    char *tmp;
146
147    dir = opendir(path);
148    if (!dir) {
149        perror(path);
150        exit(1);
151    }
152    while (1) {
153        de = readdir(dir);
154        if (!de)
155            break;
156        len = strlen(de->d_name);
157        if (len < 4)
158            continue;
159        if (strcmp(de->d_name+len-4, ".lib"))
160            continue;
161        if (asprintf(&tmp, "%s/%s", path, de->d_name) < 0) {
162            perror("asprintf");
163            exit(1);
164        }
165        add_lib(tmp);
166    }
167    closedir(dir);
168}
gencat/libs.h
1/*
2 * libs.h - Component libraries
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef LIBS_H
13#define LIBS_H
14
15struct name {
16    const char *s;
17    struct name *next;
18};
19
20const char *lookup_sym(const char *name, const struct name **names, int *units);
21void add_lib(const char *path);
22void add_libdir(const char *path);
23
24#endif /* !LIBS_H */
gencat/mkgencat-wrapper
1#!/bin/sh -e
2#
3# mkgencat-wrapper - Generate wrapper script for gencat
4#
5# Copyright 2012 by Werner Almesberger
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12
13
14MODE=555
15DIR=
16
17usage()
18{
19    echo "usage: $0 [-m mode] [-p directory] wrapper-path" 1>&2
20    exit 1
21}
22
23
24while [ "$1" ]; do
25    case "$1" in
26    -m) shift
27        MODE=$1;;
28    -p) shift
29        DIR=$1;;
30    -*) usage;;
31    *) break;;
32    esac
33    shift
34done
35
36: ${DIR:=`dirname $1`}
37
38[ -d "$DIR" ] && [ "$1" ] && [ -z "$2" ] || usage
39
40trap "rm -f _wrapper" 0
41
42cat <<EOF >_wrapper
43#!/bin/sh
44PATH=\$PATH:$DIR
45exec gencat-bin "\$@"
46EOF
47chmod $MODE _wrapper
48
49mv _wrapper "$1"
gencat/pdf.c
1/*
2 * pdf.c - Generate PDF
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#define _GNU_SOURCE
13#include <stdlib.h>
14#include <stdio.h>
15#include <sys/types.h>
16
17#include "gencat.h"
18#include "comp.h"
19#include "pdf.h"
20
21
22static struct format {
23    const char *file_setup;
24    const char *overlay_setup;
25    const char *comp_setup;
26    int left;
27    struct text {
28        const char *font;
29        int size;
30        int y;
31    } name, path, lib, comment;
32    int comment_line_skip;
33} landscape = {
34    .file_setup = "%%Orientation: Landscape",
35    .overlay_setup = "90 rotate",
36    .comp_setup = "",
37    .left = 20,
38    .name = { "Helvetica-Bold", 24, 57 },
39    .path = { "Helvetica-Bold", 18, 30 },
40    .lib = { "Courier", 12, 75 },
41    .comment = { "Helvetica", 12, 600 },
42    .comment_line_skip = 14,
43}, portrait = {
44    .file_setup = "%%Orientation: Portrait",
45    .overlay_setup = "0 790 translate",
46    .comp_setup = "-120 700 translate -90 rotate",
47    .left = 20,
48    .name = { "Helvetica-Bold", 24, 57 },
49    .path = { "Helvetica-Bold", 18, 30 },
50    .lib = { "Courier", 12, 75 },
51    .comment = { "Helvetica", 12, 740 },
52    .comment_line_skip = 14,
53}, format;
54
55static int total, done = 0;
56
57
58static int children(const struct node *node)
59{
60    int n = 0;
61
62    while (node) {
63        n++;
64        node = node->next;
65    }
66    return n;
67}
68
69
70static void ps_string(FILE *file, const char *s)
71{
72    fputc('(', file);
73    while (*s) {
74        if (*s == '(' || *s == ')' || *s == '\\')
75            fputc('\\', file);
76        fputc(*s, file);
77        s++;
78    }
79    fputc(')', file);
80}
81
82
83static void print_path(FILE *file, const struct node *node)
84{
85    if (node->parent) {
86        print_path(file, node->parent);
87        fprintf(file, "( > ) show\n");
88    }
89    ps_string(file, node->name);
90    fprintf(file, " 0.5 setgray show 0 setgray\n");
91}
92
93
94static void make_title(FILE *file, const struct node *node, int unit)
95{
96    const struct name *name;
97
98    fprintf(file, "gsave %s 0 setgray\n", format.overlay_setup);
99
100    fprintf(file, "/%s findfont %d scalefont setfont\n",
101        format.name.font, format.name.size);
102    fprintf(file, "%d %d moveto\n", format.left, -format.name.y);
103    for (name = node->names; name; name = name->next) {
104        if (name != node->names)
105            fprintf(file, "(, ) show 0.5 setgray\n");
106        ps_string(file, name->s);
107        fprintf(file, " show\n");
108    }
109    fprintf(file, "0 setgray\n");
110    if (node->units > 1)
111        fprintf(file, " ( \\(%c\\)) show\n", 'A'+unit);
112
113    fprintf(file, "/%s findfont %d scalefont setfont\n",
114        format.path.font, format.path.size);
115    fprintf(file, "%d %d moveto\n", format.left, -format.path.y);
116    print_path(file, node);
117
118    fprintf(file, "/%s findfont %d scalefont setfont\n",
119        format.lib.font, format.lib.size);
120    fprintf(file, "%d %d moveto\n", format.left, -format.lib.y);
121    ps_string(file, node->lib);
122    fprintf(file, " show\n");
123
124    fprintf(file, "grestore\n");
125}
126
127
128static void print_comment(FILE *file, const struct line *comment)
129{
130    const struct line *line;
131    int lines = 0;
132    int n;
133
134    fprintf(file, "gsave %s 0 setgray\n", format.overlay_setup);
135    fprintf(file, "/%s findfont %d scalefont setfont\n",
136        format.comment.font, format.comment.size);
137    for (line = comment; line; line = line->next)
138        lines++;
139    n = 0;
140    for (line = comment; line; line = line->next) {
141        n++;
142        fprintf(file, "%d -%d moveto\n", format.left,
143            format.comment.y+(n-lines)*format.comment_line_skip);
144        ps_string(file, line->s);
145        fprintf(file, " show\n");
146    }
147    fprintf(file, "grestore\n");
148}
149
150
151static void cat(FILE *out, const char *name)
152{
153    FILE *in;
154    char buf[10000]; /* pick any good size */
155    size_t got, wrote;
156
157    in = fopen(name, "r");
158    if (!in) {
159        perror(name);
160        exit(1);
161    }
162    while (1) {
163        got = fread(buf, 1, sizeof(buf), in);
164        if (!got)
165            break;
166        wrote = fwrite(buf, 1, got, out);
167        if (wrote != got) {
168            perror("fwrite");
169            exit(1);
170        }
171    }
172    if (ferror(in)) {
173        perror(name);
174        exit(1);
175    }
176    fclose(in);
177}
178
179
180static void convert_comp(const struct node *node, FILE *out)
181{
182    char *tmp;
183    int i, res;
184
185    for (i = 0; i != node->units; i++) {
186        if (!quiet) {
187            fprintf(stderr, "\r%u/%u", ++done, total);
188            fflush(stderr);
189        }
190        make_title(out, node, i);
191        if (!i && node->comment)
192            print_comment(out, node->comment);
193        if (asprintf(&tmp, "sym2xps '%s' '%s' %d '%s' '%s'",
194            node->lib, node->names->s, i+1, "tmp", "tmp.ps") < 0) {
195            perror("asprintf");
196            exit(1);
197        }
198        res = system(tmp);
199        if (res < 0) {
200            perror("system");
201            exit(1);
202        }
203        if (res) {
204            fprintf(stderr, "sym2xps returned %d\n", res);
205            exit(1);
206        }
207        fprintf(out, "gsave %s\n", format.comp_setup);
208        cat(out, "tmp.ps");
209        fprintf(out, "\ngrestore\n");
210    }
211}
212
213
214static void convert_tree(const struct node *node, FILE *out)
215{
216    while (node) {
217        fprintf(out, "[ /Title (%s) /Count %d /OUT pdfmark\n",
218            node->name, -children(node->child));
219        if (node->child)
220            convert_tree(node->child, out);
221        else
222            convert_comp(node, out);
223        node = node->next;
224    }
225}
226
227
228static int count_tree(const struct node *node)
229{
230    int sum = 0;
231
232    while (node) {
233        if (node->child)
234            sum += count_tree(node->child);
235        else
236            sum += node->units;
237        node = node->next;
238    }
239    return sum;
240}
241
242
243void make_pdf(int pdf, int use_portrait)
244{
245    FILE *out;
246    int res;
247
248    if (use_portrait)
249        format = portrait;
250    else
251        format = landscape;
252    if (pdf)
253        out = popen(
254            "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=- "
255              "-f -", "w");
256    else
257        out = popen("cat", "w");
258    if (!out) {
259        perror("gs");
260        exit(1);
261    }
262    fprintf(out, "%%!PS\n%s\n", format.file_setup);
263    total = count_tree(tree);
264    convert_tree(tree, out);
265    if (!quiet)
266        fprintf(stderr, "\rFinishing\n");
267    res = pclose(out);
268    if (res < 0) {
269        perror("pclose");
270        exit(1);
271    }
272    if (res) {
273        fprintf(stderr, "exit status %d\n", res);
274        exit(1);
275    }
276}
gencat/pdf.h
1/*
2 * pdf.h - Generate PDF
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef PDF_H
13#define PDF_H
14
15void make_pdf(int pdf, int use_portrait);
16
17#endif /* !PDF_H */
gencat/run
1#!/bin/sh
2# Hack: ps2pdf is happy with the PS generate, but if we invoke gs diretctly,
3# isn't. Some voodoo is still missing ...
4./gencat -p \
5    -L /home/qi/kicad-libs/components \
6    /home/qi/kicad-libs/components/EXPAND DESC >out.pdf
gencat/sym2xps
1#!/bin/sh -e
2#
3# sym2xps - Convert a symbol from a Kicad library to Postscript with expanded
4# pin types
5#
6# Copyright 2012 by Werner Almesberger
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13
14
15usage()
16{
17    echo "usage: $0 library symbol unit tmpdir outfile" 1>&2
18    exit 1
19}
20
21
22lib=$1
23sym=$2
24unit=$3
25tmp=$4
26out=$5
27
28[ "$lib" ] && [ "$sym" ] && [ "$unit" ] && [ "$tmp" ] && [ "$out" ] || usage
29
30[ -r "$lib" ] || {
31    echo "$lib: not found" 1>&2
32    exit 1
33}
34
35grep "^DEF $sym " "$lib" >/dev/null || grep "^DEF ~$sym " "$lib" >/dev/null || {
36    echo "\"$sym\" not found in $lib" 1>&2
37    exit 1
38}
39
40[ "${tmp#/}" = "$tmp" ] && tmp=`pwd`/$tmp
41[ "${out#/}" = "$out" ] && out=`pwd`/$out
42
43mkdir "$tmp"
44
45trap "rm -rf '$tmp'" 0
46
47expand-pintype "$lib" "$tmp"/tmp.lib
48
49cat <<EOF >"$tmp"/tmp.pro
50[eeschema]
51version=1
52[eeschema/libraries]
53LibName1=./tmp
54EOF
55
56X=6000
57Y=4000
58
59sed "\@^DEF $sym @,/^ENDDEF/p;d" "$lib" |
60  awk '/^F. / { if ($1 == "F0") sub(/"$/, "?\"", $2);
61    print substr($1, 1, 1), substr($1, 2, 1), $2,
62    $6, '$X'+$3, '$Y'+$4, $5, " 0000", $8, $9 }' >"$tmp"/fx.tmp
63#F field_number "text" orientation posX posY size Flags (see below)
64#F0 reference posx posy text_size text_orient visibile htext_justify vtext_justify
65
66cat <<EOF >"$tmp"/tmp.sch
67EESchema Schematic File Version 2 date Mon Mar 26 09:29:33 2012
68LIBS:dummy
69EELAYER 43 0
70EELAYER END
71\$Comp
72L X$sym ??
73U $unit 1 00000000
74P $X $Y
75`cat "$tmp"/fx.tmp`
76    $unit $X $Y
77    1 0 0 -1
78\$EndComp
79\$EndSCHEMATC
80EOF
81
82cd "$tmp"
83eeschema --plot=ps "$tmp/tmp.sch"
84mv tmp.ps "$out"
gencat/util.h
1/*
2 * util.h - Utility functions
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef UTIL_H
13#define UTIL_H
14
15#include <stdlib.h>
16#include <string.h>
17
18
19#define alloc_size(s) \
20    ({ void *alloc_size_tmp = malloc(s); \
21    if (!alloc_size_tmp) \
22        abort(); \
23    alloc_size_tmp; })
24
25#define alloc_type(t) ((t *) alloc_size(sizeof(t)))
26
27
28static inline char *stralloc(const char *s)
29{
30    char *t;
31
32    t = strdup(s);
33    if (t)
34        return t;
35    perror("strdup");
36    exit(1);
37}
38
39#endif /* !UTIL_H */
genex/DESC
1wm9707scft/v: This is a comment.
2  Continuation of the same line.
3
4  Here we have a line break,
5  and so on
6wm9707scft/v: Another comment
7  for the same component.
8WM9707SCFT/V: Component names in comments are case-insensitive.
genex/Makefile
1#
2# Makefile - Expanded component view generator
3#
4# Copyright 2012 by Werner Almesberger
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 2 of the License, or
9# (at your option) any later version.
10#
11
12PREFIX ?= /usr/local
13
14OBJS = genex.o comp.o libs.o pdf.o
15
16SHELL = /bin/bash
17CFLAGS = -Wall -g
18
19CC_normal := $(CC)
20DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG
21
22CC_quiet = @echo " CC " $@ && $(CC_normal)
23GEN_quiet = @echo " GENERATE " $@ &&
24DEPEND_quiet = @$(DEPEND_normal)
25
26ifeq ($(V),1)
27    CC = $(CC_normal)
28    GEN =
29    DEPEND = $(DEPEND_normal)
30else
31    CC = $(CC_quiet)
32    GEN = $(GEN_quiet)
33    DEPEND = $(DEPEND_quiet)
34endif
35
36.PHONY: all clean spotless install uninstall
37
38all: genex-bin
39
40genex-bin: $(OBJS)
41        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDLIBS)
42
43%.o: %.c
44        $(CC) -c $(CFLAGS) $*.c -o $*.o
45        $(DEPEND) $*.c | \
46          sed -e \
47            '/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \
48            -e '$${g;p;}' -e d >$*.d; \
49          [ "$${PIPESTATUS[*]}" = "0 0" ] || { rm -f $*.d; exit 1; }
50
51-include $(OBJS:.o=.d)
52
53clean:
54        rm -f $(OBJS) $(OBJS:.o=.d)
55
56spotless: clean
57        rm -f genex-bin
58
59#
60# Note: we use .../lib/genex/ instead of .../libexec/genex/ because FHS-3.0
61# does not define libexec under the /usr/local/ hierarchy. (And older versions
62# of FHS don't define libexec at all.)
63#
64
65install: all
66        mkdir -p $(DESTDIR)/$(PREFIX)/bin
67        mkdir -p $(DESTDIR)/$(PREFIX)/lib/genex
68        ./mkgenex-wrapper -m 755 -p $(DESTDIR)/$(PREFIX)/lib/genex/ \
69          $(DESTDIR)/$(PREFIX)/bin/genex
70        install -m 755 genex-bin $(DESTDIR)/$(PREFIX)/lib/genex/
71        install -m 755 sym2xps $(DESTDIR)/$(PREFIX)/lib/genex/
72        install -m 755 expand-pintype $(DESTDIR)/$(PREFIX)/lib/genex/
73
74uninstall:
75        rm -f $(DESTDIR)/$(PREFIX)/bin/genex
76        rm -rf $(DESTDIR)/$(PREFIX)/lib/genex
77
genex/comp.c
1/*
2 * comp.c - Component hierarchy
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#define _GNU_SOURCE /* for strcasecmp */
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <ctype.h>
17
18#include "util.h"
19#include "comp.h"
20
21
22struct node *tree = NULL;
23
24
25void read_tree(FILE *file)
26{
27    char buf[1100]; /* more than enough */
28    struct node *last = NULL, *node;
29    int depth = -1;
30    const char *s, *p, *e;
31    char *name;
32    int n;
33
34next:
35    while (fgets(buf, sizeof(buf), file)) {
36        n = 0;
37        s = buf;
38        while (1) {
39            switch (*s++) {
40            case ' ':
41                n++;
42                continue;
43            case '\t':
44                n = (n+8) & ~7;
45                continue;
46            case 0:
47            case '#':
48                goto next;
49            default:
50                break;
51            }
52            break;
53        }
54        for (p = e = --s; *p && *p != '#' && *p != '\n'; p++)
55            if (*p != ' ' && *p != '\t')
56                e = p;
57        if (!last && n) {
58            fprintf(stderr, "first entry must not be intended\n");
59            exit(1);
60        }
61        name = malloc(e-s+2);
62        if (!name) {
63            perror("malloc");
64            exit(1);
65        }
66        memcpy(name, s, e-s+1);
67        name[e-s+1] = 0;
68        node = alloc_type(struct node);
69        node->name = name;
70        node->lib = NULL;
71        node->comment = NULL;
72        node->indent = n;
73        node->child = node->next = NULL;
74        if (n > depth) {
75            if (last)
76                last->child = node;
77            else
78                tree = node;
79            node->parent = last;
80        } else {
81            while (last && last->indent != n)
82                last = last->parent;
83            if (!last && n) {
84                fprintf(stderr, "indentation error\n");
85                exit(1);
86            }
87            last->next = node;
88            node->parent = last->parent;
89        }
90        last = node;
91        depth = n;
92    }
93}
94
95
96static struct node *find_comp(struct node *node, const char *name)
97{
98    struct node *found;
99
100    while (node) {
101        if (!strcasecmp(node->name, name))
102            return node;
103        found = find_comp(node->child, name);
104        if (found)
105            return found;
106        node = node->next;
107    }
108    return NULL;
109}
110
111
112static struct line *new_line(char *s)
113{
114    struct line *line;
115
116    line = alloc_type(struct line);
117    line->s = stralloc(s);
118    line->next = NULL;
119    return line;
120}
121
122
123static void append_line(struct line *line, char *s)
124{
125    int len1, len2;
126
127    len1 = strlen(line->s);
128    len2 = strlen(s);
129    line->s = realloc(line->s, len1+len2+1+1); /* separating space */
130    if (!line->s) {
131        perror("realloc");
132        exit(1);
133    }
134    line->s[len1] = ' ';
135    memcpy(line->s+len1+1, s, len2);
136    line->s[len1+len2+1] = 0;
137}
138
139
140void read_desc(FILE *file)
141{
142    struct line **anchor = NULL;
143    char buf[1100]; /* more than enough */
144    struct node *node;
145    char *p, *end;
146    int skip = 0, lineno = 0;
147
148    while (fgets(buf, sizeof(buf), file)) {
149        lineno++;
150        p = strchr(buf, '\n');
151        if (p)
152            *p = 0;
153        p = buf;
154        if (*buf && !isspace(*buf)) {
155            /* tag is ^.*?:\s */
156            while (1) {
157                p = strchr(p, ':');
158                if (!p) {
159                    fprintf(stderr, "no tag in line %d\n",
160                        lineno);
161                    exit(1);
162                }
163                if (!p[1] || isspace(p[1]))
164                    break;
165                p++;
166            }
167            *p++ = 0;
168            node = find_comp(tree, buf);
169            if (!node) {
170                fprintf(stderr,
171                    "component \"%s\" not found in line %d\n",
172                    buf, lineno);
173                skip = 1;
174                continue;
175            }
176            for (anchor = &node->comment; *anchor;
177                anchor = &(*anchor)->next);
178            skip = 0;
179        }
180        if (skip)
181            continue;
182
183        /* remove leading whitespace */
184        while (*p && isspace(*p))
185            p++;
186        if (!*p) {
187            if (*anchor)
188                anchor = &(*anchor)->next;
189            continue;
190        }
191
192        /* remove training whitespace */
193        end = strrchr(p, 0);
194        while (isspace(end[-1]))
195            end--;
196        *end = 0;
197
198        if (*anchor)
199            append_line(*anchor, p);
200        else
201            *anchor = new_line(p);
202    }
203}
204
205
206void set_libs(struct node *node,
207    const char *(*find_lib)(const char *sym, const struct name **names,
208    int *units))
209{
210    while (node) {
211        if (!node->child) {
212            node->lib =
213                find_lib(node->name, &node->names, &node->units);
214            if (!node->lib) {
215                fprintf(stderr, "symbol %s not found\n",
216                    node->name);
217                exit(1);
218            }
219        }
220        set_libs(node->child, find_lib);
221        node = node->next;
222    }
223}
224
225
226static void dump_tree_level(const struct node *tree, int level)
227{
228    const struct node *n;
229    const struct line *line;
230    const struct name *name;
231
232    for (n = tree; n; n = n->next) {
233        printf("%*s%s", 4*level, "", n->name);
234        if (n->lib) {
235            for (name = n->names; name; name = name->next)
236                printf("%s%s",
237                    name == n->names ? " (" : ", ", name->s);
238            printf(")");
239        }
240        printf("\n");
241        for (line = n->comment; line; line = line->next)
242            printf("%*s\"%s\"\n", 4*level+2, "", line->s);
243        dump_tree_level(n->child, level+1);
244    }
245}
246
247
248void dump_tree(void)
249{
250    dump_tree_level(tree, 0);
251}
252
253
254static void dump_comp_level(const struct node *tree)
255{
256    const struct node *n;
257
258    for (n = tree; n; n = n->next) {
259        if (n->lib)
260            printf("%s\n", n->names->s);
261        dump_comp_level(n->child);
262    }
263}
264
265
266void dump_comp(void)
267{
268    dump_comp_level(tree);
269}
genex/comp.h
1/*
2 * comp.h - Component hierarchy
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef COMP_H
13#define COMP_H
14
15#include "libs.h"
16
17
18struct line {
19    char *s;
20    struct line *next;
21};
22
23struct node {
24    const char *name;
25    const char *lib; /* NULL if intermediate node */
26    const struct name *names;
27                /* canonical name and aliases of component */
28    int units; /* number of units; undefined if intermediate */
29    struct line *comment; /* NULL if intermediate node */
30    int indent; /* level of indentation (characters) */
31    struct node *parent;
32    struct node *child;
33    struct node *next;
34};
35
36
37extern struct node *tree;
38
39
40void read_tree(FILE *file);
41void read_desc(FILE *file);
42void set_libs(struct node *node,
43    const char *(*find_lib)(const char *sym, const struct name **names,
44    int *units));
45void dump_tree(void);
46void dump_comp(void);
47
48#endif /* !COMP_H */
genex/expand-pintype
1#!/usr/bin/perl
2#
3# expand-pintype - Expand pin types of symbols in a Kicad library
4#
5# Copyright 2010, 2012 by Werner Almesberger
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12
13#
14# usage:
15#
16# expand-pintype input.lib
17# expand-pintype input.lib output.lib
18#
19
20
21$GAP = 50; # gap between pin and type, in mil
22$CHAR_WIDTH = 60; # default character width, in mil
23$NAME_WIDTH = 15; # name field width in ASCII mode, in characters
24
25
26%map = (
27    "I" => "Input",
28    "O" => "Output",
29    "B" => "BiDi",
30    "T" => "3-state",
31    "P" => "Passive",
32    "U" => "Unspec",
33    "W" => "Pwr In",
34    "w" => "Pwr Out",
35    "C" => "OC",
36    "E" => "OE",
37    "N" => "NC",
38);
39
40if (@ARGV < 2) {
41    $out = 0;
42} elsif (@ARGV == 2) {
43    $file = pop @ARGV;
44    $out = 1;
45    open(FILE, ">$file") || die "$file: $!";
46} else {
47    print STDERR "usage: expand-pintype input.lib [output.lib]\n";
48    exit(1);
49}
50
51while (<>) {
52    if ($out) {
53    # make name differ so that KiCad's cache doesn't get confused
54        s/^DEF\s+~?/$&X/;
55        s/^F1\s+"+/$&X/;
56        print FILE || die;
57    }
58    next unless /^X/;
59    @a = split(/\s+/);
60    ($name, $pin, $x, $y, $dir, $unit, $pt) = @a[1, 2, 3, 4, 6, 9, 11];
61    $type = $map{$pt};
62    $type = "???" unless defined $type;
63    if ($out) {
64        $off = $GAP+(length $type)*$CHAR_WIDTH/2;
65        if ($dir eq "U") {
66            ($a, $y) = (90, $y-$off);
67        } elsif ($dir eq "D") {
68            ($a, $y) = (90, $y+$off);
69        } elsif ($dir eq "R") {
70                ($a, $x) = (0, $x-$off);
71        } else {
72            ($a, $x) = (0, $x+$off);
73        }
74        $type =~ y/ /~/;
75        print FILE sprintf("T %d %d %d 60 0 %d 0 %s Normal 0\n",
76            $a*10, $x, $y, $unit, $type);
77    } else {
78        $s = "$name ($pin)";
79        $f = $NAME_WIDTH-length $s;
80        $f = "-" x ($f > 0 ? $f : 0);
81        print "$s $f $type\n";
82    }
83}
84if ($out) {
85    close FILE || die;
86}
genex/genex
1#!/bin/sh
2PATH=$PATH:.
3exec genex-bin "$@"
genex/genex.c
1/*
2 * genex.c - Generate expanded component view
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12
13#include <stdlib.h>
14#include <stdio.h>
15#include <unistd.h>
16#include <string.h>
17
18#include "comp.h"
19#include "libs.h"
20#include "pdf.h"
21#include "genex.h"
22
23
24int quiet = 0;
25
26
27static void usage(const char *name)
28{
29    fprintf(stderr,
30"usage: %s [-d|-D] [-p] [-P] [-q] [-L libdir ...] [-l lib ...] hierarchy\n"
31" %*s [descriptions ...]\n\n"
32" -d dump the tree instead of generating a PDF\n"
33" -D dump all the canonical component names (without aliases)\n"
34" -L libdir search all libraries in the specified directory\n"
35" -l lib search the specified component library\n"
36" -p use portrait orientation; default: landscape\n"
37" -P generate Postscript instead of PDF (mainly for debugging)\n"
38" -q don't show progress\n"
39    , name, (int) strlen(name), "");
40    exit(1);
41}
42
43
44int main(int argc, char **argv)
45{
46    FILE *file;
47    int c;
48    int opt_dump_tree = 0, opt_dump_comp = 0, postscript = 0, portrait = 0;
49    char **arg;
50
51    while ((c = getopt(argc, argv, "dDL:l:Ppq")) != EOF)
52        switch (c) {
53        case 'd':
54            opt_dump_tree = 1;
55            break;
56        case 'D':
57            opt_dump_comp = 1;
58            break;
59        case 'L':
60            add_libdir(optarg);
61            break;
62        case 'l':
63            add_lib(optarg);
64            break;
65        case 'P':
66            postscript = 1;
67            break;
68        case 'p':
69            portrait = 1;
70            break;
71        case 'q':
72            quiet = 1;
73            break;
74        default:
75            usage(*argv);
76        }
77
78    if (opt_dump_tree && opt_dump_comp)
79        usage(*argv);
80
81    switch (argc-optind) {
82    case 1:
83    case 2:
84        break;
85    default:
86        usage(*argv);
87    }
88
89    file = fopen(argv[optind], "r");
90    if (!file) {
91        perror(argv[optind]);
92        exit(1);
93    }
94    read_tree(file);
95    fclose(file);
96    set_libs(tree, lookup_sym);
97
98    for (arg = argv+optind+1; *arg; arg++) {
99        file = fopen(*arg, "r");
100        if (!file) {
101            perror(*arg);
102            exit(1);
103        }
104        read_desc(file);
105        fclose(file);
106    }
107    if (opt_dump_tree)
108        dump_tree();
109    else if (opt_dump_comp)
110        dump_comp();
111    else
112        make_pdf(!postscript, portrait);
113    return 0;
114}
genex/genex.h
1/*
2 * genex.h - Generate expanded component view
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef GENEX_H
13#define GENEX_H
14
15extern int quiet;
16
17#endif /* !GENEX_H */
genex/libs.c
1/*
2 * libs.c - Component libraries
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#define _GNU_SOURCE /* for strcasecmp */
13#include <stdlib.h>
14#include <stdio.h>
15#include <ctype.h>
16#include <string.h>
17#include <sys/types.h>
18#include <dirent.h>
19
20#include "util.h"
21#include "libs.h"
22
23
24struct entry {
25    struct name *names;
26    int units;
27    struct entry *next;
28};
29
30static struct lib {
31    const char *path;
32    struct entry *comps;
33    struct lib *next;
34} *libs = NULL;
35
36
37const char *lookup_sym(const char *name, const struct name **names, int *units)
38{
39    const struct lib *lib;
40    const struct entry *e;
41
42    for (lib = libs; lib; lib = lib->next)
43        for (e = lib->comps; e; e = e->next)
44            if (!strcasecmp(e->names->s, name)) {
45                if (names)
46                    *names = e->names;
47                if (units)
48                    *units = e->units;
49                return lib->path;
50            }
51    return NULL;
52}
53
54
55static const char *field(const char *s, int n)
56{
57    while (n-- && *s) {
58        while (*s && !isspace(*s))
59            s++;
60        while (*s && isspace(*s))
61            s++;
62    }
63    return *s ? s : NULL;
64}
65
66
67static void add_name(struct entry *e, char *s)
68{
69    char *nl;
70    struct name **p;
71
72    nl = strchr(s, '\n');
73    if (nl)
74        *nl = 0;
75    for (p = &e->names; *p; p = &(*p)->next);
76    *p = alloc_type(struct name);
77    (*p)->s = stralloc(s);
78    (*p)->next = NULL;
79}
80
81
82void add_lib(const char *path)
83{
84    FILE *file;
85    struct lib *lib;
86    struct entry *e = NULL;
87    char buf[1024]; /* @@@ */
88    char *name, *spc;
89    const char *s;
90
91    file = fopen(path, "r");
92    if (!file) {
93        perror(path);
94        exit(1);
95    }
96
97    lib = alloc_type(struct lib);
98    lib->path = stralloc(path);
99    lib->comps = NULL;
100    lib->next = libs;
101    libs = lib;
102
103    while (fgets(buf, sizeof(buf), file)) {
104        if (!strncmp(buf, "ALIAS ", 6) && e)
105            add_name(e, buf+6);
106        if (strncmp(buf, "DEF ", 4))
107            continue;
108        s = field(buf, 7);
109        if (!s) {
110            fprintf(stderr, "DEF record lacks units field in %s\n",
111                 path);
112            exit(1);
113        }
114        name = buf+4;
115        if (*name == '~')
116            name++;
117        spc = strchr(name, ' ');
118        if (!spc) {
119            fprintf(stderr, "invalid DEF line in %s\n", path);
120            exit(1);
121        }
122        *spc = 0;
123        e = alloc_type(struct entry);
124        e->names = NULL;
125        add_name(e, name);
126        e->units = atoi(s);
127        if (!e->units) {
128            fprintf(stderr, "invalid number of units in %s\n",
129                path);
130            exit(1);
131        }
132        e->next = lib->comps;
133        lib->comps = e;
134    }
135
136    fclose(file);
137}
138
139
140void add_libdir(const char *path)
141{
142    DIR *dir;
143    const struct dirent *de;
144    size_t len;
145    char *tmp;
146
147    dir = opendir(path);
148    if (!dir) {
149        perror(path);
150        exit(1);
151    }
152    while (1) {
153        de = readdir(dir);
154        if (!de)
155            break;
156        len = strlen(de->d_name);
157        if (len < 4)
158            continue;
159        if (strcmp(de->d_name+len-4, ".lib"))
160            continue;
161        if (asprintf(&tmp, "%s/%s", path, de->d_name) < 0) {
162            perror("asprintf");
163            exit(1);
164        }
165        add_lib(tmp);
166    }
167    closedir(dir);
168}
genex/libs.h
1/*
2 * libs.h - Component libraries
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef LIBS_H
13#define LIBS_H
14
15struct name {
16    const char *s;
17    struct name *next;
18};
19
20const char *lookup_sym(const char *name, const struct name **names, int *units);
21void add_lib(const char *path);
22void add_libdir(const char *path);
23
24#endif /* !LIBS_H */
genex/mkgenex-wrapper
1#!/bin/sh -e
2#
3# mkgenex-wrapper - Generate wrapper script for genex
4#
5# Copyright 2012 by Werner Almesberger
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12
13
14MODE=555
15DIR=
16
17usage()
18{
19    echo "usage: $0 [-m mode] [-p directory] wrapper-path" 1>&2
20    exit 1
21}
22
23
24while [ "$1" ]; do
25    case "$1" in
26    -m) shift
27        MODE=$1;;
28    -p) shift
29        DIR=$1;;
30    -*) usage;;
31    *) break;;
32    esac
33    shift
34done
35
36: ${DIR:=`dirname $1`}
37
38[ -d "$DIR" ] && [ "$1" ] && [ -z "$2" ] || usage
39
40trap "rm -f _wrapper" 0
41
42cat <<EOF >_wrapper
43#!/bin/sh
44PATH=\$PATH:$DIR
45exec genex-bin "\$@"
46EOF
47chmod $MODE _wrapper
48
49mv _wrapper "$1"
genex/pdf.c
1/*
2 * pdf.c - Generate PDF
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#define _GNU_SOURCE
13#include <stdlib.h>
14#include <stdio.h>
15#include <sys/types.h>
16
17#include "genex.h"
18#include "comp.h"
19#include "pdf.h"
20
21
22static struct format {
23    const char *file_setup;
24    const char *overlay_setup;
25    const char *comp_setup;
26    int left;
27    struct text {
28        const char *font;
29        int size;
30        int y;
31    } name, path, lib, comment;
32    int comment_line_skip;
33} landscape = {
34    .file_setup = "%%Orientation: Landscape",
35    .overlay_setup = "90 rotate",
36    .comp_setup = "",
37    .left = 20,
38    .name = { "Helvetica-Bold", 24, 57 },
39    .path = { "Helvetica-Bold", 18, 30 },
40    .lib = { "Courier", 12, 75 },
41    .comment = { "Helvetica", 12, 600 },
42    .comment_line_skip = 14,
43}, portrait = {
44    .file_setup = "%%Orientation: Portrait",
45    .overlay_setup = "0 790 translate",
46    .comp_setup = "-120 700 translate -90 rotate",
47    .left = 20,
48    .name = { "Helvetica-Bold", 24, 57 },
49    .path = { "Helvetica-Bold", 18, 30 },
50    .lib = { "Courier", 12, 75 },
51    .comment = { "Helvetica", 12, 740 },
52    .comment_line_skip = 14,
53}, format;
54
55static int total, done = 0;
56
57
58static int children(const struct node *node)
59{
60    int n = 0;
61
62    while (node) {
63        n++;
64        node = node->next;
65    }
66    return n;
67}
68
69
70static void ps_string(FILE *file, const char *s)
71{
72    fputc('(', file);
73    while (*s) {
74        if (*s == '(' || *s == ')' || *s == '\\')
75            fputc('\\', file);
76        fputc(*s, file);
77        s++;
78    }
79    fputc(')', file);
80}
81
82
83static void print_path(FILE *file, const struct node *node)
84{
85    if (node->parent) {
86        print_path(file, node->parent);
87        fprintf(file, "( > ) show\n");
88    }
89    ps_string(file, node->name);
90    fprintf(file, " 0.5 setgray show 0 setgray\n");
91}
92
93
94static void make_title(FILE *file, const struct node *node, int unit)
95{
96    const struct name *name;
97
98    fprintf(file, "gsave %s 0 setgray\n", format.overlay_setup);
99
100    fprintf(file, "/%s findfont %d scalefont setfont\n",
101        format.name.font, format.name.size);
102    fprintf(file, "%d %d moveto\n", format.left, -format.name.y);
103    for (name = node->names; name; name = name->next) {
104        if (name != node->names)
105            fprintf(file, "(, ) show 0.5 setgray\n");
106        ps_string(file, name->s);
107        fprintf(file, " show\n");
108    }
109    fprintf(file, "0 setgray\n");
110    if (node->units > 1)
111        fprintf(file, " ( \\(%c\\)) show\n", 'A'+unit);
112
113    fprintf(file, "/%s findfont %d scalefont setfont\n",
114        format.path.font, format.path.size);
115    fprintf(file, "%d %d moveto\n", format.left, -format.path.y);
116    print_path(file, node);
117
118    fprintf(file, "/%s findfont %d scalefont setfont\n",
119        format.lib.font, format.lib.size);
120    fprintf(file, "%d %d moveto\n", format.left, -format.lib.y);
121    ps_string(file, node->lib);
122    fprintf(file, " show\n");
123
124    fprintf(file, "grestore\n");
125}
126
127
128static void print_comment(FILE *file, const struct line *comment)
129{
130    const struct line *line;
131    int lines = 0;
132    int n;
133
134    fprintf(file, "gsave %s 0 setgray\n", format.overlay_setup);
135    fprintf(file, "/%s findfont %d scalefont setfont\n",
136        format.comment.font, format.comment.size);
137    for (line = comment; line; line = line->next)
138        lines++;
139    n = 0;
140    for (line = comment; line; line = line->next) {
141        n++;
142        fprintf(file, "%d -%d moveto\n", format.left,
143            format.comment.y+(n-lines)*format.comment_line_skip);
144        ps_string(file, line->s);
145        fprintf(file, " show\n");
146    }
147    fprintf(file, "grestore\n");
148}
149
150
151static void cat(FILE *out, const char *name)
152{
153    FILE *in;
154    char buf[10000]; /* pick any good size */
155    size_t got, wrote;
156
157    in = fopen(name, "r");
158    if (!in) {
159        perror(name);
160        exit(1);
161    }
162    while (1) {
163        got = fread(buf, 1, sizeof(buf), in);
164        if (!got)
165            break;
166        wrote = fwrite(buf, 1, got, out);
167        if (wrote != got) {
168            perror("fwrite");
169            exit(1);
170        }
171    }
172    if (ferror(in)) {
173        perror(name);
174        exit(1);
175    }
176    fclose(in);
177}
178
179
180static void convert_comp(const struct node *node, FILE *out)
181{
182    char *tmp;
183    int i, res;
184
185    for (i = 0; i != node->units; i++) {
186        if (!quiet) {
187            fprintf(stderr, "\r%u/%u", ++done, total);
188            fflush(stderr);
189        }
190        make_title(out, node, i);
191        if (!i && node->comment)
192            print_comment(out, node->comment);
193        if (asprintf(&tmp, "sym2xps '%s' '%s' %d '%s' '%s'",
194            node->lib, node->names->s, i+1, "tmp", "tmp.ps") < 0) {
195            perror("asprintf");
196            exit(1);
197        }
198        res = system(tmp);
199        if (res < 0) {
200            perror("system");
201            exit(1);
202        }
203        if (res) {
204            fprintf(stderr, "sym2xps returned %d\n", res);
205            exit(1);
206        }
207        fprintf(out, "gsave %s\n", format.comp_setup);
208        cat(out, "tmp.ps");
209        fprintf(out, "\ngrestore\n");
210    }
211}
212
213
214static void convert_tree(const struct node *node, FILE *out)
215{
216    while (node) {
217        fprintf(out, "[ /Title (%s) /Count %d /OUT pdfmark\n",
218            node->name, -children(node->child));
219        if (node->child)
220            convert_tree(node->child, out);
221        else
222            convert_comp(node, out);
223        node = node->next;
224    }
225}
226
227
228static int count_tree(const struct node *node)
229{
230    int sum = 0;
231
232    while (node) {
233        if (node->child)
234            sum += count_tree(node->child);
235        else
236            sum += node->units;
237        node = node->next;
238    }
239    return sum;
240}
241
242
243void make_pdf(int pdf, int use_portrait)
244{
245    FILE *out;
246    int res;
247
248    if (use_portrait)
249        format = portrait;
250    else
251        format = landscape;
252    if (pdf)
253        out = popen(
254            "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=- "
255              "-f -", "w");
256    else
257        out = popen("cat", "w");
258    if (!out) {
259        perror("gs");
260        exit(1);
261    }
262    fprintf(out, "%%!PS\n%s\n", format.file_setup);
263    total = count_tree(tree);
264    convert_tree(tree, out);
265    if (!quiet)
266        fprintf(stderr, "\rFinishing\n");
267    res = pclose(out);
268    if (res < 0) {
269        perror("pclose");
270        exit(1);
271    }
272    if (res) {
273        fprintf(stderr, "exit status %d\n", res);
274        exit(1);
275    }
276}
genex/pdf.h
1/*
2 * pdf.h - Generate PDF
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef PDF_H
13#define PDF_H
14
15void make_pdf(int pdf, int use_portrait);
16
17#endif /* !PDF_H */
genex/run
1#!/bin/sh
2# Hack: ps2pdf is happy with the PS generate, but if we invoke gs diretctly,
3# isn't. Some voodoo is still missing ...
4./genex -p \
5    -L /home/qi/kicad-libs/components \
6    /home/qi/kicad-libs/components/EXPAND DESC >out.pdf
genex/sym2xps
1#!/bin/sh -e
2#
3# sym2xps - Convert a symbol from a Kicad library to Postscript with expanded
4# pin types
5#
6# Copyright 2012 by Werner Almesberger
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#
13
14
15usage()
16{
17    echo "usage: $0 library symbol unit tmpdir outfile" 1>&2
18    exit 1
19}
20
21
22lib=$1
23sym=$2
24unit=$3
25tmp=$4
26out=$5
27
28[ "$lib" ] && [ "$sym" ] && [ "$unit" ] && [ "$tmp" ] && [ "$out" ] || usage
29
30[ -r "$lib" ] || {
31    echo "$lib: not found" 1>&2
32    exit 1
33}
34
35grep "^DEF $sym " "$lib" >/dev/null || grep "^DEF ~$sym " "$lib" >/dev/null || {
36    echo "\"$sym\" not found in $lib" 1>&2
37    exit 1
38}
39
40[ "${tmp#/}" = "$tmp" ] && tmp=`pwd`/$tmp
41[ "${out#/}" = "$out" ] && out=`pwd`/$out
42
43mkdir "$tmp"
44
45trap "rm -rf '$tmp'" 0
46
47expand-pintype "$lib" "$tmp"/tmp.lib
48
49cat <<EOF >"$tmp"/tmp.pro
50[eeschema]
51version=1
52[eeschema/libraries]
53LibName1=./tmp
54EOF
55
56X=6000
57Y=4000
58
59sed "\@^DEF $sym @,/^ENDDEF/p;d" "$lib" |
60  awk '/^F. / { if ($1 == "F0") sub(/"$/, "?\"", $2);
61    print substr($1, 1, 1), substr($1, 2, 1), $2,
62    $6, '$X'+$3, '$Y'+$4, $5, " 0000", $8, $9 }' >"$tmp"/fx.tmp
63#F field_number "text" orientation posX posY size Flags (see below)
64#F0 reference posx posy text_size text_orient visibile htext_justify vtext_justify
65
66cat <<EOF >"$tmp"/tmp.sch
67EESchema Schematic File Version 2 date Mon Mar 26 09:29:33 2012
68LIBS:dummy
69EELAYER 43 0
70EELAYER END
71\$Comp
72L X$sym ??
73U $unit 1 00000000
74P $X $Y
75`cat "$tmp"/fx.tmp`
76    $unit $X $Y
77    1 0 0 -1
78\$EndComp
79\$EndSCHEMATC
80EOF
81
82cd "$tmp"
83eeschema --plot=ps "$tmp/tmp.sch"
84mv tmp.ps "$out"
genex/util.h
1/*
2 * util.h - Utility functions
3 *
4 * Copyright 2012 by Werner Almesberger
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 */
11
12#ifndef UTIL_H
13#define UTIL_H
14
15#include <stdlib.h>
16#include <string.h>
17
18
19#define alloc_size(s) \
20    ({ void *alloc_size_tmp = malloc(s); \
21    if (!alloc_size_tmp) \
22        abort(); \
23    alloc_size_tmp; })
24
25#define alloc_type(t) ((t *) alloc_size(sizeof(t)))
26
27
28static inline char *stralloc(const char *s)
29{
30    char *t;
31
32    t = strdup(s);
33    if (t)
34        return t;
35    perror("strdup");
36    exit(1);
37}
38
39#endif /* !UTIL_H */

Archive Download the corresponding diff file

Branches:
master



interactive