1
0
mirror of git://projects.qi-hardware.com/fped.git synced 2024-06-30 21:57:39 +03:00

- added support for string constants to unparse()

- implemented eval_str
- expand() now tries to obtain a string
- added example fbga.fpd to demonstrate use of strings
- when invoked with an inexisting file, fped now starts with an empty model,
  instead of getting confused 
- we now religiously call edit_nothing before adding fields to edit, so that
  we won't create a loop through edit-next



git-svn-id: http://svn.openmoko.org/trunk/eda/fped@5421 99fdad57-331a-0410-800a-d7fa5415bdb3
This commit is contained in:
werner 2009-08-11 23:26:38 +00:00
parent 3064b2abbb
commit 386a9fd50b
9 changed files with 170 additions and 30 deletions

3
TODO
View File

@ -39,6 +39,9 @@ Code cleanup:
- code organization is very poor. E.g., functions belonging to the different
items (pads, silk objects, vectors, etc.) should be grouped by item, not by
type of function, similar to how some things are now with gui_meas.c
- eval_string_var should be merged into eval_var and the result should be a
struct num (?) that can contain both types. This also means changing all the
ops to handle/reject strings.
Open decisions:
- Q: should loop be (start, last) or (start, iterations) ? or start ... last ?

72
expr.c
View File

@ -154,6 +154,38 @@ struct num eval_var(const struct frame *frame, const char *name)
}
static const char *eval_string_var(const struct frame *frame, const char *name)
{
const struct table *table;
const struct loop *loop;
const struct value *value;
struct var *var;
const char *res;
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) {
if (var->visited)
return NULL;
var->visited = 1;
res = eval_str(value->expr, frame);
var->visited = 0;
return res;
}
value = value->next;
}
}
for (loop = frame->loops; loop; loop = loop->next)
if (loop->var.name == name)
return NULL;
if (frame->curr_parent)
return eval_string_var(frame->curr_parent, name);
return NULL;
}
struct num op_var(const struct expr *self, const struct frame *frame)
{
struct num res;
@ -307,9 +339,13 @@ struct expr *binary_op(op_type op, struct expr *a, struct expr *b)
}
char *eval_str(const struct frame *frame, const struct expr *expr)
const char *eval_str(const struct expr *expr, const struct frame *frame)
{
abort();
if (expr->op == op_string)
return expr->u.str;
if (expr->op == op_var)
return eval_string_var(frame, expr->u.var);
return NULL;
}
@ -329,7 +365,7 @@ char *expand(const char *name, const struct frame *frame)
char num_buf[100]; /* enough :-) */
const char *s, *s0;
char *var;
const char *var_unique;
const char *var_unique, *value_string;
struct num value;
int i, value_len;
@ -366,18 +402,24 @@ char *expand(const char *name, const struct frame *frame)
continue;
var_unique = unique(var);
free(var);
value = eval_var(frame, var_unique);
if (is_undef(value)) {
fail("undefined variable \"%s\"", var_unique);
goto fail;
value_string = eval_string_var(frame, var_unique);
if (value_string)
value_len = strlen(value_string);
else {
value = eval_var(frame, var_unique);
if (is_undef(value)) {
fail("undefined variable \"%s\"", var_unique);
goto fail;
}
value_len = snprintf(num_buf, sizeof(num_buf), "%lg%s",
value.n, str_unit(value));
value_string = num_buf;
}
value_len = snprintf(num_buf, sizeof(num_buf), "%lg%s",
value.n, str_unit(value));
len += value_len;
buf = realloc(buf, len+1);
if (!buf)
abort();
strcpy(buf+i, num_buf);
strcpy(buf+i, value_string);
i += value_len;
}
buf[i] = 0;
@ -410,6 +452,7 @@ struct expr *new_num(struct num num)
void scan_expr(const char *s);
int yyparse(void);
struct expr *expr_result;
@ -422,14 +465,15 @@ struct expr *parse_expr(const char *s)
static void vacate_op(struct expr *expr)
{
if (expr->op == &op_num || expr->op == &op_var)
if (expr->op == op_num || expr->op == op_string ||
expr->op == op_var)
return;
if (expr->op == &op_minus) {
if (expr->op == op_minus) {
free_expr(expr->u.op.a);
return;
}
if (expr->op == &op_add || expr->op == &op_sub ||
expr->op == &op_mult || expr->op == &op_div) {
if (expr->op == op_add || expr->op == op_sub ||
expr->op == op_mult || expr->op == op_div) {
free_expr(expr->u.op.a);
free_expr(expr->u.op.b);
return;

8
expr.h
View File

@ -121,7 +121,13 @@ struct expr *new_op(op_type op);
struct expr *binary_op(op_type op, struct expr *a, struct expr *b);
struct num eval_var(const struct frame *frame, const char *name);
char *eval_str(const struct frame *frame, const struct expr *expr);
/*
* eval_str returns NULL if the result isn't a string. Evaluation may then
* be attempted with eval_num, and the result can be converted accordingly.
*/
const char *eval_str(const struct expr *expr, const struct frame *frame);
struct num eval_num(const struct expr *expr, const struct frame *frame);
/* if frame == NULL, we only check the syntax without expanding */

52
fbga.fpd Normal file
View File

@ -0,0 +1,52 @@
/* MACHINE-GENERATED ! */
frame pad {
set Px = 0.5mm
set Py = 0.5mm
set cname = col+1
__0: vec @(col*1mm-Px/2, row*-1mm-Py/2)
__1: vec .(0mm, Py)
__2: vec __0(Px, 0mm)
pad "$rname$cname" __1 __2
}
frame inner {
loop col = c0, c1
frame pad @
}
frame last {
loop col = 4, 5
frame pad @
}
frame first {
loop col = 0, 1
frame pad @
}
part "Fake_BGA"
table
{ row, rname, c0, c1 }
{ 0, "A", 2, 3 }
{ 1, "B", 2, 3 }
{ 2, "C", 9, 0 }
{ 3, "D", 9, 0 }
{ 4, "E", 2, 3 }
{ 5, "F", 2, 3 }
frame last @
frame first @
frame inner @
measy pad.__0 -> pad.__1 0.2mm
measy pad.__0 -> pad.__0 0.5mm
measx pad.__0 -> pad.__2 -0.3mm
measx pad.__0 -> pad.__0 -0.6mm
measy pad.__0 >> pad.__1 0.8mm
measx pad.__0 >> pad.__2 -0.9mm

28
file.c
View File

@ -47,6 +47,19 @@ char *set_extension(const char *name, const char *ext)
}
int file_exists(const char *name)
{
struct stat st;
if (stat(name, &st) >= 0)
return 1;
if (errno == ENOENT)
return 0;
perror(name);
return -1;
}
int save_to(const char *name, int (*fn)(FILE *file))
{
FILE *file;
@ -73,8 +86,7 @@ void save_with_backup(const char *name, int (*fn)(FILE *file))
char *s = stralloc(name);
char *back, *tmp;
char *slash, *dot;
int n;
struct stat st;
int n, res;
/* save to temporary file */
@ -99,14 +111,12 @@ void save_with_backup(const char *name, int (*fn)(FILE *file))
while (1) {
back = stralloc_printf("%s~%d%s%s",
s, n, dot ? "." : "", dot ? dot+1 : "");
if (stat(back, &st) < 0) {
if (errno == ENOENT)
break;
perror(back);
free(back);
return;
}
res = file_exists(back);
if (!res)
break;
free(back);
if (res < 0)
return;
n++;
}
if (rename(name, back) < 0) {

5
file.h
View File

@ -17,6 +17,11 @@
#include <stdio.h>
/*
* Returns -1 on error.
*/
int file_exists(const char *name);
char *set_extension(const char *name, const char *ext);
int save_to(const char *name, int (*fn)(FILE *file));
void save_with_backup(const char *name, int (*fn)(FILE *file));

8
fped.c
View File

@ -32,8 +32,12 @@ char *save_file_name = NULL;
static void load_file(const char *name)
{
reporter = report_parse_error;
run_cpp_on_file(name);
if (file_exists(name) == 1) {
reporter = report_parse_error;
run_cpp_on_file(name);
} else {
scan_empty();
}
(void) yyparse();
}

View File

@ -487,6 +487,7 @@ static void edit_var(struct var *var)
label_in_box_bg(var->widget, COLOR_VAR_EDITING);
status_set_type_entry("name =");
status_set_name("%s", var->name);
edit_nothing();
edit_unique(&var->name, validate_var_name, var);
}
@ -508,6 +509,7 @@ static void edit_value(struct value *value)
{
inst_select_outside(value, unselect_value);
label_in_box_bg(value->widget, COLOR_EXPR_EDITING);
edit_nothing();
edit_expr(&value->expr);
}
@ -549,6 +551,7 @@ static gboolean assignment_var_select_event(GtkWidget *widget,
switch (event->button) {
case 1:
edit_nothing();
edit_var(var);
break;
case 3:
@ -566,6 +569,7 @@ static gboolean assignment_value_select_event(GtkWidget *widget,
switch (event->button) {
case 1:
edit_nothing();
edit_value(value);
break;
}
@ -633,6 +637,7 @@ static gboolean table_var_select_event(GtkWidget *widget,
switch (event->button) {
case 1:
edit_nothing();
edit_var(var);
break;
case 3:
@ -650,9 +655,11 @@ static gboolean table_value_select_event(GtkWidget *widget,
switch (event->button) {
case 1:
if (!value->row || value->row->table->active_row == value->row)
if (!value->row ||
value->row->table->active_row == value->row) {
edit_nothing();
edit_value(value);
else {
} else {
select_row(value->row);
change_world();
}
@ -745,6 +752,7 @@ static gboolean loop_var_select_event(GtkWidget *widget,
switch (event->button) {
case 1:
edit_nothing();
edit_var(&loop->var);
break;
case 3:
@ -762,6 +770,7 @@ static gboolean loop_from_select_event(GtkWidget *widget,
switch (event->button) {
case 1:
edit_nothing();
edit_value(&loop->from);
break;
}
@ -776,6 +785,7 @@ static gboolean loop_to_select_event(GtkWidget *widget,
switch (event->button) {
case 1:
edit_nothing();
edit_value(&loop->to);
break;
}
@ -940,6 +950,7 @@ static gboolean part_name_edit_event(GtkWidget *widget, GdkEventButton *event,
label_in_box_bg(widget, COLOR_PART_NAME_EDITING);
status_set_type_entry("part =");
status_set_name("%s", part_name);
edit_nothing();
edit_name(&part_name, validate_part_name, NULL);
break;
}
@ -1001,6 +1012,7 @@ static void edit_frame(struct frame *frame)
label_in_box_bg(frame->label, COLOR_FRAME_EDITING);
status_set_type_entry("name =");
status_set_name("%s", frame->name);
edit_nothing();
edit_unique(&frame->name, validate_frame_name, frame);
}
@ -1025,8 +1037,10 @@ static gboolean frame_select_event(GtkWidget *widget, GdkEventButton *event,
if (active_frame != frame)
select_frame(frame);
else {
if (active_frame->name)
if (active_frame->name) {
edit_nothing();
edit_frame(frame);
}
}
break;
case 3:

View File

@ -38,7 +38,7 @@ static int precedence(op_type op)
return prec_mult;
if (op == op_minus)
return prec_unary;
if (op == op_num || op == op_var)
if (op == op_num || op == op_string || op == op_var)
return prec_primary;
abort();
}
@ -85,6 +85,8 @@ static char *unparse_op(const struct expr *expr, enum prec prec)
expr->u.num.n, str_unit(expr->u.num));
return stralloc(tmp);
}
if (expr->op == op_string)
return stralloc_printf("\"%s\"", expr->u.str);
if (expr->op == op_var)
return stralloc(expr->u.var);
if (expr->op == op_minus)