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