1
0
mirror of git://projects.qi-hardware.com/eda-tools.git synced 2024-11-25 21:55:20 +02:00

genex/: generate expanded component view (WIP)

This commit is contained in:
Werner Almesberger 2012-03-30 18:53:51 -03:00
parent aa2fe3ef16
commit 4902886baa
12 changed files with 718 additions and 0 deletions

40
genex/Makefile Normal file
View File

@ -0,0 +1,40 @@
#
# 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.
#
CFLAGS = -Wall -g
OBJS = genex.o comp.o libs.o pdf.o
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
all: genex
genex: $(OBJS)
$(CC) $(CFLAGS) -o $@ $(OBJS) $(LDLIBS)
clean:
rm -f $(OBJS)

125
genex/comp.c Normal file
View File

@ -0,0 +1,125 @@
/*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.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->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;
}
}
void set_libs(struct node *node,
const char *(*find_lib)(const char *sym, const char **canon))
{
while (node) {
if (!node->child) {
node->lib = find_lib(node->name, &node->canon);
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_level(const struct node *tree, int level)
{
const struct node *n;
for (n = tree; n; n = n->next) {
printf("%*s%s\n", 4*level, "", n->name);
dump_level(n->child, level+1);
}
}
void dump_tree(void)
{
dump_level(tree, 0);
}

34
genex/comp.h Normal file
View File

@ -0,0 +1,34 @@
/*
* 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
struct node {
const char *name;
const char *lib; /* NULL if not intermediate node */
const char *canon; /* canonical name of component */
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 set_libs(struct node *node,
const char *(*find_lib)(const char *sym, const char **canon));
void dump_tree(void);
#endif /* !COMP_H */

85
genex/expand-pintype Executable file
View File

@ -0,0 +1,85 @@
#!/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 = 66; # 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",
);
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;
}

61
genex/genex.c Normal file
View File

@ -0,0 +1,61 @@
/*
* genex.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 "comp.h"
#include "libs.h"
static void usage(const char *name)
{
fprintf(stderr, "usage: %s [-L libdir ...] [-l lib ...] hierarchy\n",
name);
exit(1);
}
int main(int argc, char **argv)
{
FILE *file;
int c;
while ((c = getopt(argc, argv, "L:l:")) != EOF)
switch (c) {
case 'L':
add_libdir(optarg);
break;
case 'l':
add_lib(optarg);
break;
default:
usage(*argv);
}
if (argc-optind != 1)
usage(*argv);
file = fopen(argv[optind], "r");
if (!file) {
perror(argv[optind]);
exit(1);
}
read_tree(file);
set_libs(tree, lookup_sym);
fclose(file);
// dump_tree();
make_pdf();
return 0;
}

119
genex/libs.c Normal file
View File

@ -0,0 +1,119 @@
/*
* 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
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include "util.h"
#include "libs.h"
struct entry {
const char *name;
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 char **canon)
{
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->name, name)) {
if (canon)
*canon = e->name;
return lib->path;
}
return NULL;
}
void add_lib(const char *path)
{
FILE *file;
struct lib *lib;
struct entry *e;
char buf[1024]; /* @@@ */
char *spc;
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, "DEF ", 4))
continue;
spc = strchr(buf+4, ' ');
if (!spc) {
fprintf(stderr, "invalid DEF line in %s\n", path);
exit(1);
}
*spc = 0;
e = alloc_type(struct entry);
e->name = stralloc(buf+4);
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);
}

19
genex/libs.h Normal file
View File

@ -0,0 +1,19 @@
/*
* 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
const char *lookup_sym(const char *name, const char **canon);
void add_lib(const char *path);
void add_libdir(const char *path);
#endif /* !LIBS_H */

96
genex/pdf.c Normal file
View File

@ -0,0 +1,96 @@
/*
* 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 "comp.h"
#include "pdf.h"
static int children(const struct node *node)
{
int n = 0;
while (node) {
n++;
node = node->next;
}
return n;
}
static void convert_comp(const struct node *node, FILE *out)
{
char *tmp;
int res;
if (asprintf(&tmp, "./sym2xps '%s' '%s' '%s' '%s'",
node->lib, node->canon, "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);
}
fflush(out);
system("cat tmp.ps");
}
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;
}
}
void make_pdf(void)
{
FILE *out;
int res;
#if 0
out = popen(
"gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=- -f -",
"w");
#else
out = popen("cat", "w");
#endif
if (!out) {
perror("gs");
exit(1);
}
convert_tree(tree, out);
res = pclose(out);
if (res < 0) {
perror("pclose");
exit(1);
}
if (res) {
fprintf(stderr, "exit status %d\n", res);
exit(1);
}
}

17
genex/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(void);
#endif /* !PDF_H */

8
genex/run Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
# Hack: ps2pdf is happy with the PS generate, but if we invoke gs diretctly,
# isn't. Some voodoo is still missing ...
PATH=$PATH:. ./genex \
-L /home/qi/kicad-libs/components \
/home/qi/kicad-libs/components/EXPAND >out.ps
ps2pdf out.ps out.pdf
rm -f out.ps

75
genex/sym2xps Executable file
View File

@ -0,0 +1,75 @@
#!/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 tmpdir outfile" 1>&2
exit 1
}
lib=$1
sym=$2
tmp=$3
out=$4
[ "$lib" ] && [ "$sym" ] && [ "$tmp" ] && [ "$out" ] || usage
[ -r "$lib" ] || {
echo "$lib: not found" 1>&2
exit 1
}
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
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 1 1 00000000
P $X $Y
1 $X $Y
1 0 0 -1
\$EndComp
\$EndSCHEMATC
EOF
cd "$tmp"
eeschema --plot=ps "$tmp/tmp.sch"
mv tmp.ps "$out"

39
genex/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 */