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