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

gencat clashes with an existing tool. rename to genkicat (1/2)

The "gencat" with older rights to the name is from libc, no less.
I wonder how I missed that :-(
This commit is contained in:
Werner Almesberger
2012-07-12 20:07:45 -03:00
parent 6fae97ab15
commit 48434c859d
20 changed files with 0 additions and 0 deletions

8
genkicat/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
genkicat/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 tree.o libs.o run.o comp.o fped.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

95
genkicat/comp.c Normal file
View File

@@ -0,0 +1,95 @@
/*
* comp.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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "run.h"
#include "libs.h"
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 comp_add_lib(struct lib *lib, const char *path)
{
FILE *file;
struct entry *e = NULL;
char buf[1024]; /* @@@ */
char *name, *spc;
const char *s;
file = fopen(path, "r");
if (!file) {
perror(path);
exit(1);
}
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 = new_entry(lib, atoi(s));
if (!e->units) {
fprintf(stderr, "invalid number of units in %s\n",
path);
exit(1);
}
add_name(e, name);
}
fclose(file);
}
static void comp_ps_entry(FILE *file, const struct lib *lib,
const struct entry *e, int unit, int landscape)
{
if (!landscape)
fprintf(file, "-120 700 translate -90 rotate\n");
run_cmd("sym2xps '%s' '%s' %d '%s' '%s'",
e->file->path, e->names->s, unit+1, "tmp", "tmp.ps");
cat(file, "tmp.ps");
}
struct lib comp_lib = {
.ext = ".lib",
.add_lib = comp_add_lib,
.ps_entry = comp_ps_entry,
};

86
genkicat/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;
}

62
genkicat/fped.c Normal file
View File

@@ -0,0 +1,62 @@
/*
* comp.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 asprintf */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "run.h"
#include "libs.h"
static void fped_add_lib(struct lib *lib, const char *path)
{
FILE *file;
char buf[1024]; /* @@@ */
char *tmp, *nl;
asprintf(&tmp, "fped -k '%s' -", path);
file = popen(tmp, "r");
if (!file) {
perror(path);
exit(1);
}
while (fgets(buf, sizeof(buf), file)) {
if (strncmp(buf, "$MODULE ", 8))
continue;
nl = strchr(buf, '\n');
if (nl)
*nl = 0;
add_name(new_entry(lib, 1), buf+8);
}
pclose(file);
}
static void fped_ps_entry(FILE *file, const struct lib *lib,
const struct entry *e, int unit, int landscape)
{
fprintf(file, "0 -25 translate\n");
run_cmd("fped -P -s x200 '%s' -1 '%s' '%s'",
e->file->path, e->names->s, "tmp.ps");
run_cmd("sed -i -e '/OUT pdfmark/d' tmp.ps");
cat(file, "tmp.ps");
}
struct lib fped_lib = {
.ext = ".fpd",
.add_lib = fped_add_lib,
.ps_entry = fped_ps_entry,
};

3
genkicat/gencat Executable file
View File

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

119
genkicat/genkicat.c Normal file
View File

@@ -0,0 +1,119 @@
/*
* 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 "tree.h"
#include "libs.h"
#include "pdf.h"
#include "gencat.h"
int quiet = 0;
static void usage(const char *name)
{
fprintf(stderr,
"usage: %s [-F] [-d|-D] [-p] [-P] [-q] [-L libdir ...] [-l lib ...]\n"
" %*s hierarchy [descriptions ...]\n\n"
" -d dump the tree instead of generating a PDF\n"
" -D dump all the canonical component names (without aliases)\n"
" -F use fped footprints instead of KiCad components\n"
" -L libdir search all libraries in the specified directory\n"
" -l lib search the specified 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)
{
struct lib *lib = &comp_lib;
FILE *file;
int c;
int opt_dump_tree = 0, opt_dump_comp = 0, postscript = 0, portrait = 0;
char **arg;
while ((c = getopt(argc, argv, "dDFL:l:Ppq")) != EOF)
switch (c) {
case 'd':
opt_dump_tree = 1;
break;
case 'D':
opt_dump_comp = 1;
break;
case 'F':
lib = &fped_lib;
break;
case 'L':
add_libdir(lib, optarg);
break;
case 'l':
add_lib(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(lib, tree);
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
genkicat/genkicat.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 */

112
genkicat/libs.c Normal file
View File

@@ -0,0 +1,112 @@
/*
* libc.h - Component or module 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 <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <assert.h>
#include "util.h"
#include "libs.h"
const struct entry *lookup_sym(const struct lib *lib, const char *name)
{
const struct file *file;
const struct entry *e;
for (file = lib->files; file; file = file->next)
for (e = file->entries; e; e = e->next)
if (!strcasecmp(e->names->s, name))
return e;
return NULL;
}
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;
}
struct entry *new_entry(struct lib *lib, int units)
{
struct entry *e;
e = alloc_type(struct entry);
e->names = NULL;
e->units = units;
e->file = lib->files;
e->next = lib->files->entries;
lib->files->entries = e;
return e;
}
void add_lib(struct lib *lib, const char *path)
{
struct file *file;
file = alloc_type(struct file);
file->path = stralloc(path);
file->entries = NULL;
file->lib = lib;
file->next = lib->files;
lib->files = file;
lib->add_lib(lib, path);
}
void add_libdir(struct lib *lib, const char *path)
{
DIR *dir;
const struct dirent *de;
size_t len;
char *tmp;
assert(strlen(lib->ext) == 4);
dir = opendir(path);
if (!dir) {
perror(path);
exit(1);
}
while (1) {
de = readdir(dir);
if (!de)
break;
if (strchr(de->d_name, '~'))
continue;
len = strlen(de->d_name);
if (len < 4)
continue;
if (strcmp(de->d_name+len-4, lib->ext))
continue;
if (asprintf(&tmp, "%s/%s", path, de->d_name) < 0) {
perror("asprintf");
exit(1);
}
add_lib(lib, tmp);
}
closedir(dir);
}

53
genkicat/libs.h Normal file
View File

@@ -0,0 +1,53 @@
/*
* libs.h - Component or module 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;
};
struct entry {
struct name *names;
int units;
const struct file *file;
struct entry *next;
};
struct file {
const char *path;
struct entry *entries;
const struct lib *lib;
struct file *next;
};
struct lib {
const char *ext; /* file extension, ".lib" or ".fpd" */
void (*add_lib)(struct lib *lib, const char *path);
void (*ps_entry)(FILE *file, const struct lib *lib,
const struct entry *e, int unit, int landscape);
struct file *files;
};
extern struct lib comp_lib;
extern struct lib fped_lib;
const struct entry *lookup_sym(const struct lib *lib, const char *name);
void add_name(struct entry *e, char *s);
struct entry *new_entry(struct lib *lib, int units);
void add_lib(struct lib *lib, const char *path);
void add_libdir(struct lib *lib, const char *path);
#endif /* !LIBS_H */

49
genkicat/mkgenkicat-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"

356
genkicat/pdf.c Normal file
View File

@@ -0,0 +1,356 @@
/*
* 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 /* for strcasecmp */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "util.h"
#include "gencat.h"
#include "tree.h"
#include "libs.h"
#include "pdf.h"
static struct format {
const char *file_setup;
const char *overlay_setup;
int left;
struct text {
const char *font;
int size;
int y;
} name, path, lib, comment, index;
int comment_line_skip;
int index_line_skip;
int index_column_skip;
int index_lines;
int index_columns;
} landscape = {
.file_setup = "%%Orientation: Landscape",
.overlay_setup = "90 rotate",
.left = 20,
.name = { "Helvetica-Bold", 24, 57 },
.path = { "Helvetica-Bold", 18, 30 },
.lib = { "Courier", 12, 75 },
.comment = { "Helvetica", 12, 600 },
.index = { "Helvetica", 10, 32 },
.comment_line_skip = 14,
.index_line_skip = 12,
.index_column_skip = 195, /* make a little wider than in portrait */
.index_lines = 45,
.index_columns = 4,
}, portrait = {
.file_setup = "%%Orientation: Portrait",
.overlay_setup = "0 790 translate",
.left = 20,
.name = { "Helvetica-Bold", 24, 57 },
.path = { "Helvetica-Bold", 18, 30 },
.lib = { "Courier", 12, 75 },
.comment = { "Helvetica", 12, 740 },
.index = { "Helvetica", 10, 0 },
.comment_line_skip = 14,
.index_line_skip = 12,
.index_column_skip = 185,
.index_lines = 63,
.index_columns = 3,
};
static const struct format *format;
static int total, done = 0;
/* ----- Utility functions ------------------------------------------------- */
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);
}
/* ----- Alphabetic index -------------------------------------------------- */
struct index {
const char *s;
const struct node *node;
};
static void collect_names(const struct node *node, struct index **idx, int *n)
{
const struct name *name;
while (node) {
if (node->child)
collect_names(node->child, idx, n);
else {
for (name = node->e->names; name; name = name->next) {
(*n)++;
*idx = realloc(*idx, *n*sizeof(struct entry));
if (!*idx)
abort();
(*idx)[*n-1].s = name->s;
(*idx)[*n-1].node = node;
}
}
node = node->next;
}
}
static int comp(const void *a, const void *b)
{
const struct index *ai = a;
const struct index *bi = b;
return strcasecmp(ai->s, bi->s);
}
static void make_index(FILE *file, const struct node *node)
{
struct index *idx = NULL;
const struct index *p;
int n = 0;
int line = 0, col = 0;
collect_names(node, &idx, &n);
qsort(idx, n, sizeof(struct index), comp);
fprintf(file, "[ /Title (Index) /Count 0 /OUT pdfmark\n");
fprintf(file, "/%s findfont %d scalefont setfont\n",
format->index.font, format->index.size);
fprintf(file, "gsave %s 0 setgray\n", format->overlay_setup);
for (p = idx; p != idx+n; p++) {
if (line == format->index_lines) {
line = 0;
col++;
}
if (col == format->index_columns) {
fprintf(file, "grestore showpage\n");
fprintf(file, "gsave %s 0 setgray\n",
format->overlay_setup);
col = 0;
}
fprintf(file, "newpath %d -%d moveto currentpoint\n",
format->left+col*format->index_column_skip,
format->index.y+line*format->index_line_skip);
fprintf(file, "[ /Rect [ ");
ps_string(file, p->s);
fprintf(file, " false charpath flattenpath pathbbox ]\n");
fprintf(file, " /Subtype /Link\n");
fprintf(file, " /Border [ 0 0 0 ]\n");
fprintf(file, " /Action << /Subtype /GoTo /Dest /%p%p >>\n",
p->node, p->s);
fprintf(file, " /ANN pdfmark\n");
fprintf(file, "moveto ");
ps_string(file, p->s);
fprintf(file, " show\n");
line++;
}
fprintf(file, "grestore showpage\n");
free(idx);
}
/* ----- Overlay and table of contents ------------------------------------- */
static int children(const struct node *node)
{
int n = 0;
while (node) {
n++;
node = node->next;
}
return n;
}
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->e->names; name; name = name->next) {
if (name != node->e->names)
fprintf(file, "(, ) show 0.5 setgray\n");
ps_string(file, name->s);
fprintf(file, " show\n");
if (!unit)
fprintf(file, "[ /Dest /%p%p /DEST pdfmark\n",
node, name->s);
}
fprintf(file, "0 setgray\n");
if (node->e->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->e->file->path);
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");
}
/* ----- Component conversion ---------------------------------------------- */
static void convert_entry(const struct node *node, FILE *out)
{
const struct lib *lib = node->e->file->lib;
int i;
for (i = 0; i != node->e->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);
fprintf(out, "gsave\n");
node->e->file->lib->ps_entry(out, lib, node->e, i,
format == &landscape);
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_entry(node, out);
node = node->next;
}
}
/* ----- Setup and PDF generation ------------------------------------------ */
static int count_tree(const struct node *node)
{
int sum = 0;
while (node) {
if (node->child)
sum += count_tree(node->child);
else
sum += node->e->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);
make_index(out, tree);
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
genkicat/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
genkicat/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

70
genkicat/run.c Normal file
View File

@@ -0,0 +1,70 @@
/*
* run.c - Run helper scripts
*
* 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 vasprintf */
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include "run.h"
void run_cmd(const char *fmt, ...)
{
va_list ap;
char *tmp;
int res;
va_start(ap, fmt);
if (vasprintf(&tmp, fmt, ap) < 0) {
perror("vasprintf");
exit(1);
}
res = system(tmp);
if (res < 0) {
perror("system");
exit(1);
}
if (res) {
fprintf(stderr, "\"%s\" returned %d\n", tmp, res);
exit(1);
}
}
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);
}

18
genkicat/run.h Normal file
View File

@@ -0,0 +1,18 @@
/*
* run.h - Run helper scripts
*
* 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 RUN_H
#define RUN_H
void run_cmd(const char *fmt, ...);
void cat(FILE *out, const char *name);
#endif /* !RUN_H */

84
genkicat/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"

269
genkicat/tree.c Normal file
View File

@@ -0,0 +1,269 @@
/*
* tree.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 "libs.h"
#include "tree.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->e = 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++;
if (buf[0] == '#')
continue;
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(const struct lib *lib, struct node *node)
{
while (node) {
if (!node->child) {
node->e = lookup_sym(lib, node->name);
if (!node->e) {
fprintf(stderr, "symbol %s not found\n",
node->name);
exit(1);
}
}
set_libs(lib, node->child);
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->e) {
for (name = n->e->names; name; name = name->next)
printf("%s%s",
name == n->e->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->e)
printf("%s\n", n->e->names->s);
dump_comp_level(n->child);
}
}
void dump_comp(void)
{
dump_comp_level(tree);
}

43
genkicat/tree.h Normal file
View File

@@ -0,0 +1,43 @@
/*
* tree.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 TREE_H
#define TREE_H
#include "libs.h"
struct line {
char *s;
struct line *next;
};
struct node {
const char *name;
const struct entry *e; /* NULL if intermediate node */
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(const struct lib *lib, struct node *node);
void dump_tree(void);
void dump_comp(void);
#endif /* !TREE_H */

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