r5416 - trunk/eda/fped
werner at docs.openmoko.org
werner at docs.openmoko.org
Mon Aug 10 23:02:27 CEST 2009
Author: werner
Date: 2009-08-10 23:02:26 +0200 (Mon, 10 Aug 2009)
New Revision: 5416
Added:
trunk/eda/fped/dump.c
trunk/eda/fped/kicad.c
trunk/eda/fped/kicad.h
Removed:
trunk/eda/fped/dump.c
Modified:
trunk/eda/fped/Makefile
trunk/eda/fped/TODO
trunk/eda/fped/coord.h
trunk/eda/fped/gui.c
trunk/eda/fped/inst.c
trunk/eda/fped/inst.h
Log:
- added KiCad output
- when saving a file, we now make a backup of any existing file with the same
name
Modified: trunk/eda/fped/Makefile
===================================================================
--- trunk/eda/fped/Makefile 2009-08-10 15:13:07 UTC (rev 5415)
+++ trunk/eda/fped/Makefile 2009-08-10 21:02:26 UTC (rev 5416)
@@ -11,7 +11,7 @@
#
OBJS = fped.o expr.o coord.o obj.o delete.o inst.o util.o error.o \
- unparse.o dump.o meas.o \
+ unparse.o dump.o kicad.o meas.o \
cpp.o lex.yy.o y.tab.o \
gui.o gui_util.o gui_style.o gui_inst.o gui_status.o gui_canvas.o \
gui_tool.o gui_over.o gui_meas.o gui_frame.o
Modified: trunk/eda/fped/TODO
===================================================================
--- trunk/eda/fped/TODO 2009-08-10 15:13:07 UTC (rev 5415)
+++ trunk/eda/fped/TODO 2009-08-10 21:02:26 UTC (rev 5416)
@@ -2,7 +2,6 @@
- populate input area (still needed: mm/mil, rezoom)
- add default unit (combine with grid unit selection ?)
- consider adding auto/mm/mil selection for each dimension
-- add KiCad output
- add postscript output
- add option to include/omit helper vecs and frames (done for display, still
need postscript)
Modified: trunk/eda/fped/coord.h
===================================================================
--- trunk/eda/fped/coord.h 2009-08-10 15:13:07 UTC (rev 5415)
+++ trunk/eda/fped/coord.h 2009-08-10 21:02:26 UTC (rev 5416)
@@ -20,7 +20,7 @@
#define MICRON_UNITS 10
#define MIL_UNITS (25.4*MICRON_UNITS)
#define MM_UNITS (1000.0*MICRON_UNITS)
-#define KICAD_UNIT (10.0*MIL_UNITS)
+#define KICAD_UNIT (MIL_UNITS/10.0)
#define MIL_IN_MM 0.0254
@@ -54,7 +54,7 @@
}
-static inline double units_to_kicad(unit_type u)
+static inline int units_to_kicad(unit_type u)
{
return (double) u/KICAD_UNIT;
}
Deleted: trunk/eda/fped/dump.c
===================================================================
--- trunk/eda/fped/dump.c 2009-08-10 15:13:07 UTC (rev 5415)
+++ trunk/eda/fped/dump.c 2009-08-10 21:02:26 UTC (rev 5416)
@@ -1,396 +0,0 @@
-/*
- * dump.c - Dump objects in the native FPD format
- *
- * Written 2009 by Werner Almesberger
- * Copyright 2009 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 "util.h"
-#include "unparse.h"
-#include "obj.h"
-#include "dump.h"
-
-
-/* ----- variables --------------------------------------------------------- */
-
-
-static void dump_var(FILE *file, const struct table *table,
- const char *indent)
-{
- char *s;
-
- s = unparse(table->rows->values->expr);
- fprintf(file, "%sset %s = %s\n\n", indent, table->vars->name, s);
- free(s);
-}
-
-
-static void dump_table(FILE *file, const struct table *table,
- const char *indent)
-{
- const struct var *var;
- const struct row *row;
- const struct value *value;
- char *s;
-
- if (table->vars && !table->vars->next &&
- table->rows && !table->rows->next) {
- dump_var(file, table, indent);
- return;
- }
- fprintf(file, "%stable\n%s {", indent, indent);
- for (var = table->vars; var; var = var->next)
- fprintf(file, "%s %s", var == table->vars ? "" : ",",
- var->name);
- fprintf(file, " }\n");
- for (row = table->rows; row; row = row->next) {
- fprintf(file, "%s {", indent);
- for (value = row->values; value; value = value->next) {
- s = unparse(value->expr);
- fprintf(file, "%s %s",
- value == row->values? "" : ",", s);
- free(s);
- }
- fprintf(file, " }\n");
- }
- fprintf(file, "\n");
-}
-
-
-static void dump_loop(FILE *file, const struct loop *loop, const char *indent)
-{
- char *from, *to;
-
- from = unparse(loop->from.expr);
- to = unparse(loop->to.expr);
- fprintf(file, "%sloop %s = %s, %s\n\n",
- indent, loop->var.name, from, to);
- free(from);
- free(to);
-}
-
-
-/* ----- vectors and objects ----------------------------------------------- */
-
-
-static char *generate_name(const struct vec *base)
-{
- const struct vec *walk;
- int n;
-
- n = 0;
- for (walk = base->frame->vecs; walk != base; walk = walk->next)
- n++;
- return stralloc_printf("_%s_%d",
- base->frame->name ? base->frame->name : "", n);
-}
-
-
-static char *base_name(const struct vec *base, const struct vec *next)
-{
- if (!base)
- return stralloc("@");
- if (next && base->next == next)
- return stralloc(".");
- if (base->name)
- return stralloc(base->name);
- return generate_name(base);
-}
-
-
-static char *obj_base_name(const struct vec *base, const struct vec *prev)
-{
- if (base && base == prev)
- return stralloc(".");
- return base_name(base, NULL);
-}
-
-
-static int n_vec_refs(const struct vec *vec)
-{
- const struct vec *walk;
- int n;
-
- n = 0;
- for (walk = vec->frame->vecs; walk; walk = walk->next)
- if (walk->base == vec)
- n++;
- return n;
-}
-
-
-/*
- * "need" operates in two modes:
- *
- * - if "prev" is non-NULL, we're looking for objects that need to be put after
- * the current vector (in "prev"). Only those objects need to be put there
- * that have at least one base that isn't the frame's origin or already has a
- * name.
- *
- * - if "prev" is NULL, we're at the end of the frame. We have already used all
- * the . references we could, so now we have to find out which objects
- * haven't been dumped yet. "need" still returns the ones that had a need to
- * be dumped. Again, that's those that have at least one possible "." base.
- * Since this "." base will have been used by now, the object must have been
- * dumped.
- */
-
-static int need(const struct vec *base, const struct vec *prev)
-{
- if (!base)
- return 0;
- if (base->name)
- return 0;
- if (prev)
- return base == prev;
- return 1;
-}
-
-
-/*
- * If we need a vector that's defined later, we have to defer dumping the
- * object.
- */
-
-static int later(const struct vec *base, const struct vec *prev)
-{
- while (prev) {
- if (base == prev)
- return 1;
- prev = prev->next;
- }
- return 0;
-}
-
-
-static int may_dump_obj_now(const struct obj *obj, const struct vec *prev)
-{
- int n, l;
-
- n = need(obj->base, prev);
- l = later(obj->base, prev);
-
- switch (obj->type) {
- case ot_frame:
- break;
- case ot_line:
- n |= need(obj->u.line.other, prev);
- l |= later(obj->u.line.other, prev);
- break;
- case ot_rect:
- n |= need(obj->u.rect.other, prev);
- l |= later(obj->u.rect.other, prev);
- break;
- case ot_pad:
- n |= need(obj->u.pad.other, prev);
- l |= later(obj->u.pad.other, prev);
- break;
- case ot_arc:
- n |= need(obj->u.arc.start, prev);
- n |= need(obj->u.arc.end, prev);
- l |= later(obj->u.arc.start, prev);
- l |= later(obj->u.arc.end, prev);
- break;
- case ot_meas:
- return 0;
- default:
- abort();
- }
-
- return n && !l;
-}
-
-
-static const char *meas_type_name[mt_n] = {
- "meas", "measx", "measy",
- "meas", "measx", "measy",
-};
-
-
-
-static void print_meas_base(FILE *file, struct vec *base)
-{
- if (base->frame != root_frame)
- fprintf(file, "%s.", base->frame->name);
- fprintf(file, "%s", base->name);
-}
-
-
-static void dump_obj(FILE *file, struct obj *obj, const char *indent,
- const struct vec *prev)
-{
- char *base, *s1, *s2, *s3;
-
- if (obj->dumped)
- return;
- obj->dumped = 1;
- base = obj_base_name(obj->base, prev);
- switch (obj->type) {
- case ot_frame:
- fprintf(file, "%sframe %s %s\n",
- indent, obj->u.frame.ref->name, base);
- break;
- case ot_line:
- s1 = obj_base_name(obj->u.line.other, prev);
- s2 = unparse(obj->u.line.width);
- fprintf(file, "%sline %s %s %s\n", indent, base, s1, s2);
- free(s1);
- free(s2);
- break;
- case ot_rect:
- s1 = obj_base_name(obj->u.rect.other, prev);
- s2 = unparse(obj->u.rect.width);
- fprintf(file, "%srect %s %s %s\n", indent, base, s1, s2);
- free(s1);
- free(s2);
- break;
- case ot_pad:
- s1 = obj_base_name(obj->u.pad.other, prev);
- fprintf(file, "%spad \"%s\" %s %s\n", indent,
- obj->u.pad.name, base, s1);
- free(s1);
- break;
- case ot_arc:
- s1 = obj_base_name(obj->u.arc.start, prev);
- s3 = unparse(obj->u.arc.width);
- if (obj->u.arc.start == obj->u.arc.end) {
- fprintf(file, "%scirc %s %s %s\n",
- indent, base, s1, s3);
- } else {
- s2 = obj_base_name(obj->u.arc.end, prev);
- fprintf(file, "%sarc %s %s %s %s\n", indent,
- base, s1, s2, s3);
- free(s2);
- }
- free(s1);
- free(s3);
- break;
- case ot_meas:
- fprintf(file, "%s%s ", indent,
- meas_type_name[obj->u.meas.type]);
- if (obj->u.meas.label)
- fprintf(file, "\"%s\" ", obj->u.meas.label);
- print_meas_base(file, obj->base);
- fprintf(file, " %s ",
- obj->u.meas.type < 3 ? obj->u.meas.inverted ? "<-" : "->" :
- obj->u.meas.inverted ? "<<" : ">>");
- print_meas_base(file, obj->u.meas.high);
- if (!obj->u.meas.offset)
- fprintf(file, "\n");
- else {
- s1 = unparse(obj->u.meas.offset);
- fprintf(file, " %s\n", s1);
- free(s1);
- }
- break;
- default:
- abort();
- }
- free(base);
-}
-
-
-/*
- * Tricky logic ahead: when dumping a vector, we search for a vectors that
- * depends on that vector for ".". If we find one, we dump it immediately after
- * this vector.
- */
-
-static void recurse_vec(FILE *file, const struct vec *vec, const char *indent)
-{
- const struct vec *next;
- struct obj *obj;
- char *base, *x, *y, *s;
-
- base = base_name(vec->base, vec);
- x = unparse(vec->x);
- y = unparse(vec->y);
- if (vec->name)
- fprintf(file, "%s%s: vec %s(%s, %s)\n",
- indent, vec->name, base, x, y);
- else {
- s = generate_name(vec);
- fprintf(file, "%s%s: vec %s(%s, %s)\n", indent, s, base, x, y);
- free(s);
- }
- free(base);
- free(x);
- free(y);
-
- for (obj = vec->frame->objs; obj; obj = obj->next)
- if (may_dump_obj_now(obj, vec))
- dump_obj(file, obj, indent, vec);
- if (n_vec_refs(vec) == 1) {
- for (next = vec->next; next->base != vec; next = next->next);
- recurse_vec(file, next, indent);
- }
-}
-
-
-static void dump_vecs(FILE *file, const struct vec *vecs, const char *indent)
-{
- const struct vec *vec;
-
- for (vec = vecs; vec; vec = vec->next)
- if (!vec->base || n_vec_refs(vec->base) != 1)
- recurse_vec(file, vec, indent);
-}
-
-
-/* ----- frames ------------------------------------------------------------ */
-
-
-static void dump_frame(FILE *file, const struct frame *frame,
- const char *indent)
-{
- const struct table *table;
- const struct loop *loop;
- struct obj *obj;
-
- for (table = frame->tables; table; table = table->next)
- dump_table(file, table, indent);
- for (loop = frame->loops; loop; loop = loop->next)
- dump_loop(file, loop, indent);
- for (obj = frame->objs; obj; obj = obj->next)
- obj->dumped = 0;
- dump_vecs(file, frame->vecs, indent);
-
- /* frames based on @ (anything else ?) */
- for (obj = frame->objs; obj; obj = obj->next)
- if (obj->type != ot_meas)
- dump_obj(file, obj, indent, NULL);
- for (obj = frame->objs; obj; obj = obj->next)
- dump_obj(file, obj, indent, NULL);
-}
-
-
-/* ----- file -------------------------------------------------------------- */
-
-
-int dump(FILE *file)
-{
- const struct frame *frame;
-
- fprintf(file, "/* MACHINE-GENERATED ! */\n\n");
- for (frame = frames; frame; frame = frame->next) {
- if (!frame->name) {
- fprintf(file, "part \"%s\"\n", part_name);
- dump_frame(file, frame, "");
- } else {
- fprintf(file, "frame %s {\n", frame->name);
- dump_frame(file, frame, "\t");
- fprintf(file, "}\n\n");
- }
- }
- fflush(file);
- return !ferror(file);
-}
Added: trunk/eda/fped/dump.c
===================================================================
--- trunk/eda/fped/dump.c (rev 0)
+++ trunk/eda/fped/dump.c 2009-08-10 21:02:26 UTC (rev 5416)
@@ -0,0 +1,396 @@
+/*
+ * dump.c - Dump objects in the native FPD format
+ *
+ * Written 2009 by Werner Almesberger
+ * Copyright 2009 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 "util.h"
+#include "unparse.h"
+#include "obj.h"
+#include "dump.h"
+
+
+/* ----- variables --------------------------------------------------------- */
+
+
+static void dump_var(FILE *file, const struct table *table,
+ const char *indent)
+{
+ char *s;
+
+ s = unparse(table->rows->values->expr);
+ fprintf(file, "%sset %s = %s\n\n", indent, table->vars->name, s);
+ free(s);
+}
+
+
+static void dump_table(FILE *file, const struct table *table,
+ const char *indent)
+{
+ const struct var *var;
+ const struct row *row;
+ const struct value *value;
+ char *s;
+
+ if (table->vars && !table->vars->next &&
+ table->rows && !table->rows->next) {
+ dump_var(file, table, indent);
+ return;
+ }
+ fprintf(file, "%stable\n%s {", indent, indent);
+ for (var = table->vars; var; var = var->next)
+ fprintf(file, "%s %s", var == table->vars ? "" : ",",
+ var->name);
+ fprintf(file, " }\n");
+ for (row = table->rows; row; row = row->next) {
+ fprintf(file, "%s {", indent);
+ for (value = row->values; value; value = value->next) {
+ s = unparse(value->expr);
+ fprintf(file, "%s %s",
+ value == row->values? "" : ",", s);
+ free(s);
+ }
+ fprintf(file, " }\n");
+ }
+ fprintf(file, "\n");
+}
+
+
+static void dump_loop(FILE *file, const struct loop *loop, const char *indent)
+{
+ char *from, *to;
+
+ from = unparse(loop->from.expr);
+ to = unparse(loop->to.expr);
+ fprintf(file, "%sloop %s = %s, %s\n\n",
+ indent, loop->var.name, from, to);
+ free(from);
+ free(to);
+}
+
+
+/* ----- vectors and objects ----------------------------------------------- */
+
+
+static char *generate_name(const struct vec *base)
+{
+ const struct vec *walk;
+ int n;
+
+ n = 0;
+ for (walk = base->frame->vecs; walk != base; walk = walk->next)
+ n++;
+ return stralloc_printf("_%s_%d",
+ base->frame->name ? base->frame->name : "", n);
+}
+
+
+static char *base_name(const struct vec *base, const struct vec *next)
+{
+ if (!base)
+ return stralloc("@");
+ if (next && base->next == next)
+ return stralloc(".");
+ if (base->name)
+ return stralloc(base->name);
+ return generate_name(base);
+}
+
+
+static char *obj_base_name(const struct vec *base, const struct vec *prev)
+{
+ if (base && base == prev)
+ return stralloc(".");
+ return base_name(base, NULL);
+}
+
+
+static int n_vec_refs(const struct vec *vec)
+{
+ const struct vec *walk;
+ int n;
+
+ n = 0;
+ for (walk = vec->frame->vecs; walk; walk = walk->next)
+ if (walk->base == vec)
+ n++;
+ return n;
+}
+
+
+/*
+ * "need" operates in two modes:
+ *
+ * - if "prev" is non-NULL, we're looking for objects that need to be put after
+ * the current vector (in "prev"). Only those objects need to be put there
+ * that have at least one base that isn't the frame's origin or already has a
+ * name.
+ *
+ * - if "prev" is NULL, we're at the end of the frame. We have already used all
+ * the . references we could, so now we have to find out which objects
+ * haven't been dumped yet. "need" still returns the ones that had a need to
+ * be dumped. Again, that's those that have at least one possible "." base.
+ * Since this "." base will have been used by now, the object must have been
+ * dumped.
+ */
+
+static int need(const struct vec *base, const struct vec *prev)
+{
+ if (!base)
+ return 0;
+ if (base->name)
+ return 0;
+ if (prev)
+ return base == prev;
+ return 1;
+}
+
+
+/*
+ * If we need a vector that's defined later, we have to defer dumping the
+ * object.
+ */
+
+static int later(const struct vec *base, const struct vec *prev)
+{
+ while (prev) {
+ if (base == prev)
+ return 1;
+ prev = prev->next;
+ }
+ return 0;
+}
+
+
+static int may_dump_obj_now(const struct obj *obj, const struct vec *prev)
+{
+ int n, l;
+
+ n = need(obj->base, prev);
+ l = later(obj->base, prev);
+
+ switch (obj->type) {
+ case ot_frame:
+ break;
+ case ot_line:
+ n |= need(obj->u.line.other, prev);
+ l |= later(obj->u.line.other, prev);
+ break;
+ case ot_rect:
+ n |= need(obj->u.rect.other, prev);
+ l |= later(obj->u.rect.other, prev);
+ break;
+ case ot_pad:
+ n |= need(obj->u.pad.other, prev);
+ l |= later(obj->u.pad.other, prev);
+ break;
+ case ot_arc:
+ n |= need(obj->u.arc.start, prev);
+ n |= need(obj->u.arc.end, prev);
+ l |= later(obj->u.arc.start, prev);
+ l |= later(obj->u.arc.end, prev);
+ break;
+ case ot_meas:
+ return 0;
+ default:
+ abort();
+ }
+
+ return n && !l;
+}
+
+
+static const char *meas_type_name[mt_n] = {
+ "meas", "measx", "measy",
+ "meas", "measx", "measy",
+};
+
+
+
+static void print_meas_base(FILE *file, struct vec *base)
+{
+ if (base->frame != root_frame)
+ fprintf(file, "%s.", base->frame->name);
+ fprintf(file, "%s", base->name);
+}
+
+
+static void dump_obj(FILE *file, struct obj *obj, const char *indent,
+ const struct vec *prev)
+{
+ char *base, *s1, *s2, *s3;
+
+ if (obj->dumped)
+ return;
+ obj->dumped = 1;
+ base = obj_base_name(obj->base, prev);
+ switch (obj->type) {
+ case ot_frame:
+ fprintf(file, "%sframe %s %s\n",
+ indent, obj->u.frame.ref->name, base);
+ break;
+ case ot_line:
+ s1 = obj_base_name(obj->u.line.other, prev);
+ s2 = unparse(obj->u.line.width);
+ fprintf(file, "%sline %s %s %s\n", indent, base, s1, s2);
+ free(s1);
+ free(s2);
+ break;
+ case ot_rect:
+ s1 = obj_base_name(obj->u.rect.other, prev);
+ s2 = unparse(obj->u.rect.width);
+ fprintf(file, "%srect %s %s %s\n", indent, base, s1, s2);
+ free(s1);
+ free(s2);
+ break;
+ case ot_pad:
+ s1 = obj_base_name(obj->u.pad.other, prev);
+ fprintf(file, "%spad \"%s\" %s %s\n", indent,
+ obj->u.pad.name, base, s1);
+ free(s1);
+ break;
+ case ot_arc:
+ s1 = obj_base_name(obj->u.arc.start, prev);
+ s3 = unparse(obj->u.arc.width);
+ if (obj->u.arc.start == obj->u.arc.end) {
+ fprintf(file, "%scirc %s %s %s\n",
+ indent, base, s1, s3);
+ } else {
+ s2 = obj_base_name(obj->u.arc.end, prev);
+ fprintf(file, "%sarc %s %s %s %s\n", indent,
+ base, s1, s2, s3);
+ free(s2);
+ }
+ free(s1);
+ free(s3);
+ break;
+ case ot_meas:
+ fprintf(file, "%s%s ", indent,
+ meas_type_name[obj->u.meas.type]);
+ if (obj->u.meas.label)
+ fprintf(file, "\"%s\" ", obj->u.meas.label);
+ print_meas_base(file, obj->base);
+ fprintf(file, " %s ",
+ obj->u.meas.type < 3 ? obj->u.meas.inverted ? "<-" : "->" :
+ obj->u.meas.inverted ? "<<" : ">>");
+ print_meas_base(file, obj->u.meas.high);
+ if (!obj->u.meas.offset)
+ fprintf(file, "\n");
+ else {
+ s1 = unparse(obj->u.meas.offset);
+ fprintf(file, " %s\n", s1);
+ free(s1);
+ }
+ break;
+ default:
+ abort();
+ }
+ free(base);
+}
+
+
+/*
+ * Tricky logic ahead: when dumping a vector, we search for a vectors that
+ * depends on that vector for ".". If we find one, we dump it immediately after
+ * this vector.
+ */
+
+static void recurse_vec(FILE *file, const struct vec *vec, const char *indent)
+{
+ const struct vec *next;
+ struct obj *obj;
+ char *base, *x, *y, *s;
+
+ base = base_name(vec->base, vec);
+ x = unparse(vec->x);
+ y = unparse(vec->y);
+ if (vec->name)
+ fprintf(file, "%s%s: vec %s(%s, %s)\n",
+ indent, vec->name, base, x, y);
+ else {
+ s = generate_name(vec);
+ fprintf(file, "%s%s: vec %s(%s, %s)\n", indent, s, base, x, y);
+ free(s);
+ }
+ free(base);
+ free(x);
+ free(y);
+
+ for (obj = vec->frame->objs; obj; obj = obj->next)
+ if (may_dump_obj_now(obj, vec))
+ dump_obj(file, obj, indent, vec);
+ if (n_vec_refs(vec) == 1) {
+ for (next = vec->next; next->base != vec; next = next->next);
+ recurse_vec(file, next, indent);
+ }
+}
+
+
+static void dump_vecs(FILE *file, const struct vec *vecs, const char *indent)
+{
+ const struct vec *vec;
+
+ for (vec = vecs; vec; vec = vec->next)
+ if (!vec->base || n_vec_refs(vec->base) != 1)
+ recurse_vec(file, vec, indent);
+}
+
+
+/* ----- frames ------------------------------------------------------------ */
+
+
+static void dump_frame(FILE *file, const struct frame *frame,
+ const char *indent)
+{
+ const struct table *table;
+ const struct loop *loop;
+ struct obj *obj;
+
+ for (table = frame->tables; table; table = table->next)
+ dump_table(file, table, indent);
+ for (loop = frame->loops; loop; loop = loop->next)
+ dump_loop(file, loop, indent);
+ for (obj = frame->objs; obj; obj = obj->next)
+ obj->dumped = 0;
+ dump_vecs(file, frame->vecs, indent);
+
+ /* frames based on @ (anything else ?) */
+ for (obj = frame->objs; obj; obj = obj->next)
+ if (obj->type != ot_meas)
+ dump_obj(file, obj, indent, NULL);
+ for (obj = frame->objs; obj; obj = obj->next)
+ dump_obj(file, obj, indent, NULL);
+}
+
+
+/* ----- file -------------------------------------------------------------- */
+
+
+int dump(FILE *file)
+{
+ const struct frame *frame;
+
+ fprintf(file, "/* MACHINE-GENERATED ! */\n\n");
+ for (frame = frames; frame; frame = frame->next) {
+ if (!frame->name) {
+ fprintf(file, "part \"%s\"\n", part_name);
+ dump_frame(file, frame, "");
+ } else {
+ fprintf(file, "frame %s {\n", frame->name);
+ dump_frame(file, frame, "\t");
+ fprintf(file, "}\n\n");
+ }
+ }
+ fflush(file);
+ return !ferror(file);
+}
Modified: trunk/eda/fped/gui.c
===================================================================
--- trunk/eda/fped/gui.c 2009-08-10 15:13:07 UTC (rev 5415)
+++ trunk/eda/fped/gui.c 2009-08-10 21:02:26 UTC (rev 5416)
@@ -12,11 +12,16 @@
#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
#include <gtk/gtk.h>
+#include "util.h"
#include "inst.h"
#include "obj.h"
#include "dump.h"
+#include "kicad.h"
#include "gui_util.h"
#include "gui_style.h"
#include "gui_status.h"
@@ -46,27 +51,98 @@
/* ----- menu bar ---------------------------------------------------------- */
-static void menu_save(GtkWidget *widget, gpointer user)
+static char *set_extension(const char *name, const char *ext)
{
+ char *s = stralloc(name);
+ char *slash, *dot;
+ char *res;
+
+ slash = strrchr(s, '/');
+ dot = strrchr(slash ? slash : s, '.');
+ if (dot)
+ *dot = 0;
+ res = stralloc_printf("%s.%s", s, ext);
+ free(s);
+ return res;
+}
+
+
+static void save_with_backup(const char *name, int (*fn)(FILE *file))
+{
FILE *file;
+ char *s = stralloc(name);
+ char *slash, *dot, *tmp;
+ int n;
+ struct stat st;
- if (!save_file) {
- if (!dump(stdout))
- perror("stdout");
- return;
+ slash = strrchr(s, '/');
+ dot = strrchr(slash ? slash : s, '.');
+ if (dot)
+ *dot = 0;
+ n = 0;
+ while (1) {
+ tmp = stralloc_printf("%s~%d%s%s",
+ s, n, dot ? "." : "", dot ? dot+1 : "");
+ if (stat(tmp, &st) < 0) {
+ if (errno == ENOENT)
+ break;
+ perror(tmp);
+ free(tmp);
+ return;
+ }
+ free(tmp);
+ n++;
}
- file = fopen(save_file, "w");
+ if (rename(name, tmp) < 0) {
+ if (errno != ENOENT) {
+ perror(name);
+ free(tmp);
+ return;
+ }
+ } else {
+ fprintf(stderr, "renamed %s to %s\n", name, tmp);
+ }
+ free(tmp);
+
+ file = fopen(name, "w");
if (!file) {
- perror(save_file);
+ perror(name);
return;
}
- if (!dump(file))
- perror(save_file);
+ if (!fn(file))
+ perror(name);
if (fclose(file) == EOF)
- perror(save_file);
+ perror(name);
+ fprintf(stderr, "saved to %s\n", name);
}
+static void menu_save(GtkWidget *widget, gpointer user)
+{
+ if (save_file)
+ save_with_backup(save_file, dump);
+ else {
+ if (!dump(stdout))
+ perror("stdout");
+ }
+}
+
+
+static void menu_save_kicad(GtkWidget *widget, gpointer user)
+{
+ char *name;
+
+ if (save_file) {
+ name = set_extension(save_file, "mod");
+ save_with_backup(name, kicad);
+ free(name);
+ } else {
+ if (!kicad(stdout))
+ perror("stdout");
+ }
+}
+
+
static void make_menu_bar(GtkWidget *hbox)
{
GtkWidget *bar;
@@ -86,6 +162,11 @@
g_signal_connect(G_OBJECT(save), "activate",
G_CALLBACK(menu_save), NULL);
+ save = gtk_menu_item_new_with_label("Save as KiCad");
+ gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), save);
+ g_signal_connect(G_OBJECT(save), "activate",
+ G_CALLBACK(menu_save_kicad), NULL);
+
quit = gtk_menu_item_new_with_label("Quit");
gtk_menu_shell_append(GTK_MENU_SHELL(file_menu), quit);
g_signal_connect(G_OBJECT(quit), "activate",
Modified: trunk/eda/fped/inst.c
===================================================================
--- trunk/eda/fped/inst.c 2009-08-10 15:13:07 UTC (rev 5415)
+++ trunk/eda/fped/inst.c 2009-08-10 21:02:26 UTC (rev 5416)
@@ -29,39 +29,12 @@
#include "inst.h"
-enum inst_prio {
- ip_frame, /* frames have their own selection */
- ip_pad, /* pads also accept clicks inside */
- ip_circ, /* circles don't overlap easily */
- ip_arc, /* arc are like circles, just shorter */
- ip_rect, /* rectangles have plenty of sides */
- ip_meas, /* mesurements are like lines but set a bit apart */
- ip_line, /* lines are easly overlapped by other things */
- ip_vec, /* vectors only have the end point */
- ip_n, /* number of priorities */
-};
-
-
-#define FOR_INST_PRIOS_UP(prio) \
- for (prio = 0; prio != ip_n; prio++)
-
-#define FOR_INST_PRIOS_DOWN(prio) \
- for (prio = ip_n-1; prio != (enum inst_prio) -1; prio--)
-
-#define FOR_INSTS_UP(prio, inst) \
- FOR_INST_PRIOS_UP(prio) \
- for (inst = insts[prio]; inst; inst = inst->next)
-
-#define FOR_INSTS_DOWN(prio, inst) \
- FOR_INST_PRIOS_DOWN(prio) \
- for (inst = insts[prio]; inst; inst = inst->next)
-
-
struct inst *selected_inst = NULL;
+struct inst *insts[ip_n];
struct bbox active_frame_bbox;
static struct inst *curr_frame = NULL;
-static struct inst *insts[ip_n], **next_inst[ip_n];
+static struct inst **next_inst[ip_n];
static struct inst *prev_insts[ip_n];
static unsigned long active_set = 0;
Modified: trunk/eda/fped/inst.h
===================================================================
--- trunk/eda/fped/inst.h 2009-08-10 15:13:07 UTC (rev 5415)
+++ trunk/eda/fped/inst.h 2009-08-10 21:02:26 UTC (rev 5416)
@@ -36,8 +36,23 @@
struct coord max;
};
+
+enum inst_prio {
+ ip_frame, /* frames have their own selection */
+ ip_pad, /* pads also accept clicks inside */
+ ip_circ, /* circles don't overlap easily */
+ ip_arc, /* arc are like circles, just shorter */
+ ip_rect, /* rectangles have plenty of sides */
+ ip_meas, /* mesurements are like lines but set a bit apart */
+ ip_line, /* lines are easly overlapped by other things */
+ ip_vec, /* vectors only have the end point */
+ ip_n, /* number of priorities */
+};
+
+
struct inst;
+
struct inst_ops {
void (*debug)(struct inst *self);
void (*save)(FILE *file, struct inst *self);
@@ -95,9 +110,25 @@
extern struct inst *selected_inst;
+extern struct inst *insts[ip_n];
extern struct bbox active_frame_bbox;
+#define FOR_INST_PRIOS_UP(prio) \
+ for (prio = 0; prio != ip_n; prio++)
+
+#define FOR_INST_PRIOS_DOWN(prio) \
+ for (prio = ip_n-1; prio != (enum inst_prio) -1; prio--)
+
+#define FOR_INSTS_UP(prio, inst) \
+ FOR_INST_PRIOS_UP(prio) \
+ for (inst = insts[prio]; inst; inst = inst->next)
+
+#define FOR_INSTS_DOWN(prio, inst) \
+ FOR_INST_PRIOS_DOWN(prio) \
+ for (inst = insts[prio]; inst; inst = inst->next)
+
+
void inst_select_outside(void *item, void (*deselect)(void *item));
int inst_select(struct coord pos);
void inst_deselect(void);
Added: trunk/eda/fped/kicad.c
===================================================================
--- trunk/eda/fped/kicad.c (rev 0)
+++ trunk/eda/fped/kicad.c 2009-08-10 21:02:26 UTC (rev 5416)
@@ -0,0 +1,260 @@
+/*
+ * kicad.c - Dump objects in the KiCad board/module format
+ *
+ * Written 2009 by Werner Almesberger
+ * Copyright 2009 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 <stdio.h>
+#include <time.h>
+
+#include "coord.h"
+#include "inst.h"
+#include "kicad.h"
+
+
+enum kicad_layer {
+ layer_bottom, /* "copper" */
+ layer_l15,
+ layer_l14,
+ layer_l13,
+ layer_l12,
+ layer_l11,
+ layer_l10,
+ layer_l9,
+ layer_l8,
+ layer_l7,
+ layer_l6,
+ layer_l5,
+ layer_l4,
+ layer_l3,
+ layer_l2,
+ layer_top, /* "component" */
+ layer_glue_bottom, /* adhesive, copper side */
+ layer_glue_top, /* adhesive, component side */
+ layer_paste_bottom, /* solder paste */
+ layer_paste_top,
+ layer_silk_bottom, /* silk screen */
+ layer_silk_top,
+ layer_mask_bottom, /* solder mask */
+ layer_mask_top,
+ layer_draw, /* general drawing */
+ layer_comment,
+ layer_eco1,
+ layer_eco2,
+ layer_edge, /* edge */
+};
+
+
+static void kicad_pad(FILE *file, const struct inst *inst)
+{
+ struct coord min, max;
+ unit_type tmp;
+
+ min.x = units_to_kicad(inst->base.x);
+ min.y = units_to_kicad(inst->base.y);
+ max.x = units_to_kicad(inst->u.pad.other.x);
+ max.y = units_to_kicad(inst->u.pad.other.y);
+
+ if (min.x > max.x) {
+ tmp = min.x;
+ min.x = max.x;
+ max.x = tmp;
+ }
+ if (min.y > max.y) {
+ tmp = min.y;
+ min.y = max.y;
+ max.y = tmp;
+ }
+
+ fprintf(file, "$PAD\n");
+
+ /*
+ * name, shape (rectangle), Xsize, Ysize, Xdelta, Ydelta, Orientation
+ */
+ fprintf(file, "Sh \"%s\" R %d %d 0 0 0\n",
+ inst->u.pad.name, max.x-min.x, max.y-min.y);
+
+ /*
+ * Attributes: pad type, N, layer mask
+ */
+ fprintf(file, "At SMD N %8.8X\n",
+ (1 << layer_top) |
+ (1 << layer_paste_top) |
+ (1 << layer_mask_top));
+
+ /*
+ * Position: Xpos, Ypos
+ */
+ fprintf(file, "Po %d %d\n", (min.x+max.x)/2, -(min.y+max.y)/2);
+
+ fprintf(file, "$EndPAD\n");
+}
+
+
+static void kicad_line(FILE *file, const struct inst *inst)
+{
+ /*
+ * Xstart, Ystart, Xend, Yend, Width, Layer
+ */
+ fprintf(file, "DS %d %d %d %d %d %d\n",
+ units_to_kicad(inst->base.x),
+ -units_to_kicad(inst->base.y),
+ units_to_kicad(inst->u.rect.end.x),
+ -units_to_kicad(inst->u.rect.end.y),
+ units_to_kicad(inst->u.rect.width),
+ layer_silk_top);
+}
+
+
+static void kicad_rect(FILE *file, const struct inst *inst)
+{
+ unit_type xa, ya, xb, yb;
+ unit_type width;
+
+ xa = units_to_kicad(inst->base.x);
+ ya = units_to_kicad(inst->base.y);
+ xb = units_to_kicad(inst->u.rect.end.x);
+ yb = units_to_kicad(inst->u.rect.end.y);
+ width = units_to_kicad(inst->u.rect.width);
+
+ fprintf(file, "DS %d %d %d %d %d %d\n",
+ xa, -ya, xa, -yb, width, layer_silk_top);
+ fprintf(file, "DS %d %d %d %d %d %d\n",
+ xa, -yb, xb, -yb, width, layer_silk_top);
+ fprintf(file, "DS %d %d %d %d %d %d\n",
+ xb, -yb, xb, -ya, width, layer_silk_top);
+ fprintf(file, "DS %d %d %d %d %d %d\n",
+ xb, -ya, xa, -ya, width, layer_silk_top);
+}
+
+
+static void kicad_circ(FILE *file, const struct inst *inst)
+{
+ /*
+ * Xcenter, Ycenter, Xpoint, Ypoint, Width, Layer
+ */
+ fprintf(file, "DC %d %d %d %d %d %d\n",
+ units_to_kicad(inst->base.x),
+ -units_to_kicad(inst->base.y),
+ units_to_kicad(inst->base.x),
+ units_to_kicad(inst->base.y+inst->u.arc.r),
+ units_to_kicad(inst->u.arc.width),
+ layer_silk_top);
+}
+
+
+static void kicad_arc(FILE *file, const struct inst *inst)
+{
+ fprintf(stderr, "NOT YET IMPLEMENTED\n");
+}
+
+
+static void kicad_inst(FILE *file, enum inst_prio prio, const struct inst *inst)
+{
+ switch (prio) {
+ case ip_pad:
+ kicad_pad(file, inst);
+ break;
+ case ip_line:
+ kicad_line(file, inst);
+ break;
+ case ip_rect:
+ kicad_rect(file, inst);
+ break;
+ case ip_circ:
+ kicad_circ(file, inst);
+ break;
+ case ip_arc:
+ kicad_arc(file, inst);
+ break;
+ default:
+ break;
+ }
+}
+
+
+static void kicad_module(FILE *file, const char *name, time_t now)
+{
+ enum inst_prio prio;
+ const struct inst *inst;
+
+ /*
+ * Module library name
+ */
+ fprintf(file, "$MODULE %s\n", name);
+
+ /*
+ * Xpos = 0, Ypos = 0, 15 layers, last modification, timestamp,
+ * moveable, not autoplaced.
+ */
+ fprintf(file, "Po 0 0 0 15 %8.8lX 00000000 ~~\n", (long) now);
+
+ /*
+ * Module library name again
+ */
+ fprintf(file, "Li %s\n", name);
+
+#if 0 /* optional */
+ /*
+ * Description
+ */
+ fprintf(file, "Cd %s\n", name);
+#endif
+
+ /*
+ *
+ */
+ fprintf(file, "Sc %8.8lX\n", (long) now);
+
+ /*
+ * Attributes: SMD = listed in the automatic insertion list
+ */
+ fprintf(file, "At SMD\n");
+
+ /*
+ * Rotation cost: 0 for 90 deg, 0 for 180 deg, 0 = disable rotation
+ */
+ fprintf(file, "Op 0 0 0\n");
+
+ /*
+ * Text fields: Tn = field number, Xpos, Ypos, Xsize ("emspace"),
+ * Ysize ("emspace"), rotation, pen width, N (none), V = visible,
+ * comment layer. All dimensions are 1/10 mil.
+ */
+
+ fprintf(file, "T0 0 -150 200 200 0 40 N V %d \"%s\"\n",
+ layer_comment, name);
+ fprintf(file, "T1 0 150 200 200 0 40 N I %d \"Val*\"\n",
+ layer_comment);
+
+ FOR_INSTS_UP(prio, inst)
+ kicad_inst(file, prio, inst);
+
+ fprintf(file, "$EndMODULE %s\n", name);
+}
+
+
+int kicad(FILE *file)
+{
+ time_t now = time(NULL);
+
+ fprintf(file, "PCBNEW-LibModule-V1 %s\n", ctime(&now));
+
+ fprintf(file, "$INDEX\n");
+ fprintf(file, "%s\n", part_name);
+ fprintf(file, "$EndINDEX\n");
+
+ kicad_module(file, part_name, now);
+
+ fprintf(file, "$EndLIBRARY\n");
+
+ fflush(file);
+ return !ferror(file);
+}
Added: trunk/eda/fped/kicad.h
===================================================================
--- trunk/eda/fped/kicad.h (rev 0)
+++ trunk/eda/fped/kicad.h 2009-08-10 21:02:26 UTC (rev 5416)
@@ -0,0 +1,22 @@
+/*
+ * kicad.h - Dump objects in the KiCad board/module format
+ *
+ * Written 2009 by Werner Almesberger
+ * Copyright 2009 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 KICAD_H
+#define KICAD_H
+
+#include <stdio.h>
+
+
+int kicad(FILE *file);
+
+#endif /* !KICAD_H */
More information about the commitlog
mailing list