cameo: migrated Excellon reader from drl2gp

- Makefile (OBJS): added excellon.o
- README: added brief description of Excellon input
- excellon.h, excellon.c: adaptation of KiCad drill file reader from
  ../drl2gp/drl2gp.c
- lang.l, lang.y: added command "excellon" to read KiCad drill files
- gerber.h: removed stray newline
This commit is contained in:
Werner Almesberger 2010-12-15 03:27:55 -03:00
parent 26dc02ea57
commit 848eb2a209
7 changed files with 337 additions and 5 deletions

View File

@ -15,7 +15,7 @@ PREFIX ?= /usr/local
SHELL=/bin/bash
MAIN=cameo
OBJS=cameo.o gerber.o gnuplot.o ops.o path.o lex.yy.o y.tab.o
OBJS=cameo.o excellon.o gerber.o gnuplot.o ops.o path.o lex.yy.o y.tab.o
CFLAGS_WARN=-Wall -Wshadow -Wmissing-prototypes \
-Wmissing-declarations -Wno-format-zero-length

View File

@ -28,10 +28,11 @@ Loading paths:
gerber <diameter> [<filename>]
gnuplot <diameter> [<filename>]
excellon [<filename>]
clear
"gerber" and "gnuplot" each add paths from a file to the list of paths
already loaded. "clear" removes all paths.
"gerber", "gnuplot", and "excellon" each add paths from a file to the
list of paths already loaded. "clear" removes all paths.
If the a file name is omitted, standard input is read. The diameter is
the default tool diameter.

303
cameo/excellon.c Normal file
View File

@ -0,0 +1,303 @@
/*
* excellon.c - KiCad drill file input
*
* Written 2010 by Werner Almesberger
* Copyright 2010 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.
*/
/*
* KiCad drill files are in the Excellon format. The format is described here:
*
* http://www.excellon.com/manuals/program.htm
*
* Note that drl2gp currently only implements the subset necessary to process
* the KiCad drill files encountered in a few projects, may not work correctly
* for drill files from other projects, and will almost certainly fail in
* tool-shattering ways when fed excellon files from other sources.
*/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <assert.h>
#include "excellon.h"
#define MAX_TOOL 10
static double tool_d[MAX_TOOL+1];
static int lineno = 1;
static struct path *paths, **anchor;
#define IN2MM(in) ((in)*25.4)
#define MIL2MM(mil) IN2MM((mil)/1000)
/* ----- header parsing ---------------------------------------------------- */
static void header(FILE *file)
{
enum {
ts_nl, /* at beginning of line */
ts_t, /* seen a ^T */
ts_metric, /* parsing METRIC,... */
ts_inch, /* parsing INCH,... */
ts_tc, /* seen ^T\d+C */
ts_skip, /* skip to next \n */
} state = ts_nl;
int c, tool;
double f = 1;
double tmp;
const char *next = NULL;
int metric = 1;
while ((c = fgetc(file)) != EOF) {
switch (state) {
case ts_nl:
switch (c) {
case 'T':
state = ts_t;
tool = 0;
break;
case 'I':
state = ts_inch;
next = "NCH";
break;
case 'M':
state = ts_metric;
next = "ETRIC";
break;
case '%':
return;
case '\n':
lineno++;
break;
default:
state = ts_skip;
break;
}
break;
case ts_inch:
if (c == ',')
metric = 0;
else {
if (c == *next++)
break;
}
state = ts_skip;
break;
case ts_metric:
if (c == ',')
metric = 1;
else {
if (c == *next++)
break;
}
state = ts_skip;
break;
case ts_t:
if (isdigit(c))
tool = tool*10+c-'0';
else if (c != 'C')
state = ts_skip;
else {
assert(c != '\n');
if (tool > MAX_TOOL) {
fprintf(stderr,
"tool index %d too large (> %d)\n",
tool, MAX_TOOL);
exit(1);
}
tool_d[tool] = 0;
f = 1;
state = ts_tc;
}
break;
case ts_tc:
if (isdigit(c)) {
tmp = c-'0';
if (!metric)
tmp = IN2MM(tmp);
if (f == 1)
tool_d[tool] =
tool_d[tool]*10+tmp;
else {
tool_d[tool] += f*tmp;
f /= 10;
}
} else if (c == '.') {
f = 0.1;
} else if (c == '\n') {
lineno++;
state = ts_nl;
} else {
state = ts_skip;
}
break;
default:
if (c == '\n') {
lineno++;
state = ts_nl;
} else {
state = ts_skip;
}
}
}
}
/* ----- body parsing ------------------------------------------------------ */
static int do_cmd(char cmd, double v, int nl)
{
static int metric = 1;
static int slotting = 0;
static double x = 0, y = 0, x0 = 0, d = 0;
int n = v;
switch (cmd) {
case 'M':
switch (n) {
case 30: /* end of program */
return 0;
case 47: /* operator message */
break;
case 71: /* metric measuring mode */
metric = 1;
break;
case 72: /* inch measuring mode */
metric = 0;
break;
default:
fprintf(stderr,
"unrecognized command M%d at line %d\n",
n, lineno);
exit(1);
}
break;
case 'G':
switch (n) {
case 5: /* drill mode */
break;
case 85: /* slot */
x0 = x;
slotting = 1;
break;
default:
fprintf(stderr,
"unrecognized command G%d at line %d\n",
n, lineno);
exit(1);
}
break;
case 'T':
if (!n) {
d = 0;
break;
}
if (n < 1 || n > MAX_TOOL || !tool_d[n]) {
fprintf(stderr, "invalid tool T%d at line %d\n",
n, lineno);
exit(1);
}
d = tool_d[n];
break;
case 'X':
x = metric ? v : IN2MM(v);
break;
case 'Y':
if (!metric)
v = IN2MM(v);
if (slotting) {
*anchor = path_new(d/2);
path_add(*anchor, x0, y, 0);
path_add(*anchor, x, v, 0);
anchor = &(*anchor)->next;
slotting = 0;
break;
}
if (nl) {
assert(d);
*anchor = path_new(d/2);
path_add(*anchor, x, v, 0);
anchor = &(*anchor)->next;
break;
}
y = v;
break;
default:
fprintf(stderr, "unrecognized command \"%c\" at line %d\n",
cmd, lineno);
exit(1);
}
return 1;
}
static void body(FILE *file)
{
char cmd = 0;
double v = 0, f = 1;
int c, s = 0;
while ((c = fgetc(file)) != EOF) {
if (c == '\n') {
lineno++;
if (cmd)
do_cmd(cmd, s ? -v : v, 1);
cmd = 0;
} else if (isdigit(c)) {
if (f == 1)
v = v*10+c-'0';
else {
v += f*(c-'0');
f /= 10;
}
} else if (c == '.') {
f = 0.1;
} else if (c == '-') {
s = !s;
} else {
if (cmd)
if (!do_cmd(cmd, s ? -v : v, 0))
return;
cmd = c;
v = 0;
f = 1;
s = 0;
}
}
}
struct path *excellon_read(const char *name)
{
FILE *file;
file = name ? fopen(name, "r") : stdin;
if (!file) {
perror(name);
exit(1);
}
lineno = 1;
paths = NULL;
anchor = &paths;
header(file);
body(file);
fclose(file);
return paths;
}

21
cameo/excellon.h Normal file
View File

@ -0,0 +1,21 @@
/*
* excellon.h - KiCad drill file input
*
* Written 2010 by Werner Almesberger
* Copyright 2010 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 EXCELLON_H
#define EXCELLON_H
#include "path.h"
struct path *excellon_read(const char *name);
#endif /* !EXCELLON_H */

View File

@ -19,4 +19,3 @@
struct path *gerber_read(const char *name, double r_tool_default);
#endif /* !GERBER_H */

View File

@ -51,6 +51,8 @@ NUM -?[0-9]+\.?[0-9]*
return TOK_GERBER; }
<INITIAL>gnuplot { file_name_follows = 1;
return TOK_GNUPLOT; }
<INITIAL>excellon { BEGIN(FILENAME);
return TOK_EXCELLON; }
<INITIAL>write { BEGIN(FILENAME);
return TOK_WRITE; }

View File

@ -18,6 +18,7 @@
#include "ops.h"
#include "gnuplot.h"
#include "gerber.h"
#include "excellon.h"
#include "y.tab.h"
@ -122,7 +123,7 @@ static void align(int ref, double x, double y)
%token TOK_ALIGN TOK_ARRAY TOK_CLEAR TOK_RESET TOK_OFFSET
%token TOK_TRANSLATE TOK_Z
%token TOK_GERBER TOK_GNUPLOT TOK_WRITE
%token TOK_GERBER TOK_GNUPLOT TOK_EXCELLON TOK_WRITE
%token TOK_DOG TOK_INSIDE
%token <num> NUM_EXP_MIL NUM_EXP_MM NUM_IMP_MIL NUM_IMP_MM REF
@ -206,6 +207,11 @@ command:
add_paths(gnuplot_read($3, $2/2));
translate(xo, yo, 0);
}
| TOK_EXCELLON opt_filename
{
add_paths(excellon_read($2));
translate(xo, yo, 0);
}
| TOK_WRITE opt_filename
{
translate(0, 0, zo);