Clean up the parser, allow fields to be specified inline and

generally make the forms language much less verbose.

Add height option for fields and calculate sensible defaults.
This commit is contained in:
Paul Richards 1995-02-01 03:22:17 +00:00
parent ba3fbfe69c
commit 463e33c94b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=6086
4 changed files with 266 additions and 277 deletions

View File

@ -6,6 +6,6 @@ LDADD = -ll
DPADD = ${LIBL} ${LIBFORMS}
CLEANFILES= parser.c lex.c y.tab.h
CFLAGS += -I${.CURDIR} -I.
CFLAGS += -I${.CURDIR} -I. -g
.include <bsd.prog.mk>

View File

@ -35,11 +35,24 @@
main(int argc, char **argv)
{
FILE *outf;
if (argc != 1)
if (!(freopen(*++argv, "r", stdin))) {
perror(*argv);
exit(1);
}
if (yyparse())
exit(2);
exit(1);
outf = fopen("frm.tab.h", "w");
if (!outf) {
perror("Couldn't open output file:");
exit(1);
}
output_forms(outf);
if (fclose(outf) == EOF) {
perror("Error closing output file:");
exit (1);
}
}

View File

@ -60,7 +60,6 @@ height { return HEIGHT; }
width { return WIDTH; }
start { return STARTFIELD; }
text { return TEXT; }
Field { return FIELD; }
attributes { return ATTR; }
highlight { return SELATTR; }
label { return LABEL; }
@ -70,7 +69,6 @@ selected { return SELECTED; }
options { return OPTIONS; }
action { return ACTION; }
function { return FUNC; }
Link { return LINK; }
up { return UP; }
down { return DOWN; }
left { return LEFT; }

View File

@ -44,16 +44,16 @@ int lineno = 1;
int charno = 1;
int off;
char *startname;
char *fieldname;
char *defname;
char *formname;
char *startname;
char *colortable;
char *formattr;
char *text;
char *label;
char *fieldname;
char *function;
char *up, *down, *left, *right, *next;
char *linkname;
int height, width;
int y, x;
int width;
@ -63,37 +63,28 @@ char *selattr;
int type;
int lbl_flag;
int selected, no_options=0;
FILE *outf;
extern FILE *outf;
struct field_list {
char *fieldname;
char *defname;
char *attr;
char *selattr;
struct field field;
struct field_list *next;
};
struct field_list *cur_field;
struct field_list *field_list;
struct field_list *field;
struct field_list *cur_form_field;
struct field_list *form_field_list;
struct link_list {
char *linkname;
char *fieldname;
char *up;
char *down;
char *left;
char *right;
char *next;
struct link_list *lnext;
struct field field;
struct field_list *next_field;
};
struct link_list *cur_link;
struct link_list *link_list;
struct link_list *link;
struct field_list *cur_field_def;
struct field_list *field_defs;
struct field_list *field;
struct field_list *cur_form_field;
struct field_list *form_field_list;
struct form_list {
char *formname;
@ -144,6 +135,7 @@ struct color_table *color_tables;
char *sval;
}
%token <ival> FORM
%token <ival> COLORTABLE
%token <ival> COLOR
%token <ival> BLACK
@ -155,7 +147,6 @@ struct color_table *color_tables;
%token <ival> CYAN
%token <ival> WHITE
%token <ival> PAIR
%token <ival> FORM
%token <sval> NAME
%token <sval> STRING
%token <ival> AT
@ -168,7 +159,6 @@ struct color_table *color_tables;
%token <ival> COMMA
%token <ival> LBRACE
%token <ival> RBRACE
%token <ival> FIELD
%token <ival> TEXT
%token <ival> ATTR
%token <ival> SELATTR
@ -185,6 +175,7 @@ struct color_table *color_tables;
%token <ival> LEFT
%token <ival> RIGHT
%token <ival> NEXT
%token <ival> DEF
%type <sval> a_color
@ -192,19 +183,10 @@ struct color_table *color_tables;
%%
spec: colours fields links forms
{
outf = fopen("frm.tab.h", "w");
if (!outf) {
perror("Couldn't open output file:");
exit (1);
}
output_forms(outf);
if (fclose(outf) == EOF) {
perror("Error closing output file:");
exit (1);
}
}
spec: /* empty */
| spec fields
| spec forms
| spec colours
;
colours: COLOR NAME
@ -230,7 +212,7 @@ colours: COLOR NAME
}
;
color_pairs: pair
color_pairs: /* empty */
| color_pairs pair
;
@ -246,7 +228,6 @@ pair: PAIR EQUALS a_color
COMMA a_color
{
pair->background = cpstr($6);
fprintf(stderr, "for = %s, back = %s\n", pair->foreground, pair->background);
if (!cur_pair) {
color_list = pair;
cur_pair = pair;
@ -275,77 +256,9 @@ a_color: BLACK
{ $$ = "COLOR_WHITE"; }
;
fields: field
| fields field
;
links: /* empty */
| link
| links link
;
link: LINK NAME
{
linkname = cpstr($2);
fieldname = 0;
up = 0;
down = 0;
left = 0;
right = 0;
next = 0;
}
alias LBRACE connspec RBRACE
{
link = malloc(sizeof (struct link_list));
if (!link) {
fprintf(stderr,"Failed to allocate memory for link\n");
exit(1);
}
link->linkname = linkname;
link->fieldname = fieldname;
link->up = up;
link->down = down;
link->left = left;
link->right = right;
link->next = next;
if (!cur_link) {
link_list = link;
cur_link = link;
} else {
cur_link->lnext = link;
cur_link = link;
}
}
;
alias: /* empty */
| AS NAME
{ fieldname = cpstr($2); }
;
connspec: conns
| connspec conns
;
conns: UP EQUALS NAME
{ up = cpstr($3); }
| DOWN EQUALS NAME
{ down = cpstr($3); }
| LEFT EQUALS NAME
{ left = cpstr($3); }
| RIGHT EQUALS NAME
{ right = cpstr($3); }
| NEXT EQUALS NAME
{ next = cpstr($3); }
;
forms: form
| forms form
;
form: FORM NAME
{ formname = cpstr($2); }
AT coord
forms: FORM NAME
{ formname = cpstr($2); }
AT coord LBRACE formspec RBRACE
{
form = malloc(sizeof (struct form_list));
if (!form) {
@ -354,9 +267,6 @@ form: FORM NAME
}
form->form.y = y;
form->form.x = x;
}
LBRACE formspec RBRACE
{
form->startfield = startname;
form->formname = formname;
form->colortable = colortable;
@ -378,14 +288,6 @@ form: FORM NAME
formspec: height width startfield colortable formattr fieldlocs
;
height: HEIGHT EQUALS NUMBER
{ height = $3; }
;
width: WIDTH EQUALS NUMBER
{ width = $3; }
;
startfield: /* empty */
{ startname = 0;
printf("Warning: No start field specified for form %s\n", formname);
@ -407,119 +309,86 @@ formattr: /* empty */
;
fieldlocs: /* empty */
| afield
| fieldlocs afield
| fieldlocs field_at
;
afield: FIELD NAME
{ fieldname = cpstr($2); }
AT coord
{
field_at: NAME
{ fieldname = cpstr($1); }
field_def AT coord
{
field = malloc(sizeof (struct field_list));
if (!field) {
fprintf(stderr,"Failed to allocate memory for form field\n");
exit(1);
}
field->fieldname = fieldname;
if (!defname)
field->defname = fieldname;
else
field->defname = defname;
field->field.y = y;
field->field.x = x;
}
links
{
field->up = up;
field->down = down;
field->left = left;
field->right = right;
field->next = next;
up = 0;
down = 0;
left = 0;
right = 0;
next = 0;
if (!cur_form_field) {
form_field_list = field;
cur_form_field = field;
} else {
cur_form_field->next = field;
cur_form_field->next_field = field;
cur_form_field = field;
}
}
;
coord: NUMBER COMMA NUMBER
{ y = $1; x = $3; }
fields: NAME
{ defname = cpstr($1); }
field_spec
{ define_field(defname, 0); }
;
field: FIELD NAME
{ fieldname = cpstr($2); }
LBRACE fieldspec RBRACE
{
field = malloc(sizeof (struct field_list));
if (!field) {
fprintf(stderr,"Failed to allocate memory for field\n");
exit(1);
}
field->fieldname = fieldname;
field->field.type = type;
field->field.width = width;
field->attr = attr;
field->selattr = selattr;
switch (type) {
case F_TEXT:
field->field.field.text = malloc(sizeof (struct text_field));
if (!field->field.field.text) {
fprintf(stderr,
"Failed to allocate memory for text field\n");
exit (1);
}
field->field.field.text->text = text;
break;
case F_INPUT:
field->field.field.input = malloc(sizeof (struct input_field));
if (!field->field.field.input) {
fprintf(stderr,
"Failed to allocate memory for input field\n");
exit (1);
}
field->field.field.input->lbl_flag = lbl_flag;
field->field.field.input->label = label;
field->field.field.input->limit = limit;
break;
case F_MENU:
field->field.field.menu = malloc(sizeof (struct menu_field));
if (!field->field.field.menu) {
fprintf(stderr,
"Failed to allocate memory for menu field\n");
exit (1);
}
field->field.field.menu->selected = selected;
field->field.field.menu->no_options = no_options;
no_options = 0;
field->field.field.menu->options = (char **)menu_list;
cur_menu = 0;
break;
case F_ACTION:
field->field.field.action = malloc(sizeof (struct action_field));
if (!field->field.field.action) {
fprintf(stderr,
"Failed to allocate memory for action field\n");
exit (1);
}
field->field.field.action->text = text;
field->field.field.action->fn = (void *) function;
break;
default:
break;
}
if (!cur_field) {
field_list = field;
cur_field = field;
} else {
cur_field->next = field;
cur_field = field;
}
width=0;
attr=0;
selattr=0;
limit=0;
}
field_def: /* empty */
{ defname = 0; }
| LBRACE NAME
{ defname = cpstr($2); }
RBRACE
| field_spec
{ defname = fieldname; define_field(defname, 0); }
;
fieldspec: width attr selattr type
field_spec: LBRACE height width attr selattr type RBRACE
;
links: /* empty */
| links COMMA conns
;
conns: UP EQUALS NAME
{ up = cpstr($3); }
| DOWN EQUALS NAME
{ down = cpstr($3); }
| LEFT EQUALS NAME
{ left = cpstr($3); }
| RIGHT EQUALS NAME
{ right = cpstr($3); }
| NEXT EQUALS NAME
{ next = cpstr($3); }
;
type: textfield
| inputfield
| menufield
| actionfield
| error
{ fprintf(stderr, "Uknown field type at %d\n", lineno); }
;
textfield: TEXT EQUALS STRING
@ -535,6 +404,7 @@ inputspec: LABEL EQUALS STRING limit
| DEFAULT EQUALS STRING limit
{ lbl_flag = 0; label = cpstr($3); }
;
limit: /* empty */
| LIMIT EQUALS NUMBER
{ limit = $3; }
@ -570,6 +440,12 @@ actionfield: ACTION EQUALS STRING FUNC EQUALS NAME
{ type = F_ACTION; text = cpstr($3); function = cpstr($6); }
;
height: /* empty */
{ height = 0; }
| HEIGHT EQUALS NUMBER
{ height = $3; }
;
width: /* empty */
{ width = 0; }
| WIDTH EQUALS NUMBER
@ -588,6 +464,10 @@ selattr: /* empty */
{ selattr = cpstr($3); }
;
coord: NUMBER COMMA NUMBER
{ y = $1; x = $3; }
;
%%
yyerror (char *error)
@ -625,12 +505,17 @@ output_field(struct field_list *fields, char *fieldname, FILE *outf)
if (!fieldname) {
if (!fields->field.width)
fields->field.width = strlen(fields->field.field.text->text);
if (!fields->field.height)
calc_field_height(&fields->field, fields->field.field.text->text);
fprintf(outf, "struct text_field %s = {\"%s\"};\n",
fields->fieldname,
fields->defname,
fields->field.field.text->text);
}
break;
case F_INPUT:
/* Force height to one regardless */
fields->field.height = 1;
if (!fields->field.width && !fields->field.field.input->limit) {
fields->field.width = strlen(fields->field.field.input->label);
fields->field.field.input->limit = fields->field.width;
@ -641,15 +526,17 @@ output_field(struct field_list *fields, char *fieldname, FILE *outf)
if (fields->field.field.input->limit < fields->field.width)
fields->field.width = fields->field.field.input->limit;
fprintf(outf, "struct input_field %s = {%d, \"%s\", 0, %d};\n",
(fieldname)?fieldname:fields->fieldname,
(fieldname)?fieldname:fields->defname,
(fields->field.field.input->lbl_flag ? 1 : 0),
fields->field.field.input->label,
fields->field.field.input->limit);
break;
case F_MENU:
/* Force height to one regardless */
fields->field.height = 1;
if (!fieldname) {
fprintf(outf, "char *%s_options[] = {",
fields->fieldname);
fields->defname);
menu = (struct menu_list *)fields->field.field.menu->options;
lim = 0;
for (i=0; i < fields->field.field.menu->no_options - 1; i++) {
@ -664,16 +551,18 @@ output_field(struct field_list *fields, char *fieldname, FILE *outf)
fprintf(outf, "\"%s\"};\n", menu->option);
}
fprintf(outf, "struct menu_field %s = {%d, %d, %s_options};\n",
(fieldname)?fieldname:fields->fieldname,
(fieldname)?fieldname:fields->defname,
fields->field.field.menu->no_options,
fields->field.field.menu->selected,
fields->fieldname);
fields->defname);
break;
case F_ACTION:
if (!fields->field.width)
fields->field.width = strlen(fields->field.field.action->text);
if (!fields->field.height)
calc_field_height(&fields->field, fields->field.field.action->text);
fprintf(outf, "struct action_field %s = {\"%s\", &%s};\n",
(fieldname)?fieldname:fields->fieldname,
(fieldname)?fieldname:fields->defname,
fields->field.field.action->text,
fields->field.field.action->fn);
break;
@ -688,7 +577,7 @@ output_forms(FILE *outf)
struct field_list *fields;
/* Output the general field definitions */
for (fields = field_list; fields; fields=fields->next)
for (fields = field_defs; fields; fields=fields->next_field)
output_field(fields, 0, outf);
for(forms=form_list; forms; forms = forms->next) {
@ -718,9 +607,8 @@ output_coltab(struct color_table *coltab, FILE *outf)
parse_form(struct form_list *form, FILE *outf)
{
struct field_list *fields;
struct field_list *def;
struct field_list *defs;
struct field_list *info;
struct link_list *links;
struct color_table *coltab;
char *fieldname;
int no_fields = 0;
@ -744,85 +632,67 @@ parse_form(struct form_list *form, FILE *outf)
* this form, filling in the link structures and outputing a field
* definition for this particular instance.
*/
for(fields=form->fields; fields; fields=fields->next) {
for(fields=form->fields; fields; fields=fields->next_field) {
fieldname = fields->fieldname;
/* Fill in link values */
/* Search links list for an entry for this field */
for (links = link_list; links; links = links->lnext) {
if (!strcmp(links->linkname, fields->fieldname)) {
/* Check for an alias */
if (links->fieldname)
fieldname = links->fieldname;
fields->fieldname = links->linkname;
fields->field.up = field_id(links->up, form->fields);
fields->field.down = field_id(links->down, form->fields);
fields->field.left = field_id(links->left, form->fields);
fields->field.right = field_id(links->right, form->fields);
fields->field.next = field_id(links->next, form->fields);
fields->field.up = field_id(fields->up, form->fields);
fields->field.down = field_id(fields->down, form->fields);
fields->field.left = field_id(fields->left, form->fields);
fields->field.right = field_id(fields->right, form->fields);
fields->field.next = field_id(fields->next, form->fields);
/* Search field list for definition of this field */
for(defs=field_defs; defs; defs=defs->next_field) {
if (!strcmp(fields->defname, defs->defname))
break;
}
}
for (def = field_list; def; def=def->next)
if (!strcmp(fieldname, def->fieldname))
break;
if (!def) {
if (!defs) {
fprintf(stderr,
"%s not found in field definitions, field not output\n",
fieldname);
fields->defname);
fields->fieldname = 0;
} else {
fields->field.type = def->field.type;
fields->field.width = def->field.width;
fields->attr = def->attr;
fields->selattr = def->selattr;
fields->field.type = defs->field.type;
fields->field.height = defs->field.height;
fields->field.width = defs->field.width;
fields->attr = defs->attr;
fields->selattr = defs->selattr;
if (strcmp(fields->defname, fields->fieldname))
output_field(defs, fields->fieldname, outf);
}
if (!links) {
/* No links for this field */
fields->field.up = -1;
fields->field.down = -1;
fields->field.left = -1;
fields->field.right = -1;
fields->field.next = -1;
fields->defname = fieldname;
}
if (strcmp(def->fieldname, fields->fieldname))
output_field(def, fields->fieldname, outf);
if ((fields->field.type == F_TEXT)
|| (fields->field.type == F_ACTION))
fields->defname = def->fieldname;
else
fields->defname = fields->fieldname;
}
/* Output the field table for this form */
fprintf(outf, "struct field %s_fields[] = {\n", form->formname);
for(fields=form->fields; fields; fields=fields->next) {
++no_fields;
fprintf(outf, "\t{%d, %d, %d, %d, %s, %s, ",
fields->field.type, fields->field.y, fields->field.x,
fields->field.width, (fields->attr ? fields->attr : "F_DEFATTR"),
(fields->selattr ? fields->selattr : "F_SELATTR"));
fprintf(outf, "%d, %d, %d, %d, %d, ",
fields->field.next,
fields->field.up,
fields->field.down,
fields->field.left,
fields->field.right);
fprintf(outf, "(struct text_field *)&%s},\n",
fields->defname);
for(fields=form->fields; fields; fields=fields->next_field) {
if (fields->fieldname) {
++no_fields;
fprintf(outf, "\t{%d, %d, %d, %d, %d, %s, %s, ",
fields->field.type, fields->field.y, fields->field.x,
fields->field.height, fields->field.width,
(fields->attr ? fields->attr : "F_DEFATTR"),
(fields->selattr ? fields->selattr : "F_SELATTR"));
fprintf(outf, "%d, %d, %d, %d, %d, ",
fields->field.next,
fields->field.up,
fields->field.down,
fields->field.left,
fields->field.right);
fprintf(outf, "(struct text_field *)&%s},\n",
fields->fieldname);
}
}
fprintf(outf, "\t{%d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}\n};\n", F_END);
/* If no start field set then find first non-text field */
if (!form->startfield)
for (fields = form->fields; fields; fields = fields->next)
for (fields = form->fields; fields; fields = fields->next_field)
if (fields->field.type != F_TEXT) {
form->startfield = fields->fieldname;
break;
@ -862,7 +732,7 @@ field_id(char *fieldname, struct field_list *field_list)
if (!fieldname)
return (-1);
for (fields = field_list; fields; fields = fields->next, id++) {
for (fields = field_list; fields; fields = fields->next_field, id++) {
if (!strcmp(fieldname, fields->fieldname))
return (id);
}
@ -870,3 +740,111 @@ field_id(char *fieldname, struct field_list *field_list)
fprintf(stderr, "Field %s, not found in specification\n", fieldname);
return (-1);
}
/* Calculate a default height for a field */
calc_field_height(struct field *field, char *string)
{
int len;
len = strlen(string);
if (!width) {
/*
* This is a failsafe, this routine shouldn't be called
* with a width of 0, the width should be determined
* first.
*/
height = 1;
return;
}
if (len < field->width) {
field->height = 1;
return;
} else
field->height = len / width;
if ((field->height*width) < len)
field->height++;
return;
}
/* Add a field to the pre-defined fields list */
define_field(char *defname, char *fieldname)
{
field = malloc(sizeof (struct field_list));
if (!field) {
fprintf(stderr,"Failed to allocate memory for form field\n");
exit(1);
}
field->fieldname = fieldname;
field->defname = defname;
field->field.type = type;
field->field.height = height;
field->field.width = width;
field->attr = attr;
field->selattr = selattr;
switch (type) {
case F_TEXT:
field->field.field.text = malloc(sizeof (struct text_field));
if (!field->field.field.text) {
fprintf(stderr,
"Failed to allocate memory for text field\n");
exit (1);
}
field->field.field.text->text = text;
break;
case F_INPUT:
field->field.field.input = malloc(sizeof (struct input_field));
if (!field->field.field.input) {
fprintf(stderr,
"Failed to allocate memory for input field\n");
exit (1);
}
field->field.field.input->lbl_flag = lbl_flag;
field->field.field.input->label = label;
field->field.field.input->limit = limit;
break;
case F_MENU:
field->field.field.menu = malloc(sizeof (struct menu_field));
if (!field->field.field.menu) {
fprintf(stderr,
"Failed to allocate memory for menu field\n");
exit (1);
}
field->field.field.menu->selected = selected;
field->field.field.menu->no_options = no_options;
no_options = 0;
field->field.field.menu->options = (char **)menu_list;
cur_menu = 0;
break;
case F_ACTION:
field->field.field.action = malloc(sizeof (struct action_field));
if (!field->field.field.action) {
fprintf(stderr,
"Failed to allocate memory for action field\n");
exit (1);
}
field->field.field.action->text = text;
field->field.field.action->fn = (void *) function;
break;
default:
break;
}
if (!cur_field_def) {
field_defs = field;
cur_field_def = field;
} else {
cur_field_def->next_field = field;
cur_field_def = field;
}
width=0;
height = 0;
attr=0;
selattr=0;
limit=0;
}