1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2025-04-21 12:27:27 +03:00

genex/: renamed genex to gencat

This commit is contained in:
Werner Almesberger
2012-06-25 21:04:59 -03:00
parent 2800fa93a5
commit e832845a02
16 changed files with 24 additions and 24 deletions

8
gencat/DESC Normal file
View File

@@ -0,0 +1,8 @@
wm9707scft/v: This is a comment.
Continuation of the same line.
Here we have a line break,
and so on
wm9707scft/v: Another comment
for the same component.
WM9707SCFT/V: Component names in comments are case-insensitive.

77
gencat/Makefile Normal file
View File

@@ -0,0 +1,77 @@
#
# Makefile - Expanded component view generator
#
# 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.
#
PREFIX ?= /usr/local
OBJS = gencat.o comp.o libs.o pdf.o
SHELL = /bin/bash
CFLAGS = -Wall -g
CC_normal := $(CC)
DEPEND_normal := $(CPP) $(CFLAGS) -MM -MG
CC_quiet = @echo " CC " $@ && $(CC_normal)
GEN_quiet = @echo " GENERATE " $@ &&
DEPEND_quiet = @$(DEPEND_normal)
ifeq ($(V),1)
CC = $(CC_normal)
GEN =
DEPEND = $(DEPEND_normal)
else
CC = $(CC_quiet)
GEN = $(GEN_quiet)
DEPEND = $(DEPEND_quiet)
endif
.PHONY: all clean spotless install uninstall
all: gencat-bin
gencat-bin: $(OBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LDLIBS)
%.o: %.c
$(CC) -c $(CFLAGS) $*.c -o $*.o
$(DEPEND) $*.c | \
sed -e \
'/^\(.*:\)\? */{p;s///;s/ *\\\?$$/ /;s/ */:\n/g;H;}' \
-e '$${g;p;}' -e d >$*.d; \
[ "$${PIPESTATUS[*]}" = "0 0" ] || { rm -f $*.d; exit 1; }
-include $(OBJS:.o=.d)
clean:
rm -f $(OBJS) $(OBJS:.o=.d)
spotless: clean
rm -f gencat-bin
#
# Note: we use .../lib/gencat/ instead of .../libexec/gencat/ because FHS-3.0
# does not define libexec under the /usr/local/ hierarchy. (And older versions
# of FHS don't define libexec at all.)
#
install: all
mkdir -p $(DESTDIR)/$(PREFIX)/bin
mkdir -p $(DESTDIR)/$(PREFIX)/lib/gencat
./mkgencat-wrapper -m 755 -p $(DESTDIR)/$(PREFIX)/lib/gencat/ \
$(DESTDIR)/$(PREFIX)/bin/gencat
install -m 755 gencat-bin $(DESTDIR)/$(PREFIX)/lib/gencat/
install -m 755 sym2xps $(DESTDIR)/$(PREFIX)/lib/gencat/
install -m 755 expand-pintype $(DESTDIR)/$(PREFIX)/lib/gencat/
uninstall:
rm -f $(DESTDIR)/$(PREFIX)/bin/gencat
rm -rf $(DESTDIR)/$(PREFIX)/lib/gencat

269
gencat/comp.c Normal file
View File

@@ -0,0 +1,269 @@
/*
* comp.c - Component hierarchy
*
* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "util.h"
#include "comp.h"
struct node *tree = NULL;
void read_tree(FILE *file)
{
char buf[1100]; /* more than enough */
struct node *last = NULL, *node;
int depth = -1;
const char *s, *p, *e;
char *name;
int n;
next:
while (fgets(buf, sizeof(buf), file)) {
n = 0;
s = buf;
while (1) {
switch (*s++) {
case ' ':
n++;
continue;
case '\t':
n = (n+8) & ~7;
continue;
case 0:
case '#':
goto next;
default:
break;
}
break;
}
for (p = e = --s; *p && *p != '#' && *p != '\n'; p++)
if (*p != ' ' && *p != '\t')
e = p;
if (!last && n) {
fprintf(stderr, "first entry must not be intended\n");
exit(1);
}
name = malloc(e-s+2);
if (!name) {
perror("malloc");
exit(1);
}
memcpy(name, s, e-s+1);
name[e-s+1] = 0;
node = alloc_type(struct node);
node->name = name;
node->lib = NULL;
node->comment = NULL;
node->indent = n;
node->child = node->next = NULL;
if (n > depth) {
if (last)
last->child = node;
else
tree = node;
node->parent = last;
} else {
while (last && last->indent != n)
last = last->parent;
if (!last && n) {
fprintf(stderr, "indentation error\n");
exit(1);
}
last->next = node;
node->parent = last->parent;
}
last = node;
depth = n;
}
}
static struct node *find_comp(struct node *node, const char *name)
{
struct node *found;
while (node) {
if (!strcasecmp(node->name, name))
return node;
found = find_comp(node->child, name);
if (found)
return found;
node = node->next;
}
return NULL;
}
static struct line *new_line(char *s)
{
struct line *line;
line = alloc_type(struct line);
line->s = stralloc(s);
line->next = NULL;
return line;
}
static void append_line(struct line *line, char *s)
{
int len1, len2;
len1 = strlen(line->s);
len2 = strlen(s);
line->s = realloc(line->s, len1+len2+1+1); /* separating space */
if (!line->s) {
perror("realloc");
exit(1);
}
line->s[len1] = ' ';
memcpy(line->s+len1+1, s, len2);
line->s[len1+len2+1] = 0;
}
void read_desc(FILE *file)
{
struct line **anchor = NULL;
char buf[1100]; /* more than enough */
struct node *node;
char *p, *end;
int skip = 0, lineno = 0;
while (fgets(buf, sizeof(buf), file)) {
lineno++;
p = strchr(buf, '\n');
if (p)
*p = 0;
p = buf;
if (*buf && !isspace(*buf)) {
/* tag is ^.*?:\s */
while (1) {
p = strchr(p, ':');
if (!p) {
fprintf(stderr, "no tag in line %d\n",
lineno);
exit(1);
}
if (!p[1] || isspace(p[1]))
break;
p++;
}
*p++ = 0;
node = find_comp(tree, buf);
if (!node) {
fprintf(stderr,
"component \"%s\" not found in line %d\n",
buf, lineno);
skip = 1;
continue;
}
for (anchor = &node->comment; *anchor;
anchor = &(*anchor)->next);
skip = 0;
}
if (skip)
continue;
/* remove leading whitespace */
while (*p && isspace(*p))
p++;
if (!*p) {
if (*anchor)
anchor = &(*anchor)->next;
continue;
}
/* remove training whitespace */
end = strrchr(p, 0);
while (isspace(end[-1]))
end--;
*end = 0;
if (*anchor)
append_line(*anchor, p);
else
*anchor = new_line(p);
}
}
void set_libs(struct node *node,
const char *(*find_lib)(const char *sym, const struct name **names,
int *units))
{
while (node) {
if (!node->child) {
node->lib =
find_lib(node->name, &node->names, &node->units);
if (!node->lib) {
fprintf(stderr, "symbol %s not found\n",
node->name);
exit(1);
}
}
set_libs(node->child, find_lib);
node = node->next;
}
}
static void dump_tree_level(const struct node *tree, int level)
{
const struct node *n;
const struct line *line;
const struct name *name;
for (n = tree; n; n = n->next) {
printf("%*s%s", 4*level, "", n->name);
if (n->lib) {
for (name = n->names; name; name = name->next)
printf("%s%s",
name == n->names ? " (" : ", ", name->s);
printf(")");
}
printf("\n");
for (line = n->comment; line; line = line->next)
printf("%*s\"%s\"\n", 4*level+2, "", line->s);
dump_tree_level(n->child, level+1);
}
}
void dump_tree(void)
{
dump_tree_level(tree, 0);
}
static void dump_comp_level(const struct node *tree)
{
const struct node *n;
for (n = tree; n; n = n->next) {
if (n->lib)
printf("%s\n", n->names->s);
dump_comp_level(n->child);
}
}
void dump_comp(void)
{
dump_comp_level(tree);
}

48
gencat/comp.h Normal file
View File

@@ -0,0 +1,48 @@
/*
* comp.h - Component hierarchy
*
* 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.
*/
#ifndef COMP_H
#define COMP_H
#include "libs.h"
struct line {
char *s;
struct line *next;
};
struct node {
const char *name;
const char *lib; /* NULL if intermediate node */
const struct name *names;
/* canonical name and aliases of component */
int units; /* number of units; undefined if intermediate */
struct line *comment; /* NULL if intermediate node */
int indent; /* level of indentation (characters) */
struct node *parent;
struct node *child;
struct node *next;
};
extern struct node *tree;
void read_tree(FILE *file);
void read_desc(FILE *file);
void set_libs(struct node *node,
const char *(*find_lib)(const char *sym, const struct name **names,
int *units));
void dump_tree(void);
void dump_comp(void);
#endif /* !COMP_H */

86
gencat/expand-pintype Executable file
View File

@@ -0,0 +1,86 @@
#!/usr/bin/perl
#
# expand-pintype - Expand pin types of symbols in a Kicad library
#
# Copyright 2010, 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.
#
#
# usage:
#
# expand-pintype input.lib
# expand-pintype input.lib output.lib
#
$GAP = 50; # gap between pin and type, in mil
$CHAR_WIDTH = 60; # default character width, in mil
$NAME_WIDTH = 15; # name field width in ASCII mode, in characters
%map = (
"I" => "Input",
"O" => "Output",
"B" => "BiDi",
"T" => "3-state",
"P" => "Passive",
"U" => "Unspec",
"W" => "Pwr In",
"w" => "Pwr Out",
"C" => "OC",
"E" => "OE",
"N" => "NC",
);
if (@ARGV < 2) {
$out = 0;
} elsif (@ARGV == 2) {
$file = pop @ARGV;
$out = 1;
open(FILE, ">$file") || die "$file: $!";
} else {
print STDERR "usage: expand-pintype input.lib [output.lib]\n";
exit(1);
}
while (<>) {
if ($out) {
# make name differ so that KiCad's cache doesn't get confused
s/^DEF\s+~?/$&X/;
s/^F1\s+"+/$&X/;
print FILE || die;
}
next unless /^X/;
@a = split(/\s+/);
($name, $pin, $x, $y, $dir, $unit, $pt) = @a[1, 2, 3, 4, 6, 9, 11];
$type = $map{$pt};
$type = "???" unless defined $type;
if ($out) {
$off = $GAP+(length $type)*$CHAR_WIDTH/2;
if ($dir eq "U") {
($a, $y) = (90, $y-$off);
} elsif ($dir eq "D") {
($a, $y) = (90, $y+$off);
} elsif ($dir eq "R") {
($a, $x) = (0, $x-$off);
} else {
($a, $x) = (0, $x+$off);
}
$type =~ y/ /~/;
print FILE sprintf("T %d %d %d 60 0 %d 0 %s Normal 0\n",
$a*10, $x, $y, $unit, $type);
} else {
$s = "$name ($pin)";
$f = $NAME_WIDTH-length $s;
$f = "-" x ($f > 0 ? $f : 0);
print "$s $f $type\n";
}
}
if ($out) {
close FILE || die;
}

3
gencat/gencat Executable file
View File

@@ -0,0 +1,3 @@
#!/bin/sh
PATH=$PATH:.
exec gencat-bin "$@"

114
gencat/gencat.c Normal file
View File

@@ -0,0 +1,114 @@
/*
* gencat.c - Generate expanded component view
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include "comp.h"
#include "libs.h"
#include "pdf.h"
#include "gencat.h"
int quiet = 0;
static void usage(const char *name)
{
fprintf(stderr,
"usage: %s [-d|-D] [-p] [-P] [-q] [-L libdir ...] [-l lib ...] hierarchy\n"
" %*s [descriptions ...]\n\n"
" -d dump the tree instead of generating a PDF\n"
" -D dump all the canonical component names (without aliases)\n"
" -L libdir search all libraries in the specified directory\n"
" -l lib search the specified component library\n"
" -p use portrait orientation; default: landscape\n"
" -P generate Postscript instead of PDF (mainly for debugging)\n"
" -q don't show progress\n"
, name, (int) strlen(name), "");
exit(1);
}
int main(int argc, char **argv)
{
FILE *file;
int c;
int opt_dump_tree = 0, opt_dump_comp = 0, postscript = 0, portrait = 0;
char **arg;
while ((c = getopt(argc, argv, "dDL:l:Ppq")) != EOF)
switch (c) {
case 'd':
opt_dump_tree = 1;
break;
case 'D':
opt_dump_comp = 1;
break;
case 'L':
add_libdir(optarg);
break;
case 'l':
add_lib(optarg);
break;
case 'P':
postscript = 1;
break;
case 'p':
portrait = 1;
break;
case 'q':
quiet = 1;
break;
default:
usage(*argv);
}
if (opt_dump_tree && opt_dump_comp)
usage(*argv);
switch (argc-optind) {
case 1:
case 2:
break;
default:
usage(*argv);
}
file = fopen(argv[optind], "r");
if (!file) {
perror(argv[optind]);
exit(1);
}
read_tree(file);
fclose(file);
set_libs(tree, lookup_sym);
for (arg = argv+optind+1; *arg; arg++) {
file = fopen(*arg, "r");
if (!file) {
perror(*arg);
exit(1);
}
read_desc(file);
fclose(file);
}
if (opt_dump_tree)
dump_tree();
else if (opt_dump_comp)
dump_comp();
else
make_pdf(!postscript, portrait);
return 0;
}

17
gencat/gencat.h Normal file
View File

@@ -0,0 +1,17 @@
/*
* gencat.h - Generate expanded component view
*
* 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.
*/
#ifndef GENCAT_H
#define GENCAT_H
extern int quiet;
#endif /* !GENCAT_H */

168
gencat/libs.c Normal file
View File

@@ -0,0 +1,168 @@
/*
* 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 <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#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);
}

24
gencat/libs.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* libs.h - 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.
*/
#ifndef LIBS_H
#define LIBS_H
struct name {
const char *s;
struct name *next;
};
const char *lookup_sym(const char *name, const struct name **names, int *units);
void add_lib(const char *path);
void add_libdir(const char *path);
#endif /* !LIBS_H */

49
gencat/mkgencat-wrapper Executable file
View File

@@ -0,0 +1,49 @@
#!/bin/sh -e
#
# mkgencat-wrapper - Generate wrapper script for gencat
#
# 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.
#
MODE=555
DIR=
usage()
{
echo "usage: $0 [-m mode] [-p directory] wrapper-path" 1>&2
exit 1
}
while [ "$1" ]; do
case "$1" in
-m) shift
MODE=$1;;
-p) shift
DIR=$1;;
-*) usage;;
*) break;;
esac
shift
done
: ${DIR:=`dirname $1`}
[ -d "$DIR" ] && [ "$1" ] && [ -z "$2" ] || usage
trap "rm -f _wrapper" 0
cat <<EOF >_wrapper
#!/bin/sh
PATH=\$PATH:$DIR
exec gencat-bin "\$@"
EOF
chmod $MODE _wrapper
mv _wrapper "$1"

276
gencat/pdf.c Normal file
View File

@@ -0,0 +1,276 @@
/*
* pdf.c - Generate PDF
*
* 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
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include "gencat.h"
#include "comp.h"
#include "pdf.h"
static struct format {
const char *file_setup;
const char *overlay_setup;
const char *comp_setup;
int left;
struct text {
const char *font;
int size;
int y;
} name, path, lib, comment;
int comment_line_skip;
} landscape = {
.file_setup = "%%Orientation: Landscape",
.overlay_setup = "90 rotate",
.comp_setup = "",
.left = 20,
.name = { "Helvetica-Bold", 24, 57 },
.path = { "Helvetica-Bold", 18, 30 },
.lib = { "Courier", 12, 75 },
.comment = { "Helvetica", 12, 600 },
.comment_line_skip = 14,
}, portrait = {
.file_setup = "%%Orientation: Portrait",
.overlay_setup = "0 790 translate",
.comp_setup = "-120 700 translate -90 rotate",
.left = 20,
.name = { "Helvetica-Bold", 24, 57 },
.path = { "Helvetica-Bold", 18, 30 },
.lib = { "Courier", 12, 75 },
.comment = { "Helvetica", 12, 740 },
.comment_line_skip = 14,
}, format;
static int total, done = 0;
static int children(const struct node *node)
{
int n = 0;
while (node) {
n++;
node = node->next;
}
return n;
}
static void ps_string(FILE *file, const char *s)
{
fputc('(', file);
while (*s) {
if (*s == '(' || *s == ')' || *s == '\\')
fputc('\\', file);
fputc(*s, file);
s++;
}
fputc(')', file);
}
static void print_path(FILE *file, const struct node *node)
{
if (node->parent) {
print_path(file, node->parent);
fprintf(file, "( > ) show\n");
}
ps_string(file, node->name);
fprintf(file, " 0.5 setgray show 0 setgray\n");
}
static void make_title(FILE *file, const struct node *node, int unit)
{
const struct name *name;
fprintf(file, "gsave %s 0 setgray\n", format.overlay_setup);
fprintf(file, "/%s findfont %d scalefont setfont\n",
format.name.font, format.name.size);
fprintf(file, "%d %d moveto\n", format.left, -format.name.y);
for (name = node->names; name; name = name->next) {
if (name != node->names)
fprintf(file, "(, ) show 0.5 setgray\n");
ps_string(file, name->s);
fprintf(file, " show\n");
}
fprintf(file, "0 setgray\n");
if (node->units > 1)
fprintf(file, " ( \\(%c\\)) show\n", 'A'+unit);
fprintf(file, "/%s findfont %d scalefont setfont\n",
format.path.font, format.path.size);
fprintf(file, "%d %d moveto\n", format.left, -format.path.y);
print_path(file, node);
fprintf(file, "/%s findfont %d scalefont setfont\n",
format.lib.font, format.lib.size);
fprintf(file, "%d %d moveto\n", format.left, -format.lib.y);
ps_string(file, node->lib);
fprintf(file, " show\n");
fprintf(file, "grestore\n");
}
static void print_comment(FILE *file, const struct line *comment)
{
const struct line *line;
int lines = 0;
int n;
fprintf(file, "gsave %s 0 setgray\n", format.overlay_setup);
fprintf(file, "/%s findfont %d scalefont setfont\n",
format.comment.font, format.comment.size);
for (line = comment; line; line = line->next)
lines++;
n = 0;
for (line = comment; line; line = line->next) {
n++;
fprintf(file, "%d -%d moveto\n", format.left,
format.comment.y+(n-lines)*format.comment_line_skip);
ps_string(file, line->s);
fprintf(file, " show\n");
}
fprintf(file, "grestore\n");
}
static void cat(FILE *out, const char *name)
{
FILE *in;
char buf[10000]; /* pick any good size */
size_t got, wrote;
in = fopen(name, "r");
if (!in) {
perror(name);
exit(1);
}
while (1) {
got = fread(buf, 1, sizeof(buf), in);
if (!got)
break;
wrote = fwrite(buf, 1, got, out);
if (wrote != got) {
perror("fwrite");
exit(1);
}
}
if (ferror(in)) {
perror(name);
exit(1);
}
fclose(in);
}
static void convert_comp(const struct node *node, FILE *out)
{
char *tmp;
int i, res;
for (i = 0; i != node->units; i++) {
if (!quiet) {
fprintf(stderr, "\r%u/%u", ++done, total);
fflush(stderr);
}
make_title(out, node, i);
if (!i && node->comment)
print_comment(out, node->comment);
if (asprintf(&tmp, "sym2xps '%s' '%s' %d '%s' '%s'",
node->lib, node->names->s, i+1, "tmp", "tmp.ps") < 0) {
perror("asprintf");
exit(1);
}
res = system(tmp);
if (res < 0) {
perror("system");
exit(1);
}
if (res) {
fprintf(stderr, "sym2xps returned %d\n", res);
exit(1);
}
fprintf(out, "gsave %s\n", format.comp_setup);
cat(out, "tmp.ps");
fprintf(out, "\ngrestore\n");
}
}
static void convert_tree(const struct node *node, FILE *out)
{
while (node) {
fprintf(out, "[ /Title (%s) /Count %d /OUT pdfmark\n",
node->name, -children(node->child));
if (node->child)
convert_tree(node->child, out);
else
convert_comp(node, out);
node = node->next;
}
}
static int count_tree(const struct node *node)
{
int sum = 0;
while (node) {
if (node->child)
sum += count_tree(node->child);
else
sum += node->units;
node = node->next;
}
return sum;
}
void make_pdf(int pdf, int use_portrait)
{
FILE *out;
int res;
if (use_portrait)
format = portrait;
else
format = landscape;
if (pdf)
out = popen(
"gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=- "
"-f -", "w");
else
out = popen("cat", "w");
if (!out) {
perror("gs");
exit(1);
}
fprintf(out, "%%!PS\n%s\n", format.file_setup);
total = count_tree(tree);
convert_tree(tree, out);
if (!quiet)
fprintf(stderr, "\rFinishing\n");
res = pclose(out);
if (res < 0) {
perror("pclose");
exit(1);
}
if (res) {
fprintf(stderr, "exit status %d\n", res);
exit(1);
}
}

17
gencat/pdf.h Normal file
View File

@@ -0,0 +1,17 @@
/*
* pdf.h - Generate PDF
*
* 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.
*/
#ifndef PDF_H
#define PDF_H
void make_pdf(int pdf, int use_portrait);
#endif /* !PDF_H */

6
gencat/run Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/sh
# Hack: ps2pdf is happy with the PS generate, but if we invoke gs diretctly,
# isn't. Some voodoo is still missing ...
./gencat -p \
-L /home/qi/kicad-libs/components \
/home/qi/kicad-libs/components/EXPAND DESC >out.pdf

84
gencat/sym2xps Executable file
View File

@@ -0,0 +1,84 @@
#!/bin/sh -e
#
# sym2xps - Convert a symbol from a Kicad library to Postscript with expanded
# pin types
#
# 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.
#
usage()
{
echo "usage: $0 library symbol unit tmpdir outfile" 1>&2
exit 1
}
lib=$1
sym=$2
unit=$3
tmp=$4
out=$5
[ "$lib" ] && [ "$sym" ] && [ "$unit" ] && [ "$tmp" ] && [ "$out" ] || usage
[ -r "$lib" ] || {
echo "$lib: not found" 1>&2
exit 1
}
grep "^DEF $sym " "$lib" >/dev/null || grep "^DEF ~$sym " "$lib" >/dev/null || {
echo "\"$sym\" not found in $lib" 1>&2
exit 1
}
[ "${tmp#/}" = "$tmp" ] && tmp=`pwd`/$tmp
[ "${out#/}" = "$out" ] && out=`pwd`/$out
mkdir "$tmp"
trap "rm -rf '$tmp'" 0
expand-pintype "$lib" "$tmp"/tmp.lib
cat <<EOF >"$tmp"/tmp.pro
[eeschema]
version=1
[eeschema/libraries]
LibName1=./tmp
EOF
X=6000
Y=4000
sed "\@^DEF $sym @,/^ENDDEF/p;d" "$lib" |
awk '/^F. / { if ($1 == "F0") sub(/"$/, "?\"", $2);
print substr($1, 1, 1), substr($1, 2, 1), $2,
$6, '$X'+$3, '$Y'+$4, $5, " 0000", $8, $9 }' >"$tmp"/fx.tmp
#F field_number "text" orientation posX posY size Flags (see below)
#F0 reference posx posy text_size text_orient visibile htext_justify vtext_justify
cat <<EOF >"$tmp"/tmp.sch
EESchema Schematic File Version 2 date Mon Mar 26 09:29:33 2012
LIBS:dummy
EELAYER 43 0
EELAYER END
\$Comp
L X$sym ??
U $unit 1 00000000
P $X $Y
`cat "$tmp"/fx.tmp`
$unit $X $Y
1 0 0 -1
\$EndComp
\$EndSCHEMATC
EOF
cd "$tmp"
eeschema --plot=ps "$tmp/tmp.sch"
mv tmp.ps "$out"

39
gencat/util.h Normal file
View File

@@ -0,0 +1,39 @@
/*
* util.h - Utility functions
*
* 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.
*/
#ifndef UTIL_H
#define UTIL_H
#include <stdlib.h>
#include <string.h>
#define alloc_size(s) \
({ void *alloc_size_tmp = malloc(s); \
if (!alloc_size_tmp) \
abort(); \
alloc_size_tmp; })
#define alloc_type(t) ((t *) alloc_size(sizeof(t)))
static inline char *stralloc(const char *s)
{
char *t;
t = strdup(s);
if (t)
return t;
perror("strdup");
exit(1);
}
#endif /* !UTIL_H */