r5325 - in developers/werner: . fped

werner at docs.openmoko.org werner at docs.openmoko.org
Mon Jul 27 09:31:00 CEST 2009


Author: werner
Date: 2009-07-27 09:30:59 +0200 (Mon, 27 Jul 2009)
New Revision: 5325

Added:
   developers/werner/fped/
   developers/werner/fped/Makefile
   developers/werner/fped/coord.h
   developers/werner/fped/error.c
   developers/werner/fped/error.h
   developers/werner/fped/expr.c
   developers/werner/fped/expr.h
   developers/werner/fped/fpd.l
   developers/werner/fped/fpd.y
   developers/werner/fped/fped.c
   developers/werner/fped/gui.c
   developers/werner/fped/gui.h
   developers/werner/fped/gui_inst.c
   developers/werner/fped/gui_inst.h
   developers/werner/fped/gui_style.c
   developers/werner/fped/gui_style.h
   developers/werner/fped/inst.c
   developers/werner/fped/inst.h
   developers/werner/fped/obj.c
   developers/werner/fped/obj.h
   developers/werner/fped/qfn.fpd
   developers/werner/fped/util.c
   developers/werner/fped/util.h
Log:
Footprint editor. Work in progress.



Added: developers/werner/fped/Makefile
===================================================================
--- developers/werner/fped/Makefile	                        (rev 0)
+++ developers/werner/fped/Makefile	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,44 @@
+OBJS = fped.o expr.o obj.o inst.o util.o error.o lex.yy.o y.tab.o \
+       gui.o gui_style.o gui_inst.o
+
+CFLAGS_GTK = `pkg-config --cflags gtk+-2.0`
+LIBS_GTK = `pkg-config --libs gtk+-2.0`
+
+CFLAGS=-Wall -g $(CFLAGS_GTK)
+CFLAGS_LEX=-g
+CFLAGS_YACC=-g
+LDLIBS = -lm -lfl $(LIBS_GTK)
+YACC=bison -y
+YYFLAGS=-v
+
+all:		fped
+
+fped:		$(OBJS)
+		$(CC) -o $@ $(OBJS) $(LDLIBS)
+
+lex.yy.c:	fpd.l y.tab.h
+		$(LEX) fpd.l
+
+lex.yy.o:	lex.yy.c y.tab.h
+		$(CC) -c $(CFLAGS_LEX) lex.yy.c
+
+y.tab.c y.tab.h: fpd.y
+		$(YACC) $(YYFLAGS) -d fpd.y
+
+y.tab.o:	y.tab.c
+		$(CC) -c $(CFLAGS_YACC) y.tab.c
+
+# ----- Dependencies ----------------------------------------------------------
+
+dep depend .depend: lex.yy.c y.tab.h y.tab.c
+		$(CPP) $(CFLAGS) -MM -MG *.c >.depend || \
+		  { rm -f .depend; exit 1; }
+
+ifeq (.depend,$(wildcard .depend))
+include .depend
+endif
+
+# ----- Cleanup ---------------------------------------------------------------
+
+clean:
+		rm -f $(OBJS) lex.yy.c y.tab.c y.tab.h y.output

Added: developers/werner/fped/coord.h
===================================================================
--- developers/werner/fped/coord.h	                        (rev 0)
+++ developers/werner/fped/coord.h	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,60 @@
+/*
+ * coord.h - Coordinate representation
+ *
+ * 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 COORD_H
+#define COORD_H
+
+#include <stdint.h>
+
+
+#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)
+
+
+typedef int32_t unit_type;
+
+
+#define	UNIT_ERROR	((unit_type) 1 << (sizeof(unit_type)*8-1))
+
+
+struct coord {
+	unit_type x, y;
+};
+
+
+static inline unit_type mil_to_units(double mil)
+{
+	return mil*MIL_UNITS;
+}
+
+
+static inline unit_type mm_to_units(double mm)
+{
+	return mm*MM_UNITS;
+}
+
+
+static inline double units_to_mm(unit_type u)
+{
+	return (double) u/MM_UNITS;
+}
+
+
+static inline double units_to_kicad(unit_type u)
+{
+	return (double) u/KICAD_UNIT;
+}
+
+#endif /* !COORD_H */

Added: developers/werner/fped/error.c
===================================================================
--- developers/werner/fped/error.c	                        (rev 0)
+++ developers/werner/fped/error.c	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,55 @@
+/*
+ * error.c - Error reporting
+ *
+ * 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 <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "error.h"
+
+
+int lineno = 1;
+
+extern char *yytext;
+
+
+void __attribute__((noreturn)) yyerrorf(const char *fmt, ...)
+{
+	va_list ap;
+
+	fprintf(stderr, "%d: ", lineno);
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "near \"%s\"\n", yytext);
+	exit(1);
+}
+
+
+void __attribute__((noreturn)) yyerror(const char *s)
+{
+	yyerrorf("%s", s);
+}
+
+
+void fail(const char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+	fprintf(stderr, "\n");
+	exit(1);
+}
+

Added: developers/werner/fped/error.h
===================================================================
--- developers/werner/fped/error.h	                        (rev 0)
+++ developers/werner/fped/error.h	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,26 @@
+/*
+ * error.h - Error reporting
+ *
+ * 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 ERROR_H
+#define ERROR_H
+
+
+int lineno;
+
+
+void __attribute__((noreturn)) yyerrorf(const char *fmt, ...);
+void __attribute__((noreturn)) yyerror(const char *s);
+
+void __attribute__((noreturn)) fail(const char *fmt, ...);
+
+#endif /* !ERROR_H */

Added: developers/werner/fped/expr.c
===================================================================
--- developers/werner/fped/expr.c	                        (rev 0)
+++ developers/werner/fped/expr.c	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,148 @@
+/*
+ * expr.c - Expressions and values
+ *
+ * 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 "util.h"
+#include "error.h"
+#include "obj.h"
+#include "expr.h"
+
+
+double op_num(const struct expr *self, const struct frame *frame)
+{
+	return self->u.num;
+}
+
+
+static double eval_var(const struct frame *frame, const char *name)
+{
+	const struct table *table;
+	const struct loop *loop;
+	const struct value *value;
+	const struct var *var;
+
+	for (table = frame->tables; table; table = table->next) {
+		value = table->curr_row->values;
+		for (var = table->vars; var; var = var->next) {
+			if (var->name == name)
+				return eval_num(value->expr, frame);
+			value = value->next;
+		}
+	}
+	for (loop = frame->loops; loop; loop = loop->next)
+		if (loop->var == name)
+			return loop->curr_value;
+	if (frame->curr_parent)
+		return eval_var(frame->curr_parent, name);
+	return UNDEF;
+}
+
+
+double op_var(const struct expr *self, const struct frame *frame)
+{
+	double res;
+
+	res = eval_var(frame, self->u.var);
+	if (res == UNDEF)
+		fail("undefined variable \"%s\"", self->u.var);
+	return res;
+}
+
+
+double op_minus(const struct expr *self, const struct frame *frame)
+{
+	double res;
+
+	res = eval_num(self->u.op.a, frame);
+	return res == UNDEF ? UNDEF : -res;
+}
+
+
+#define	BINARY					\
+	double a, b;				\
+						\
+	a = eval_num(self->u.op.a, frame);	\
+	b = eval_num(self->u.op.b, frame);	\
+	if (a == UNDEF || b == UNDEF)		\
+		return UNDEF;			\
+
+
+double op_add(const struct expr *self, const struct frame *frame)
+{
+	BINARY;
+	return a+b;
+}
+
+
+double op_sub(const struct expr *self, const struct frame *frame)
+{
+	BINARY;
+	return a-b;
+}
+
+
+double op_mult(const struct expr *self, const struct frame *frame)
+{
+	BINARY;
+	return a*b;
+}
+
+
+double op_div(const struct expr *self, const struct frame *frame)
+{
+	BINARY;
+	if (!b) {
+		fail("Division by zero");
+		return UNDEF;
+	}
+	return a/b;
+}
+
+
+struct expr *new_op(op_type op)
+{
+	struct expr *expr;
+
+	expr = alloc_type(struct expr);
+	expr->op = op;
+	return expr;
+}
+
+
+struct expr *binary_op(op_type op, struct expr *a, struct expr *b)
+{
+	struct expr *expr;
+
+	expr = new_op(op);
+	expr->u.op.a = a;
+	expr->u.op.b = b;
+	return expr;
+}
+
+
+double eval(const struct expr *expr, const struct frame *frame)
+{
+	return expr->op(expr, frame);
+}
+
+char *eval_str(const struct frame *frame, const struct expr *expr)
+{
+	abort();
+}
+
+
+double eval_num(const struct expr *expr, const struct frame *frame)
+{
+	return expr->op(expr, frame);
+}

Added: developers/werner/fped/expr.h
===================================================================
--- developers/werner/fped/expr.h	                        (rev 0)
+++ developers/werner/fped/expr.h	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,58 @@
+/*
+ * expr.h - Expressions and values
+ *
+ * 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 EXPR_H
+#define EXPR_H
+
+#include <math.h>
+
+
+#define UNDEF HUGE_VAL
+
+
+struct frame;
+struct expr;
+
+
+typedef double (*op_type)(const struct expr *self, const struct frame *frame);
+
+struct expr {
+	op_type op;
+	union {
+		double num;
+		const char *var;
+		struct {
+			struct expr *a;
+			struct expr *b;
+		} op;
+	} u;
+};
+
+
+double op_num(const struct expr *self, const struct frame *frame);
+double op_var(const struct expr *self, const struct frame *frame);
+
+double op_minus(const struct expr *self, const struct frame *frame);
+
+double op_add(const struct expr *self, const struct frame *frame);
+double op_sub(const struct expr *self, const struct frame *frame);
+double op_mult(const struct expr *self, const struct frame *frame);
+double op_div(const struct expr *self, const struct frame *frame);
+
+struct expr *new_op(op_type op);
+struct expr *binary_op(op_type op, struct expr *a, struct expr *b);
+
+char *eval_str(const struct frame *frame, const struct expr *expr);
+double eval_num(const struct expr *expr, const struct frame *frame);
+
+#endif /* !EXPR_H */

Added: developers/werner/fped/fpd.l
===================================================================
--- developers/werner/fped/fpd.l	                        (rev 0)
+++ developers/werner/fped/fpd.l	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,59 @@
+%{
+/*
+ * fpd.l - FootPrint Definition language
+ *
+ * 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 "util.h"
+#include "coord.h"
+#include "error.h"
+
+#include "y.tab.h"
+
+%}
+
+
+NUM	[0-9]+\.?[0-9]*
+SP	[\t ]*
+
+
+%%
+
+
+".frame"			return TOK_FRAME;
+".table"			return TOK_TABLE;
+".vec"				return TOK_VEC;
+".pad"				return TOK_PAD;
+".rect"				return TOK_RECT;
+".line"				return TOK_LINE;
+".arc"				return TOK_ARC;
+
+[a-zA-Z_][a-zA-Z_0-9]*		{ yylval.id = unique(yytext);
+				  return ID; }
+
+{NUM}{SP}mm			{ sscanf(yytext, "%lf", &yylval.num);
+				  yylval.num = mm_to_units(yylval.num);
+				  return NUMBER; }
+{NUM}{SP}mil			{ sscanf(yytext, "%lf", &yylval.num);
+				  yylval.num = mil_to_units(yylval.num);
+				  return NUMBER; }
+{NUM}				{ sscanf(yytext, "%lf", &yylval.num);
+				  return NUMBER; }
+
+\"(\\[^\n\t]|[^\\"\n\t])*\"	{ *strrchr(yytext, '"') = 0;
+				  yylval.str = stralloc(yytext+1);
+				  return STRING; }
+
+{SP}				;
+\n				lineno++;
+^#.*\n				lineno++;
+
+.				return *yytext;

Added: developers/werner/fped/fpd.y
===================================================================
--- developers/werner/fped/fpd.y	                        (rev 0)
+++ developers/werner/fped/fpd.y	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,444 @@
+%{
+/*
+ * fpd.y - FootPrint Definition language
+ *
+ * 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 "util.h"
+#include "error.h"
+#include "expr.h"
+#include "obj.h"
+
+
+static struct frame *curr_frame;
+static struct frame **next_frame;
+static struct table **next_table;
+static struct loop **next_loop;
+static struct vec **next_vec;
+static struct obj **next_obj;
+static int n_vars, n_values;
+static struct vec *last_vec = NULL;
+
+
+static struct frame *find_frame(const char *name)
+{
+	struct frame *f;
+
+	for (f = frames; f; f = f->next)
+		if (f->name == name)
+			return f;
+	return NULL;
+}
+
+
+static struct vec *find_vec(const char *name)
+{
+	struct vec *v;
+
+	for (v = curr_frame->vecs; v; v = v->next)
+		if (v->name == name)
+			return v;
+	return NULL;
+}
+
+
+static void set_frame(struct frame *frame)
+{
+	curr_frame = frame;
+	next_table = &frame->tables;
+	next_loop = &frame->loops;
+	next_vec = &frame->vecs;
+	next_obj = &frame->objs;
+	last_vec = NULL;
+}
+
+
+static void make_var(const char *id, struct expr *expr)
+{
+	struct table *table;
+
+	table = zalloc_type(struct table);
+	table->vars = zalloc_type(struct var);
+	table->vars->name = id;
+	table->rows = zalloc_type(struct row);
+	table->rows->values = zalloc_type(struct value);
+	table->rows->values->expr = expr;
+	*next_table = table;
+	next_table = &table->next;
+}
+
+
+static void make_loop(const char *id, struct expr *from, struct expr *to)
+{
+	struct loop *loop;
+
+	loop = alloc_type(struct loop);
+	loop->var = id;
+	loop->from = from;
+	loop->to = to;
+	loop->next = NULL;
+	*next_loop = loop;
+	next_loop = &loop->next;
+}
+
+
+static struct obj *new_obj(enum obj_type type)
+{
+	struct obj *obj;
+
+	obj = alloc_type(struct obj);
+	obj->type = type;
+	obj->next = NULL;
+	return obj;
+}
+
+
+%}
+
+
+%union {
+	double num;
+	char *str;
+	const char *id;
+	struct expr *expr;
+	struct frame *frame;
+	struct table *table;
+	struct var *var;
+	struct row *row;
+	struct value *value;
+	struct vec *vec;
+	struct obj *obj;
+};
+
+
+%token		TOK_FRAME TOK_TABLE TOK_VEC TOK_PAD TOK_RECT TOK_LINE TOK_ARC
+
+%token	<num>	NUMBER
+%token	<str>	STRING
+%token	<id>	ID
+
+%type	<table>	table
+%type	<var>	vars var
+%type	<row>	rows
+%type	<value>	row value
+%type	<vec>	vec base opt_base
+%type	<obj>	obj
+%type	<expr>	opt_range
+%type	<expr>	expr add_expr mult_expr unary_expr primary_expr
+
+%%
+
+all:
+		{
+			frames = zalloc_type(struct frame);
+			next_frame = &frames->next;
+			set_frame(frames);
+		}
+	frame_defs frame_items
+	;
+
+frame_defs:
+	| frame_defs frame_def
+	;
+
+frame_def:
+	TOK_FRAME ID '{'
+		{
+			if (find_frame($2))
+				yyerrorf("duplicate frame \"%s\"", $2);
+			*next_frame = zalloc_type(struct frame);
+			(*next_frame)->name = $2;
+			set_frame(*next_frame);
+			next_frame = &(*next_frame)->next;
+
+		}
+	    frame_items '}'
+		{
+			set_frame(frames);
+		}
+	;
+
+frame_items:
+	| frame_item frame_items
+	;
+
+frame_item:
+	table
+	| ID '=' expr opt_range
+		{
+			if ($4)
+				make_loop($1, $3, $4);
+			else
+				make_var($1, $3);
+		}
+	| vec
+	| ID '=' vec
+		{
+			if (find_vec($1))
+				yyerrorf("duplicate vector \"%s\"", $1);
+			$3->name = $1;
+		}
+	| obj
+		{
+			*next_obj = $1;
+			next_obj = &$1->next;
+		}
+	;
+
+opt_range:
+		{
+			$$ = NULL;
+		}
+	| ',' expr
+		{
+			$$ = $2;
+		}
+	;
+
+table:
+	TOK_TABLE
+		{
+			$<table>$ = zalloc_type(struct table);
+			*next_table = $<table>$;
+			n_vars = 0;
+		}
+	    '{' vars '}' rows
+		{
+			$$ = $<table>2;
+			$$->vars = $4;
+			$$->rows = $6;
+			next_table = &$$->next;
+		}
+	;
+
+vars:
+	var
+		{
+			$$ = $1;
+		}
+	| vars ',' var
+		{
+			struct var **walk;
+
+			$$ = $1;
+			for (walk = &$$; *walk; walk = &(*walk)->next);
+			*walk = $3;
+		}
+	;
+
+var:
+	ID
+		{
+			$$ = alloc_type(struct var);
+			$$->name = $1;
+			$$->next = NULL;
+			n_vars++;
+		}
+	;
+	
+	
+rows:
+		{
+			$$ = NULL;
+		}
+	| '{'
+		{
+			n_values = 0;
+		}
+	    row '}'
+		{
+			if (n_vars != n_values)
+				yyerrorf("table has %d variables but row has "
+				    "%d values", n_vars, n_values);
+			$<row>$ = alloc_type(struct row);
+			$<row>$->values = $3;
+		}
+	    rows
+		{
+			$$ = $<row>5;
+			$$->next = $6;
+		}
+	;
+
+row:
+	value
+		{
+			$$ = $1;
+		}
+	| row ',' value
+		{
+			struct value **walk;
+
+			$$ = $1;
+			for (walk = &$$; *walk; walk = &(*walk)->next);
+			*walk = $3;
+		}
+	;
+
+value:
+	expr
+		{
+			$$ = alloc_type(struct value);
+			$$->expr = $1;
+			$$->next = NULL;
+			n_values++;
+		}
+	;
+
+vec:
+	TOK_VEC base expr ',' expr
+		{
+			$$ = alloc_type(struct vec);
+			$$->base = $2;
+			if ($2)
+				$2->n_refs++;
+			$$->x = $3;
+			$$->y = $5;
+			$$->n_refs = 0;
+			$$->next = NULL;
+			last_vec = $$;
+			*next_vec = $$;
+			next_vec = &$$->next;
+		}
+	;
+
+base:
+	'@'
+		{
+			$$ = NULL;
+		}
+	| '.'
+		{
+			$$ = last_vec;
+			if (!$$)
+				yyerrorf(". without predecessor");
+		}
+	| ID
+		{
+			$$ = find_vec($1);
+			if (!$$)
+				yyerrorf("unknown vector \"%s\"", $1);
+		}
+	;
+
+obj:
+	TOK_PAD STRING base base
+		{
+			$$ = new_obj(ot_pad);
+			$$->base = $3;
+			$$->u.pad.name = $2;
+			$$->u.pad.other = $4;
+		}
+	| TOK_RECT base base
+		{
+			$$ = new_obj(ot_rect);
+			$$->base = $2;
+			$$->u.rect.other = $3;
+		}
+	| TOK_LINE base base
+		{
+			$$ = new_obj(ot_line);
+			$$->base = $2;
+			$$->u.line.other = $3;
+		}
+	| TOK_ARC base base opt_base
+		{
+			$$ = new_obj(ot_arc);
+			$$->base = $2;
+			$$->u.arc.start = $3;
+			$$->u.arc.end = $3;
+		}
+	| TOK_FRAME ID base
+		{
+			$$ = new_obj(ot_frame);
+			$$->base = $3;
+			$$->u.frame = find_frame($2);
+			if (!$$->u.frame)
+				yyerrorf("unknown frame \"%s\"", $2);
+		}
+	;
+
+opt_base:
+		{
+			$$ = NULL;
+		}
+	| ',' base
+		{
+			$$ = $2;
+		}
+	;
+
+expr:
+	add_expr
+		{
+			$$ = $1;
+		}
+	;
+
+add_expr:
+	mult_expr
+		{
+			$$ = $1;
+		}
+	| add_expr '+' mult_expr
+		{
+			$$ = binary_op(op_add, $1, $3);
+		}
+	| add_expr '-' mult_expr
+		{
+			$$ = binary_op(op_sub, $1, $3);
+		}
+	;
+
+mult_expr:
+	unary_expr
+		{
+			$$ = $1;
+		}
+	| mult_expr '*' unary_expr
+		{
+			$$ = binary_op(op_mult, $1, $3);
+		}
+	| mult_expr '/' unary_expr
+		{
+			$$ = binary_op(op_div, $1, $3);
+		}
+	;
+
+unary_expr:
+	primary_expr
+		{
+			$$ = $1;
+		}
+	| '-' primary_expr
+		{
+			$$ = binary_op(op_minus, $2, NULL);
+		}
+	;
+
+primary_expr:
+	NUMBER
+		{
+			$$ = new_op(op_num);
+			$$->u.num = $1;
+		}
+	| ID
+		{
+			$$ = new_op(op_var);
+			$$->u.var = $1;
+		}
+	| '(' expr ')'
+		{
+			$$ = $2;
+		}
+	;

Added: developers/werner/fped/fped.c
===================================================================
--- developers/werner/fped/fped.c	                        (rev 0)
+++ developers/werner/fped/fped.c	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,64 @@
+/*
+ * fped.c - Footprint editor, main function
+ *
+ * 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 <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+
+#include "obj.h"
+#include "inst.h"
+#include "gui.h"
+
+
+int yyparse(void);
+
+
+static void load_file(const char *name)
+{
+	int fd;
+
+	fd = open(name, O_RDONLY);
+	if (fd < 0) {
+		perror(name);
+		exit(1);
+	}
+	if (dup2(fd, 0) < 0) {
+		perror("dup2");
+		exit(1);
+	}
+	(void) yyparse();
+}
+
+
+int main(int argc, char **argv)
+{
+	int error;
+
+	error = gui_init(&argc, &argv);
+	if (error)
+		return error;
+	if (argc > 1) {
+		load_file(argv[1]);
+		argc--;
+		argv++;
+	}
+	instantiate();
+	inst_debug();
+	error = gui_main(argc, argv);
+	if (error)
+		return error;
+	return 0;
+}

Added: developers/werner/fped/gui.c
===================================================================
--- developers/werner/fped/gui.c	                        (rev 0)
+++ developers/werner/fped/gui.c	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,195 @@
+/*
+ * gui.c - Editor GUI core
+ *
+ * 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 <math.h>
+#include <gtk/gtk.h>
+
+#include "obj.h"
+#include "inst.h"
+#include "gui_inst.h"
+#include "gui_style.h"
+#include "gui.h"
+
+
+static void make_menu_bar(GtkWidget *vbox)
+{
+	GtkWidget *bar;
+	GtkWidget *file_menu, *file, *quit;
+
+	bar = gtk_menu_bar_new();
+	gtk_box_pack_start(GTK_BOX(vbox), bar, FALSE, FALSE, 0);
+
+	file_menu = gtk_menu_new();
+
+	file = gtk_menu_item_new_with_label("File");
+	gtk_menu_item_set_submenu(GTK_MENU_ITEM(file), file_menu);
+	gtk_menu_shell_append(GTK_MENU_SHELL(bar), file);
+
+	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",
+	    G_CALLBACK(gtk_main_quit), NULL);
+}
+
+
+static void add_frame(GtkListStore  *list, const char *name)
+{
+	GtkTreeIter iter;
+
+	gtk_list_store_append(list, &iter);
+	gtk_list_store_set(list, &iter, 0, name, -1);
+}
+
+
+static void show_frames(GtkWidget *frame_list)
+{
+	GtkListStore *list;
+	struct frame *f;
+
+	list = gtk_list_store_new(1, G_TYPE_STRING);
+
+	for (f = frames; f; f = f->next)
+		add_frame(list, f->name ? f->name : "(root)");
+
+	gtk_tree_view_set_model(GTK_TREE_VIEW(frame_list),
+	    GTK_TREE_MODEL(list));
+	g_object_unref(list);
+}
+
+
+static gboolean expose_event_callback(GtkWidget *widget, GdkEventExpose *event,
+     gpointer data)
+{
+	static int need_style = 1;
+	struct bbox bbox;
+	unit_type h, w;
+	int sx, sy;
+	float aw, ah;
+
+	struct draw_ctx ctx = {
+		.widget = widget,
+		.scale = 1000,
+		.center = {
+			.x = 0,
+			.y = 0,
+		},
+	};
+
+	if (need_style) {
+		gui_setup_style(widget->window);
+		need_style = 0;
+	}
+
+	aw = widget->allocation.width;
+	ah = widget->allocation.height;
+	gdk_draw_rectangle(widget->window, gc_bg, TRUE, 0, 0, aw, ah);
+	bbox = inst_get_bbox();
+	ctx.center.x = (bbox.min.x+bbox.max.x)/2;
+	ctx.center.y = (bbox.min.y+bbox.max.y)/2;
+	h = bbox.max.x-bbox.min.x;
+	w = bbox.max.y-bbox.min.y;
+	aw -= 2*CANVAS_CLEARANCE;
+	ah -= 2*CANVAS_CLEARANCE;
+	if (aw < 1)
+		aw = 1;
+	if (ah < 1)
+		ah = 1;
+	sx = ceil(h/aw);
+	sy = ceil(w/ah);
+	ctx.scale = sx > sy ? sx : sy > 0 ? sy : 1;
+	
+	inst_draw(&ctx);
+	return TRUE;
+}
+
+
+static void make_center_area(GtkWidget *vbox)
+{
+	GtkWidget *hbox;
+	GtkWidget *frame_list, *sep, *canvas;
+	GdkColor black = { 0, 0, 0, 0 };
+
+	hbox = gtk_hbox_new(FALSE, 0);
+
+	frame_list = gtk_tree_view_new();
+	gtk_box_pack_start(GTK_BOX(hbox), frame_list, FALSE, TRUE, 0);
+
+	gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(frame_list),
+	    -1, "Frame", gtk_cell_renderer_text_new(), "text", 0, NULL);
+
+	show_frames(frame_list);
+
+	sep = gtk_drawing_area_new();
+	gtk_box_pack_start(GTK_BOX(hbox), sep, FALSE, TRUE, 2);
+	gtk_widget_modify_bg(sep, GTK_STATE_NORMAL, &black);
+
+	canvas = gtk_drawing_area_new();
+	gtk_box_pack_start(GTK_BOX(hbox), canvas, TRUE, TRUE, 0);
+	gtk_widget_modify_bg(canvas, GTK_STATE_NORMAL, &black);
+	g_signal_connect (G_OBJECT(canvas), "expose_event",
+	    G_CALLBACK(expose_event_callback), NULL);
+
+	gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 0);
+}
+
+
+static void make_input_area(GtkWidget *vbox)
+{
+	GtkWidget *entry;
+
+	entry = gtk_entry_new();
+	gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE, 0);
+}
+
+
+static void make_screen(GtkWidget *root)
+{
+	GtkWidget *vbox;
+
+	vbox = gtk_vbox_new(FALSE, 0);
+	gtk_container_add(GTK_CONTAINER(root), vbox);
+
+	make_menu_bar(vbox);
+	make_center_area(vbox);
+	make_input_area(vbox);
+}
+
+
+int gui_init(int *argc, char ***argv)
+{
+	gtk_init(argc, argv);
+	return 0;
+}
+
+
+int gui_main(int argc, char **argv)
+{
+	GtkWidget *root;
+
+	root = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_position(GTK_WINDOW(root), GTK_WIN_POS_CENTER);
+	gtk_window_set_default_size(GTK_WINDOW(root), 600, 400);
+	gtk_window_set_title(GTK_WINDOW(root), "fped");
+
+	g_signal_connect_swapped(G_OBJECT(root), "destroy",
+	    G_CALLBACK(gtk_main_quit), NULL);
+
+	make_screen(root);
+
+	gtk_widget_show_all(root);
+
+	gtk_main();
+
+	return 0;
+}

Added: developers/werner/fped/gui.h
===================================================================
--- developers/werner/fped/gui.h	                        (rev 0)
+++ developers/werner/fped/gui.h	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,23 @@
+/*
+ * gui.h - Editor GUI core
+ *
+ * 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 GUI_H
+#define GUI_H
+
+#include <gtk/gtk.h>
+
+
+int gui_init(int *argc, char ***argv);
+int gui_main(int argc, char **argv);
+
+#endif /* !GUI_H */

Added: developers/werner/fped/gui_inst.c
===================================================================
--- developers/werner/fped/gui_inst.c	                        (rev 0)
+++ developers/werner/fped/gui_inst.c	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,148 @@
+/*
+ * gui_inst.c - GUI, instance functions
+ *
+ * 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 <gtk/gtk.h>
+
+#include "inst.h"
+#include "gui.h"
+#include "gui_style.h"
+#include "gui_inst.h"
+
+
+#define DA	GDK_DRAWABLE(ctx->widget->window)
+
+
+static struct coord translate(const struct draw_ctx *ctx, struct coord pos)
+{
+	pos.x -= ctx->center.x;
+	pos.y -= ctx->center.y;
+	pos.x /= ctx->scale;
+	pos.y /= ctx->scale;
+	pos.y = -pos.y;
+	pos.x += ctx->widget->allocation.width/2;
+	pos.y += ctx->widget->allocation.height/2;
+fprintf(stderr, "%d %d\n", (int) pos.x, (int) pos.y);
+	return pos;
+}
+
+
+/* ----- drawing primitives ------------------------------------------------ */
+
+
+static void draw_arc(struct draw_ctx *ctx, GdkGC *gc, int fill,
+    int x, int y, int r, double a1, double a2)
+{
+	gdk_draw_arc(DA, gc, fill, x-r, y-r, 2*r, 2*r, a1*64, a2*64);
+}
+
+
+static void draw_circle(struct draw_ctx *ctx, GdkGC *gc, int fill,
+    int x, int y, int r)
+{
+	draw_arc(ctx, gc, fill, x, y, r, 0, 360);
+}
+
+
+static void draw_eye(struct draw_ctx *ctx, GdkGC *gc, struct coord center,
+    int r1, int r2)
+{
+	center = translate(ctx, center);
+	draw_circle(ctx, gc, TRUE, center.x, center.y, r1);
+	draw_circle(ctx, gc, FALSE, center.x, center.y, r2);
+}
+
+
+/* ----- vec --------------------------------------------------------------- */
+
+
+void gui_draw_vec(struct inst *self, struct draw_ctx *ctx)
+{
+	struct coord from = translate(ctx, self->base);
+	struct coord to = translate(ctx, self->u.end);
+
+	draw_circle(ctx, gc_vec_bg, FALSE, to.x, to.y, VEC_EYE_R);
+	gdk_draw_line(DA, gc_vec_bg, from.x, from.y, to.x, to.y);
+
+}
+
+
+/* ----- line -------------------------------------------------------------- */
+
+
+void gui_draw_line(struct inst *self, struct draw_ctx *ctx)
+{
+	struct coord min = translate(ctx, self->bbox.min);
+	struct coord max = translate(ctx, self->bbox.max);
+
+	gdk_draw_line(DA, gc_line_bg, min.x, min.x, max.x, max.y);
+}
+
+
+/* ----- rect -------------------------------------------------------------- */
+
+
+void gui_draw_rect(struct inst *self, struct draw_ctx *ctx)
+{
+	struct coord min = translate(ctx, self->bbox.min);
+	struct coord max = translate(ctx, self->bbox.max);
+
+	gdk_draw_rectangle(DA, gc_rect_bg, FALSE,
+	    min.x, max.y, max.x-min.x+1, min.y-max.y+1);
+}
+
+
+/* ----- pad --------------------------------------------------------------- */
+
+
+void gui_draw_pad(struct inst *self, struct draw_ctx *ctx)
+{
+	struct coord min = translate(ctx, self->bbox.min);
+	struct coord max = translate(ctx, self->bbox.max);
+
+	/* @@@ name */
+	gdk_draw_rectangle(DA, gc_pad_bg, TRUE,
+	    min.x, max.y, max.x-min.x+1, min.y-max.y+1);
+}
+
+
+/* ----- arc --------------------------------------------------------------- */
+
+
+void gui_draw_arc(struct inst *self, struct draw_ctx *ctx)
+{
+	struct coord center = translate(ctx, self->base);
+
+	draw_arc(ctx, gc_arc_bg, FALSE, center.x, center.y,
+	    self->u.arc.r/ctx->scale, self->u.arc.a1, self->u.arc.a2);
+}
+
+
+/* ----- frame ------------------------------------------------------------- */
+
+
+void gui_draw_frame(struct inst *self, struct draw_ctx *ctx)
+{
+	struct coord pos = translate(ctx, self->base);
+	struct coord corner = { self->bbox.min.x, self->bbox.max.y };
+
+	draw_eye(ctx, gc_frame_bg, pos, FRAME_EYE_R1, FRAME_EYE_R2);
+	if (!self->u.frame.ref->name)
+		return;
+	corner = translate(ctx, corner);
+	corner.x -= FRAME_CLEARANCE;
+	corner.y -= FRAME_CLEARANCE;
+	gdk_draw_line(DA, gc_frame_bg,
+	    corner.x, corner.y, corner.x+100, corner.y);
+	gdk_draw_line(DA, gc_frame_bg,
+	    corner.x, corner.y, corner.x, corner.y+20);
+}

Added: developers/werner/fped/gui_inst.h
===================================================================
--- developers/werner/fped/gui_inst.h	                        (rev 0)
+++ developers/werner/fped/gui_inst.h	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,37 @@
+/*
+ * gui_inst.h - GUI, instance functions
+ *
+ * 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 GUI_INST_H
+#define GUI_INST_H
+
+#include <gtk/gtk.h>
+
+#include "coord.h"
+#include "inst.h"
+
+
+struct draw_ctx {
+	GtkWidget *widget;
+	int scale;
+	struct coord center;
+};
+
+
+void gui_draw_vec(struct inst *self, struct draw_ctx *ctx);
+void gui_draw_line(struct inst *self, struct draw_ctx *ctx);
+void gui_draw_rect(struct inst *self, struct draw_ctx *ctx);
+void gui_draw_pad(struct inst *self, struct draw_ctx *ctx);
+void gui_draw_arc(struct inst *self, struct draw_ctx *ctx);
+void gui_draw_frame(struct inst *self, struct draw_ctx *ctx);
+
+#endif /* !GUI_INST_H */

Added: developers/werner/fped/gui_style.c
===================================================================
--- developers/werner/fped/gui_style.c	                        (rev 0)
+++ developers/werner/fped/gui_style.c	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,64 @@
+/*
+ * gui_style.c - GUI, style definitions
+ *
+ * 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 <gtk/gtk.h>
+
+#include "gui_style.h"
+
+
+#define	GC(spec)	gc(drawable, (spec))
+
+
+static GdkColor get_color(GdkColormap *cmap, const char *spec)
+{
+	GdkColor color;
+
+	if (!gdk_color_parse(spec, &color))
+		abort();
+	if (!gdk_colormap_alloc_color(cmap, &color, FALSE, TRUE))
+		abort();
+	return color;
+}
+
+
+static GdkGC *gc(GdkDrawable *drawable, const char *spec)
+{
+	GdkGCValues gc_values = {
+		.background = get_color(gdk_drawable_get_colormap(drawable),
+		    "black"),
+		.foreground = get_color(gdk_drawable_get_colormap(drawable),
+		    spec),
+	};
+
+	return gdk_gc_new_with_values(drawable, &gc_values,
+	     GDK_GC_FOREGROUND | GDK_GC_BACKGROUND);
+}
+
+
+void gui_setup_style(GdkDrawable *drawable)
+{
+	gc_bg = GC("#000000");
+	gc_vec_bg = GC("#ffff00");
+	gc_vec_fg = GC("#ffff00");
+	gc_line_bg = GC("#ffffff");
+	gc_line_fg = GC("#ffffff");
+	gc_rect_bg = gc_line_bg;
+	gc_rect_fg = gc_line_fg;
+	gc_pad_bg = GC("#ff0000");
+	gc_pad_fg = GC("#ff0000");
+	gc_arc_bg = gc_line_bg;
+	gc_arc_fg = gc_line_fg;
+	gc_frame_bg = GC("#00ff00");
+	gc_frame_fg = GC("#00ff00");
+}

Added: developers/werner/fped/gui_style.h
===================================================================
--- developers/werner/fped/gui_style.h	                        (rev 0)
+++ developers/werner/fped/gui_style.h	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,37 @@
+/*
+ * gui_style.h - GUI, style definitions
+ *
+ * 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 GUI_STYLE_H
+#define	GUI_STYLE_H
+
+#define	CANVAS_CLEARANCE	10
+
+#define	VEC_ARROW		6
+#define	VEC_EYE_R		4
+
+#define	FRAME_CLEARANCE		5
+#define	FRAME_EYE_R1		3
+#define	FRAME_EYE_R2		5
+
+
+GdkGC *gc_bg;
+GdkGC *gc_vec_bg, *gc_vec_fg;
+GdkGC *gc_line_bg, *gc_line_fg;
+GdkGC *gc_rect_bg, *gc_rect_fg;
+GdkGC *gc_pad_bg, *gc_pad_fg;
+GdkGC *gc_arc_bg, *gc_arc_fg;
+GdkGC *gc_frame_bg, *gc_frame_fg;
+
+void gui_setup_style(GdkDrawable *drawable);
+
+#endif /* !GUI_STYLE_H */

Added: developers/werner/fped/inst.c
===================================================================
--- developers/werner/fped/inst.c	                        (rev 0)
+++ developers/werner/fped/inst.c	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,296 @@
+/*
+ * inst.c - Instance structures
+ *
+ * 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 <math.h>
+
+#include "util.h"
+#include "coord.h"
+#include "obj.h"
+#include "gui_inst.h"
+#include "inst.h"
+
+
+static struct inst *insts = NULL, **next_inst;
+struct inst *curr_frame = NULL;
+
+
+static void update_bbox(struct bbox *bbox, struct coord coord)
+{
+	if (bbox->min.x > coord.x)
+		bbox->min.x = coord.x;
+	if (bbox->max.x < coord.x)
+		bbox->max.x = coord.x;
+	if (bbox->min.y > coord.y)
+		bbox->min.y = coord.y;
+	if (bbox->max.y < coord.y)
+		bbox->max.y = coord.y;
+}
+
+
+static void propagate_bbox(const struct inst *inst)
+{
+	update_bbox(&curr_frame->bbox, inst->bbox.min);
+	update_bbox(&curr_frame->bbox, inst->bbox.max);
+}
+
+
+static struct inst *add_inst(const struct inst_ops *ops, struct coord base)
+{
+	struct inst *inst;
+
+	inst = alloc_type(struct inst);
+	inst->ops = ops;
+	inst->base = inst->bbox.min = inst->bbox.max = base;
+	inst->next = NULL;
+	*next_inst = inst;
+	next_inst = &inst->next;
+	return inst;
+}
+
+
+/* ----- vec --------------------------------------------------------------- */
+
+
+static void vec_op_debug(struct inst *self)
+{
+	printf("vec %lg, %lg -> %lg, %lg\n",
+	    units_to_mm(self->base.x), units_to_mm(self->base.y),
+	    units_to_mm(self->u.end.x), units_to_mm(self->u.end.y));
+}
+
+
+static struct inst_ops vec_ops = {
+	.debug	= vec_op_debug,
+	.draw	= gui_draw_vec,
+};
+
+
+int inst_vec(struct vec *vec, struct coord base)
+{
+	struct inst *inst;
+
+	inst = add_inst(&vec_ops, base);
+	inst->u.end = vec->pos;
+	update_bbox(&inst->bbox, vec->pos);
+	propagate_bbox(inst);
+	return 1;
+}
+
+
+/* ----- line -------------------------------------------------------------- */
+
+
+static void line_op_debug(struct inst *self)
+{
+	printf("line %lg, %lg / %lg, %lg\n",
+	    units_to_mm(self->base.x), units_to_mm(self->base.y),
+	    units_to_mm(self->u.end.x), units_to_mm(self->u.end.y));
+}
+
+
+static struct inst_ops line_ops = {
+	.debug	= line_op_debug,
+	.draw	= gui_draw_line,
+};
+
+
+int inst_line(struct coord a, struct coord b)
+{
+	struct inst *inst;
+
+	inst = add_inst(&line_ops, a);
+	inst->u.end = b;
+	update_bbox(&inst->bbox, b);
+	propagate_bbox(inst);
+	return 1;
+}
+
+
+/* ----- rect -------------------------------------------------------------- */
+
+
+static void rect_op_debug(struct inst *self)
+{
+	printf("rect %lg, %lg / %lg, %lg\n",
+	    units_to_mm(self->base.x), units_to_mm(self->base.y),
+	    units_to_mm(self->u.end.x), units_to_mm(self->u.end.y));
+}
+
+
+static struct inst_ops rect_ops = {
+	.debug	= rect_op_debug,
+	.draw	= gui_draw_rect,
+};
+
+
+int inst_rect(struct coord a, struct coord b)
+{
+	struct inst *inst;
+
+	inst = add_inst(&rect_ops, a);
+	inst->u.end = b;
+	update_bbox(&inst->bbox, b);
+	propagate_bbox(inst);
+	return 1;
+}
+
+
+/* ----- pad --------------------------------------------------------------- */
+
+
+static void pad_op_debug(struct inst *self)
+{
+	printf("pad \"%s\" %lg, %lg / %lg, %lg\n", self->u.name,
+	    units_to_mm(self->bbox.min.x), units_to_mm(self->bbox.min.y),
+	    units_to_mm(self->bbox.max.x), units_to_mm(self->bbox.max.y));
+}
+
+
+static struct inst_ops pad_ops = {
+	.debug	= pad_op_debug,
+	.draw	= gui_draw_pad,
+};
+
+
+int inst_pad(const char *name, struct coord a, struct coord b)
+{
+	struct inst *inst;
+
+	inst = add_inst(&pad_ops, a);
+	inst->u.name = name;
+	update_bbox(&inst->bbox, b);
+	propagate_bbox(inst);
+	return 1;
+}
+
+
+/* ----- arc --------------------------------------------------------------- */
+
+
+static void arc_op_debug(struct inst *self)
+{
+	printf("arc %lg, %lg radius %lg %lg ... %lg\n",
+	    units_to_mm(self->base.x), units_to_mm(self->base.y),
+	    units_to_mm(self->u.arc.r), self->u.arc.a1, self->u.arc.a2);
+}
+
+
+static struct inst_ops arc_ops = {
+	.debug	= arc_op_debug,
+	.draw	= gui_draw_pad,
+};
+
+
+int inst_arc(struct coord center, struct coord start, struct coord end)
+{
+	struct inst *inst;
+	unit_type r;
+
+	inst = add_inst(&arc_ops, center);
+	r = hypot(start.x-center.x, start.y-center.y);
+	inst->bbox.min.x = center.x-r;
+	inst->bbox.max.x = center.x+r;
+	inst->bbox.min.y = center.x-r;
+	inst->bbox.max.y = center.x+r;
+	propagate_bbox(inst);
+	return 1;
+}
+
+
+/* ----- frame ------------------------------------------------------------- */
+
+
+static void frame_op_debug(struct inst *self)
+{
+	printf("frame %s @ %lg, %lg\n",
+	    self->u.frame.ref->name ? self->u.frame.ref->name : "(root)",
+	    units_to_mm(self->base.x), units_to_mm(self->base.y));
+}
+
+
+static struct inst_ops frame_ops = {
+	.debug	= frame_op_debug,
+	.draw	= gui_draw_frame,
+};
+
+
+void inst_begin_frame(const struct frame *frame, struct coord base)
+{
+	struct inst *inst;
+
+	inst = add_inst(&frame_ops, base);
+	inst->u.frame.ref = frame;
+	inst->u.frame.outer = curr_frame;
+	curr_frame = inst;
+}
+
+
+void inst_end_frame(const struct frame *frame)
+{
+	struct inst *inst = curr_frame;
+
+	curr_frame = curr_frame->u.frame.outer;
+	if (curr_frame)
+		propagate_bbox(inst);
+}
+
+
+/* ----- misc. ------------------------------------------------------------- */
+
+
+struct bbox inst_get_bbox(void)
+{
+	static struct bbox bbox_zero;
+
+	return insts ? insts->bbox : bbox_zero;
+}
+
+
+static void inst_free(void)
+{
+	struct inst *next;
+
+	while (insts) {
+		next = insts->next;
+		free(insts);
+		insts = next;
+	}
+	next_inst = &insts;
+}
+
+
+void inst_reset(void)
+{
+	inst_free();
+}
+
+
+void inst_draw(struct draw_ctx *ctx)
+{
+	struct inst *walk;
+
+	for (walk = insts; walk; walk = walk->next)
+		if (walk->ops->draw)
+			walk->ops->draw(walk, ctx);
+}
+
+
+void inst_debug(void)
+{
+	struct inst *walk;
+
+	for (walk = insts; walk; walk = walk->next)
+		walk->ops->debug(walk);
+}

Added: developers/werner/fped/inst.h
===================================================================
--- developers/werner/fped/inst.h	                        (rev 0)
+++ developers/werner/fped/inst.h	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,69 @@
+/*
+ * inst.h - Instance structures
+ *
+ * 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 INST_H
+#define INST_H
+
+#include <stdio.h>
+
+#include "coord.h"
+#include "obj.h"
+
+
+struct bbox {
+	struct coord min;
+	struct coord max;
+};
+
+struct inst;
+struct draw_ctx;
+
+struct inst_ops {
+	void (*debug)(struct inst *self);
+	void (*save)(FILE *file, struct inst *self);
+	void (*draw)(struct inst *self, struct draw_ctx *ctx);
+};
+
+struct inst {
+	const struct inst_ops *ops;
+	struct coord base;
+	struct bbox bbox;
+	union {
+		struct {
+			const struct frame *ref;
+			struct inst *outer;
+		} frame;
+		const char *name;
+		struct coord end;
+		struct {
+			unit_type r;
+			double a1, a2;
+		} arc;
+	} u;
+	struct inst *next;
+};
+
+
+int inst_vec(struct vec *vec, struct coord base);
+int inst_line(struct coord a, struct coord b);
+int inst_rect(struct coord a, struct coord b);
+int inst_pad(const char *name, struct coord a, struct coord b);
+int inst_arc(struct coord center, struct coord start, struct coord stop);
+void inst_begin_frame(const struct frame *frame, struct coord base); 
+void inst_end_frame(const struct frame *frame);
+struct bbox inst_get_bbox(void);
+void inst_reset(void);
+void inst_draw(struct draw_ctx *ctx);
+void inst_debug(void);
+
+#endif /* !INST_H */

Added: developers/werner/fped/obj.c
===================================================================
--- developers/werner/fped/obj.c	                        (rev 0)
+++ developers/werner/fped/obj.c	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,139 @@
+/*
+ * obj.c - Object definition model
+ *
+ * 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 "expr.h"
+#include "obj.h"
+#include "inst.h"
+
+
+struct frame *frames = NULL;
+
+
+static int generate_frame(struct frame *frame, struct coord base,
+    const struct frame *parent);
+
+
+static int generate_objects(struct frame *frame, struct coord base)
+{
+	struct vec *vec;
+	struct obj *obj;
+	double x, y;
+
+	for (vec = frame->vecs; vec; vec = vec->next) {
+		x = eval_num(vec->x, frame);
+		if (x == UNDEF)
+			return 0;
+		y = eval_num(vec->y, frame);
+		if (y == UNDEF)
+			return 0;
+		vec->pos = vec->base ? vec->base->pos : base;
+		vec->pos.x += x;
+		vec->pos.y += y;
+		if (!inst_vec(vec, base))
+			return 0;
+	}
+	for (obj = frame->objs; obj; obj = obj->next)
+		switch (obj->type) {
+		case ot_frame:
+			if (!generate_frame(obj->u.frame,
+			    obj->base ? obj->base->pos : base, frame))
+				return 0;
+			break;
+		case ot_line:
+			if (!inst_line(obj->base ? obj->base->pos : base,
+			    obj->u.line.other ? obj->u.line.other->pos : base))
+				return 0;
+			break;
+		case ot_rect:
+			if (!inst_rect(obj->base ? obj->base->pos : base,
+			    obj->u.rect.other ? obj->u.rect.other->pos : base))
+				return 0;
+			break;
+		case ot_pad:
+			if (!inst_pad(obj->u.pad.name,
+			    obj->base ? obj->base->pos : base,
+			    obj->u.pad.other ? obj->u.pad.other->pos : base))
+				return 0;
+			break;
+		case ot_arc:
+			if (!inst_arc(obj->base ? obj->base->pos : base,
+			    obj->u.arc.start ? obj->u.arc.start->pos : base,
+			    obj->u.arc.end ? obj->u.arc.end->pos : base))
+				return 0;
+			break;
+		default:
+			abort();
+		}
+	return 1;
+}
+
+
+static int run_loops(struct frame *frame, struct loop *loop,
+    struct coord base)
+{
+	double from, to;
+
+	if (!loop)
+		return generate_objects(frame, base);
+	from = eval_num(loop->from, frame);
+	if (from == UNDEF)
+		return 0;
+	to = eval_num(loop->to, frame);
+	if (from == UNDEF)
+		return 0;
+	for (loop->curr_value = from; loop->curr_value <= to;
+	    loop->curr_value += 1)
+		if (!run_loops(frame, loop->next, base))
+			return 0;
+	return 1;
+}
+
+
+static int iterate_tables(struct frame *frame, struct table *table,
+    struct coord base)
+{
+	if (!table)
+		return run_loops(frame, frame->loops, base);
+	for (table->curr_row = table->rows; table->curr_row;
+	    table->curr_row = table->curr_row->next)
+		if (!iterate_tables(frame, table->next, base))
+			return 0;
+	return 1;
+}
+
+
+static int generate_frame(struct frame *frame, struct coord base,
+    const struct frame *parent)
+{
+	int res;
+
+	/*
+	 * We ensure during construction that frames can never recurse.
+	 */
+	inst_begin_frame(frame, base);
+	frame->curr_parent = parent;
+	res = iterate_tables(frame, frame->tables, base);
+	inst_end_frame(frame);
+	return res;
+}
+
+
+void instantiate(void)
+{
+	struct coord zero = { 0, 0 };
+
+	inst_reset();
+	generate_frame(frames, zero, NULL);
+}

Added: developers/werner/fped/obj.h
===================================================================
--- developers/werner/fped/obj.h	                        (rev 0)
+++ developers/werner/fped/obj.h	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,120 @@
+/*
+ * obj.h - Object definition model
+ *
+ * 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 OBJ_H
+#define OBJ_H
+
+#include "expr.h"
+#include "coord.h"
+
+
+struct var {
+	const char *name;
+	struct var *next;
+};
+
+struct value {
+	struct expr *expr;
+	struct value *next;
+};
+
+struct row {
+	struct value *values;
+	struct row *next;
+};
+
+struct table {
+	struct var *vars;
+	struct row *rows;
+	struct table *next;
+
+	/* used during generation and when editing */
+	struct row *curr_row;
+};
+
+struct loop {
+	const char *var;
+	struct expr *from;
+	struct expr *to;
+	struct loop *next;
+
+	/* used during generation */
+	double curr_value;
+};
+
+struct vec {
+	const char *name; /* NULL if anonymous */
+	struct expr *x;
+	struct expr *y;
+	struct vec *base; /* NULL if frame */
+	int n_refs;
+	struct vec *next;
+
+	/* used during generation */
+	struct coord pos;
+};
+
+struct frame {
+	const char *name; /* NULL if top-level */
+	struct table *tables;
+	struct loop *loops;
+	struct vec *vecs;
+	struct obj *objs;
+	struct frame *next;
+
+	/* used during generation */
+	const struct frame *curr_parent;
+};
+
+enum obj_type {
+	ot_frame,
+	ot_rect,
+	ot_pad,
+	ot_line,
+	ot_arc,
+};
+
+struct rect {
+	struct vec *other; /* NULL if frame origin */
+};
+
+struct pad {
+	const char *name;
+	struct vec *other; /* NULL if frame origin */
+};
+
+struct arc {
+	struct vec *start; /* NULL if frame origin */
+	struct vec *end; /* NULL if this is a circle */
+};
+
+struct obj {
+	enum obj_type type;
+	union {
+		struct frame *frame;
+		struct rect rect;
+		struct rect line;
+		struct pad pad;
+		struct arc arc;
+	} u;
+	struct vec *base;
+	struct obj *next;
+};
+
+
+struct frame *frames;
+
+
+void instantiate(void);
+
+#endif /* !OBJ_H */

Added: developers/werner/fped/qfn.fpd
===================================================================
--- developers/werner/fped/qfn.fpd	                        (rev 0)
+++ developers/werner/fped/qfn.fpd	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,27 @@
+# http://www.nxp.com/acrobat/packages/footprint/SOT616-1_fp_reflow.pdf
+
+.frame pad_up {
+	.vec @ -D/2, 0
+	.vec . D, C
+	.pad "N/4+n" @ .
+}
+
+N = 24
+
+.table
+    { P, Ax, Ay, By, C, D, SLx, SLy, SPx_tot, SPy_tot, SPx, SPy, Gx, Gy, Hx, Hy }
+    { 0.5mm, 5mm, 5mm, 3.2mm, 3.2mm, 0.9mm, 0.24mm, 2.1mm, 2.1mm, 1.2mm,
+      0.45mm, 0.45mm, 4.3mm, 4.3mm, 5.25mm, 5.25mm }
+
+h_x0y0 = .vec @ -Hx/2, -Hy/2
+h_x1y1 = .vec . Hx, Hy
+.rect h_x0y0 h_x1y1
+
+g_x0y0 = .vec @ -Gx/2, -Gy/2
+g_x1y1 = .vec . Gx, Gy
+.rect g_x0y0 g_x1y1
+
+n = 0, N/4-1
+
+.vec @ P*(n-(N-1)/2), -Ay/2
+.frame pad_up .

Added: developers/werner/fped/util.c
===================================================================
--- developers/werner/fped/util.c	                        (rev 0)
+++ developers/werner/fped/util.c	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,38 @@
+/*
+ * util.c - Common utility functions
+ *
+ * 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 <string.h>
+
+#include "util.h"
+
+
+static struct unique {
+	const char *s;
+	struct unique *next;
+} *uniques = NULL;
+
+
+/* @@@ consider using rb trees */
+
+const char *unique(const char *s)
+{
+	struct unique **walk;
+
+	for (walk = &uniques; *walk; walk = &(*walk)->next)
+		if (!strcmp(s, (*walk)->s))
+			return (*walk)->s;
+	*walk = alloc_type(struct unique);
+	(*walk)->s = stralloc(s);
+	(*walk)->next = NULL;
+	return (*walk)->s;
+}

Added: developers/werner/fped/util.h
===================================================================
--- developers/werner/fped/util.h	                        (rev 0)
+++ developers/werner/fped/util.h	2009-07-27 07:30:59 UTC (rev 5325)
@@ -0,0 +1,40 @@
+/*
+ * util.h - Common utility functions
+ *
+ * Written 2006, 2009 by Werner Almesberger
+ * Copyright 2006, 2009 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_type(t)					\
+    ({	t *alloc_type_tmp = (t *) malloc(sizeof(t));	\
+	if (!alloc_type_tmp)				\
+		abort();				\
+	alloc_type_tmp; })
+
+#define zalloc_type(t)					\
+    ({	t *zalloc_type_tmp = alloc_type(t);		\
+	memset(zalloc_type_tmp, 0, sizeof(t));		\
+	zalloc_type_tmp; })
+
+#define stralloc(s)					\
+    ({	char *stralloc_tmp = strdup(s);			\
+	if (!stralloc_tmp)				\
+		abort();				\
+	stralloc_tmp; })
+
+const char *unique(const char *s);
+
+#endif /* !UTIL_H */




More information about the commitlog mailing list