mirror of
git://projects.qi-hardware.com/fped.git
synced 2024-11-25 18:01:54 +02: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:
parent
3064b2abbb
commit
386a9fd50b
3
TODO
3
TODO
@ -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
72
expr.c
@ -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
8
expr.h
@ -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
52
fbga.fpd
Normal 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
28
file.c
@ -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
5
file.h
@ -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
8
fped.c
@ -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();
|
||||
}
|
||||
|
||||
|
20
gui_frame.c
20
gui_frame.c
@ -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:
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user