r5335 - developers/werner/fped

werner at docs.openmoko.org werner at docs.openmoko.org
Wed Jul 29 12:59:03 CEST 2009


Author: werner
Date: 2009-07-29 12:59:02 +0200 (Wed, 29 Jul 2009)
New Revision: 5335

Modified:
   developers/werner/fped/TODO
   developers/werner/fped/coord.c
   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/obj.c
   developers/werner/fped/obj.h
   developers/werner/fped/qfn.fpd
   developers/werner/fped/unparse.c
   developers/werner/fped/unparse.h
Log:
- units are now part of value and checked for conformity
- line number is now reported when expressions fail
- corrected line number counting for cpp "noise"



Modified: developers/werner/fped/TODO
===================================================================
--- developers/werner/fped/TODO	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/TODO	2009-07-29 10:59:02 UTC (rev 5335)
@@ -14,7 +14,6 @@
 - decide on table presentation
 - add table/var/loop editor
 - add incremental expression parser (for editor)
-- make units part of value and check for conformity
 - add default unit (combine with grid unit selection ?)
 - consider adding auto/mm/mil selection for each dimension
 - syntax seems a little cryptic. too many dots and at signs.

Modified: developers/werner/fped/coord.c
===================================================================
--- developers/werner/fped/coord.c	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/coord.c	2009-07-29 10:59:02 UTC (rev 5335)
@@ -16,6 +16,23 @@
 #include "coord.h"
 
 
+/* ----- unit conversion --------------------------------------------------- */
+
+
+double mm_to_mil(double mm, int exponent)
+{
+	return mm*pow(MIL_IN_MM, -exponent);
+}
+
+
+double mil_to_mm(double mil, int exponent)
+{
+        return mil*pow(MIL_IN_MM, exponent);
+}
+
+/* ----- vector operations ------------------------------------------------- */
+
+
 struct coord normalize(struct coord v, unit_type len)
 {
 	double f;

Modified: developers/werner/fped/coord.h
===================================================================
--- developers/werner/fped/coord.h	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/coord.h	2009-07-29 10:59:02 UTC (rev 5335)
@@ -22,7 +22,9 @@
 #define	MM_UNITS	(1000.0*MICRON_UNITS)
 #define	KICAD_UNIT	(10.0*MIL_UNITS)
 
+#define	MIL_IN_MM	0.0254
 
+
 typedef int32_t unit_type;
 
 
@@ -58,6 +60,9 @@
 }
 
 
+double mm_to_mil(double mm, int exponent);
+double mil_to_mm(double mil, int exponent);
+
 struct coord normalize(struct coord v, unit_type len);
 struct coord rotate(struct coord v, double angle);
 struct coord add_vec(struct coord a, struct coord b);

Modified: developers/werner/fped/error.c
===================================================================
--- developers/werner/fped/error.c	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/error.c	2009-07-29 10:59:02 UTC (rev 5335)
@@ -50,6 +50,5 @@
 	vfprintf(stderr, fmt, ap);
 	va_end(ap);
 	fprintf(stderr, "\n");
-	exit(1);
 }
 

Modified: developers/werner/fped/error.h
===================================================================
--- developers/werner/fped/error.h	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/error.h	2009-07-29 10:59:02 UTC (rev 5335)
@@ -21,6 +21,6 @@
 void __attribute__((noreturn)) yyerrorf(const char *fmt, ...);
 void __attribute__((noreturn)) yyerror(const char *s);
 
-void __attribute__((noreturn)) fail(const char *fmt, ...);
+void fail(const char *fmt, ...);
 
 #endif /* !ERROR_H */

Modified: developers/werner/fped/expr.c
===================================================================
--- developers/werner/fped/expr.c	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/expr.c	2009-07-29 10:59:02 UTC (rev 5335)
@@ -12,20 +12,102 @@
 
 
 #include <stdlib.h>
+#include <math.h>
 
 #include "util.h"
 #include "error.h"
 #include "obj.h"
+#include "unparse.h"
 #include "expr.h"
 
 
-double op_num(const struct expr *self, const struct frame *frame)
+struct num undef = { .type = nt_none };
+
+
+/* ----- error reporting --------------------------------------------------- */
+
+
+void fail_expr(const struct expr *expr)
 {
+	char *s;
+
+	s = unparse(expr);
+	fail("in \"%s\" at line %d", s, expr->lineno);
+	free(s);
+}
+
+
+/* ----- unit conversion --------------------------------------------------- */
+
+
+const char *str_unit(struct num n)
+{
+	if (n.exponent == 0)
+		return "";
+	if (n.type == nt_mm) {
+		switch (n.exponent) {
+		case -2:
+			return "mm^-2";
+		case -1:
+			return "mm^-1";
+		case 1:
+			return "mm";
+		case 2:
+			return "mm^2";
+		default:
+			abort();
+		}
+	}
+	if (n.type == nt_mil) {
+		switch (n.exponent) {
+		case -2:
+			return "mil^(-2)";
+		case -1:
+			return "mil^(-1)";
+		case 1:
+			return "mil";
+		case 2:
+			return "mil^2";
+		default:
+			abort();
+		}
+	}
+	abort();
+}
+
+
+int to_unit(struct num *n)
+{
+	if (!is_distance(*n)) {
+		fail("%s^%d is not a distance",
+		    n->type == nt_mm ? "mm" : n->type == nt_mil ? "mil" : "?",
+		    n->exponent);
+		return 0;
+	}
+	switch (n->type) {
+	case nt_mil:
+		n->n = mil_to_units(n->n);
+		break;
+	case nt_mm:
+		n->n = mm_to_units(n->n);
+		break;
+	default:
+		abort();
+	}
+	return 1;
+}
+
+
+/* ----- primary expressions ----------------------------------------------- */
+
+
+struct num op_num(const struct expr *self, const struct frame *frame)
+{
 	return self->u.num;
 }
 
 
-double eval_var(const struct frame *frame, const char *name)
+struct num eval_var(const struct frame *frame, const char *name)
 {
 	const struct table *table;
 	const struct loop *loop;
@@ -42,71 +124,136 @@
 	}
 	for (loop = frame->loops; loop; loop = loop->next)
 		if (loop->var == name)
-			return loop->curr_value;
+			return make_num(loop->curr_value);
 	if (frame->curr_parent)
 		return eval_var(frame->curr_parent, name);
-	return UNDEF;
+	return undef;
 }
 
 
-double op_var(const struct expr *self, const struct frame *frame)
+struct num op_var(const struct expr *self, const struct frame *frame)
 {
-	double res;
+	struct num res;
 
 	res = eval_var(frame, self->u.var);
-	if (res == UNDEF)
+	if (is_undef(res))
 		fail("undefined variable \"%s\"", self->u.var);
 	return res;
 }
 
 
-double op_minus(const struct expr *self, const struct frame *frame)
+/* ----- arithmetic -------------------------------------------------------- */
+
+
+static struct num compatible_sum(struct num *a, struct num *b)
 {
-	double res;
+	struct num res;
 
+	if (a->type != b->type) {
+		if (a->type == nt_mil) {
+			a->type = nt_mm;
+			a->n = mil_to_mm(a->n, a->exponent);
+		}
+		if (b->type == nt_mil) {
+			b->type = nt_mm;
+			b->n = mil_to_mm(b->n, a->exponent);
+		}
+	}
+	if (a->exponent != b->exponent) {
+		fail("incompatible exponents (%d, %d)",
+		    a->exponent, b->exponent);
+		return undef;
+	}
+	res.type = a->type;
+	res.exponent = a->exponent;
+	return res;
+}
+
+
+static struct num compatible_mult(struct num *a, struct num *b,
+    int exponent)
+{
+	struct num res;
+
+	if (a->type != b->type) {
+		if (a->type == nt_mil) {
+			a->type = nt_mm;
+			a->n = mil_to_mm(a->n, a->exponent);
+		}
+		if (b->type == nt_mil) {
+			b->type = nt_mm;
+			b->n = mil_to_mm(b->n, b->exponent);
+		}
+	}
+	res.type = a->type;
+	res.exponent = exponent;
+	return res;
+}
+
+
+struct num op_minus(const struct expr *self, const struct frame *frame)
+{
+	struct num res;
+
 	res = eval_num(self->u.op.a, frame);
-	return res == UNDEF ? UNDEF : -res;
+	if (!is_undef(res))
+		res.n = -res.n;
+	return 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;			\
+#define	BINARY						\
+	struct num a, b, res;				\
+							\
+	a = eval_num(self->u.op.a, frame);		\
+	if (is_undef(a))				\
+		return undef;				\
+	b = eval_num(self->u.op.b, frame);		\
+	if (is_undef(b))				\
+		return undef;
 
 
-double op_add(const struct expr *self, const struct frame *frame)
+struct num op_add(const struct expr *self, const struct frame *frame)
 {
 	BINARY;
-	return a+b;
+	res = compatible_sum(&a, &b);
+	if (is_undef(res))
+		return undef;
+	res.n = a.n+b.n;
+	return res;
 }
 
 
-double op_sub(const struct expr *self, const struct frame *frame)
+struct num op_sub(const struct expr *self, const struct frame *frame)
 {
 	BINARY;
-	return a-b;
+	res = compatible_sum(&a, &b);
+	if (is_undef(res))
+		return undef;
+	res.n = a.n-b.n;
+	return res;
 }
 
 
-double op_mult(const struct expr *self, const struct frame *frame)
+struct num op_mult(const struct expr *self, const struct frame *frame)
 {
 	BINARY;
-	return a*b;
+	res = compatible_mult(&a, &b, a.exponent+b.exponent);
+	res.n = a.n*b.n;
+	return res;
 }
 
 
-double op_div(const struct expr *self, const struct frame *frame)
+struct num op_div(const struct expr *self, const struct frame *frame)
 {
 	BINARY;
-	if (!b) {
+	if (!b.n) {
 		fail("Division by zero");
-		return UNDEF;
+		return undef;
 	}
-	return a/b;
+	res = compatible_mult(&a, &b, a.exponent-b.exponent);
+	res.n = a.n/b.n;
+	return res;
 }
 
 
@@ -116,6 +263,7 @@
 
 	expr = alloc_type(struct expr);
 	expr->op = op;
+	expr->lineno = lineno;
 	return expr;
 }
 
@@ -137,7 +285,7 @@
 }
 
 
-double eval_num(const struct expr *expr, const struct frame *frame)
+struct num eval_num(const struct expr *expr, const struct frame *frame)
 {
 	return expr->op(expr, frame);
 }

Modified: developers/werner/fped/expr.h
===================================================================
--- developers/werner/fped/expr.h	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/expr.h	2009-07-29 10:59:02 UTC (rev 5335)
@@ -23,37 +23,79 @@
 struct frame;
 struct expr;
 
+enum num_type {
+	nt_none,
+	nt_mm,
+	nt_mil,
+};
 
-typedef double (*op_type)(const struct expr *self, const struct frame *frame);
+struct num {
+	enum num_type type;
+	int exponent;
+	double n;
+};
 
+typedef struct num (*op_type)(const struct expr *self,
+    const struct frame *frame);
+
 struct expr {
 	op_type op;
 	union {
-		double num;
+		struct num num;
 		const char *var;
 		struct {
 			struct expr *a;
 			struct expr *b;
 		} op;
 	} u;
+	int lineno;
 };
 
 
-double op_num(const struct expr *self, const struct frame *frame);
-double op_var(const struct expr *self, const struct frame *frame);
+struct num undef;
 
-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);
+#define	is_undef(num)		((num).type == nt_none)
+#define	is_dimensionless(num)	(!(num).exponent)
 
+
+static inline int is_distance(struct num num)
+{
+	return (num.type == nt_mm || num.type == nt_mil) && num.exponent == 1;
+}
+
+
+void fail_expr(const struct expr *expr);
+
+const char *str_unit(struct num n);
+
+static inline struct num make_num(double n)
+{
+	struct num res;
+
+	res.type = nt_mm;
+	res.exponent = 0;
+	res.n = n;
+	return res;
+}
+
+int to_unit(struct num *n);
+
+struct num op_num(const struct expr *self, const struct frame *frame);
+struct num op_var(const struct expr *self, const struct frame *frame);
+
+struct num op_minus(const struct expr *self, const struct frame *frame);
+
+struct num op_add(const struct expr *self, const struct frame *frame);
+struct num op_sub(const struct expr *self, const struct frame *frame);
+struct num op_mult(const struct expr *self, const struct frame *frame);
+struct num 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);
 
-double eval_var(const struct frame *frame, const char *name);
+struct num eval_var(const struct frame *frame, const char *name);
 char *eval_str(const struct frame *frame, const struct expr *expr);
-double eval_num(const struct expr *expr, const struct frame *frame);
+struct num eval_num(const struct expr *expr, const struct frame *frame);
 
 #endif /* !EXPR_H */

Modified: developers/werner/fped/fpd.l
===================================================================
--- developers/werner/fped/fpd.l	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/fpd.l	2009-07-29 10:59:02 UTC (rev 5335)
@@ -12,8 +12,11 @@
  */
 
 
+#include <stdlib.h>
+
 #include "util.h"
 #include "coord.h"
+#include "expr.h"
 #include "error.h"
 
 #include "y.tab.h"
@@ -39,13 +42,17 @@
 [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);
+{NUM}{SP}mm			{ yylval.num.type = nt_mm;
+				  yylval.num.exponent = 1;
+				  sscanf(yytext, "%lf", &yylval.num.n);
 				  return NUMBER; }
-{NUM}{SP}mil			{ sscanf(yytext, "%lf", &yylval.num);
-				  yylval.num = mil_to_units(yylval.num);
+{NUM}{SP}mil			{ yylval.num.type = nt_mil;
+				  yylval.num.exponent = 1;
+				  sscanf(yytext, "%lf", &yylval.num.n);
 				  return NUMBER; }
-{NUM}				{ sscanf(yytext, "%lf", &yylval.num);
+{NUM}				{ yylval.num.type = nt_mm; /* mm or mil */
+				  yylval.num.exponent = 0;
+				  sscanf(yytext, "%lf", &yylval.num.n);
 				  return NUMBER; }
 
 \"(\\[^\n\t]|[^\\"\n\t])*\"	{ *strrchr(yytext, '"') = 0;
@@ -54,6 +61,7 @@
 
 {SP}				;
 \n				lineno++;
-^#.*\n				lineno++;
 
+^#\ [0-9]+\ \"[^"]*\"(\ [0-9]+)*\n lineno = strtol(yytext+2, NULL, 0);
+
 .				return *yytext;

Modified: developers/werner/fped/fpd.y
===================================================================
--- developers/werner/fped/fpd.y	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/fpd.y	2009-07-29 10:59:02 UTC (rev 5335)
@@ -107,7 +107,7 @@
 
 
 %union {
-	double num;
+	struct num num;
 	char *str;
 	const char *id;
 	struct expr *expr;

Modified: developers/werner/fped/fped.c
===================================================================
--- developers/werner/fped/fped.c	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/fped.c	2009-07-29 10:59:02 UTC (rev 5335)
@@ -40,7 +40,8 @@
 		argc--;
 		argv++;
 	}
-	instantiate();
+	if (!instantiate())
+		return 1;
 	inst_debug();
 	error = gui_main(argc, argv);
 	if (error)

Modified: developers/werner/fped/obj.c
===================================================================
--- developers/werner/fped/obj.c	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/obj.c	2009-07-29 10:59:02 UTC (rev 5335)
@@ -17,8 +17,8 @@
 #include "util.h"
 #include "error.h"
 #include "expr.h"
+#include "inst.h"
 #include "obj.h"
-#include "inst.h"
 
 
 struct frame *frames = NULL;
@@ -48,7 +48,7 @@
 	const char *s, *s0;
 	char *var;
 	const char *var_unique;
-	double value;
+	struct num value;
 	int i, value_len;
 
 	i = 0;
@@ -77,11 +77,12 @@
 		var_unique = unique(var);
 		free(var);
 		value = eval_var(frame, var_unique);
-		if (value == UNDEF) {
+		if (is_undef(value)) {
 			fail("undefined variable \"%s\"", var_unique);
 			goto fail;
 		}
-		value_len = snprintf(num_buf, sizeof(num_buf), "%lg", value);
+		value_len = snprintf(num_buf, sizeof(num_buf), "%lg%s",
+		    value.n, str_unit(value));
 		len += value_len;
 		buf = realloc(buf, len);
 		if (!buf)
@@ -105,21 +106,25 @@
 	struct coord vec_base;
 	struct vec *vec;
 	struct obj *obj;
-	double x, y;
+	struct num x, y;
 	char *name;
 	int res;
 
 	for (vec = frame->vecs; vec; vec = vec->next) {
 		x = eval_num(vec->x, frame);
-		if (x == UNDEF)
+		if (is_undef(x) || !to_unit(&x)) {
+			fail_expr(vec->x);
 			return 0;
+		}
 		y = eval_num(vec->y, frame);
-		if (y == UNDEF)
+		if (is_undef(y) || !to_unit(&y)) {
+			fail_expr(vec->y);
 			return 0;
+		}
 		vec_base = vec->base ? vec->base->pos : base;
 		vec->pos = vec_base;
-		vec->pos.x += x;
-		vec->pos.y += y;
+		vec->pos.x += x.n;
+		vec->pos.y += y.n;
 		if (!inst_vec(vec, vec_base))
 			return 0;
 	}
@@ -167,17 +172,31 @@
 static int run_loops(struct frame *frame, struct loop *loop,
     struct coord base)
 {
-	double from, to;
+	struct num from, to;
 
 	if (!loop)
 		return generate_objects(frame, base);
 	from = eval_num(loop->from, frame);
-	if (from == UNDEF)
+	if (is_undef(from)) {
+		fail_expr(loop->from);
 		return 0;
+	}
+	if (!is_dimensionless(from)) {
+		fail("incompatible type for start value");
+		fail_expr(loop->from);
+		return 0;
+	}
 	to = eval_num(loop->to, frame);
-	if (from == UNDEF)
+	if (is_undef(to)) {
+		fail_expr(loop->to);
 		return 0;
-	for (loop->curr_value = from; loop->curr_value <= to;
+	}
+	if (!is_dimensionless(to)) {
+		fail("incompatible type for end value");
+		fail_expr(loop->to);
+		return 0;
+	}
+	for (loop->curr_value = from.n; loop->curr_value <= to.n;
 	    loop->curr_value += 1)
 		if (!run_loops(frame, loop->next, base))
 			return 0;
@@ -214,10 +233,10 @@
 }
 
 
-void instantiate(void)
+int instantiate(void)
 {
 	struct coord zero = { 0, 0 };
 
 	inst_reset();
-	generate_frame(frames, zero, NULL);
+	return generate_frame(frames, zero, NULL);
 }

Modified: developers/werner/fped/obj.h
===================================================================
--- developers/werner/fped/obj.h	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/obj.h	2009-07-29 10:59:02 UTC (rev 5335)
@@ -115,6 +115,6 @@
 struct frame *frames;
 
 
-void instantiate(void);
+int instantiate(void);
 
 #endif /* !OBJ_H */

Modified: developers/werner/fped/qfn.fpd
===================================================================
--- developers/werner/fped/qfn.fpd	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/qfn.fpd	2009-07-29 10:59:02 UTC (rev 5335)
@@ -1,7 +1,7 @@
 // http://www.nxp.com/acrobat/packages/footprint/SOT616-1_fp_reflow.pdf
 
 .frame pad_up {
-	c = .vec @ -D/2, 0
+	c = .vec @ -D/2, 0mm
 	.vec . D, C
 	pad = n+1
 	.pad "$pad" c .

Modified: developers/werner/fped/unparse.c
===================================================================
--- developers/werner/fped/unparse.c	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/unparse.c	2009-07-29 10:59:02 UTC (rev 5335)
@@ -81,7 +81,8 @@
 		return buf;
 	}
 	if (expr->op == op_num) {
-		snprintf(tmp, sizeof(tmp), "%lg", expr->u.num);
+		snprintf(tmp, sizeof(tmp), "%lg%s",
+		    expr->u.num.n, str_unit(expr->u.num));
 		return stralloc(tmp);
 	}
 	if (expr->op == op_var)

Modified: developers/werner/fped/unparse.h
===================================================================
--- developers/werner/fped/unparse.h	2009-07-29 03:31:56 UTC (rev 5334)
+++ developers/werner/fped/unparse.h	2009-07-29 10:59:02 UTC (rev 5335)
@@ -1,3 +1,16 @@
+/*
+ * unparse.h - Dump an expression tree into a string
+ *
+ * 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 UNPARSE_H
 #define UNPARSE_H
 




More information about the commitlog mailing list