From 8e6feb0e55de8429bae4b7f49fbede5cf19ee013 Mon Sep 17 00:00:00 2001 From: Paul Richards Date: Mon, 23 Jan 1995 14:43:38 +0000 Subject: [PATCH] A forms interface builder. Basically, it reads a forms spec file and spits out a frm.tab.h file with all the definitions needed by the libforms interface. --- usr.bin/fib/Makefile | 10 + usr.bin/fib/fib.c | 45 +++ usr.bin/fib/lex.l | 83 ++++++ usr.bin/fib/parser.y | 633 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 771 insertions(+) create mode 100644 usr.bin/fib/Makefile create mode 100644 usr.bin/fib/fib.c create mode 100644 usr.bin/fib/lex.l create mode 100644 usr.bin/fib/parser.y diff --git a/usr.bin/fib/Makefile b/usr.bin/fib/Makefile new file mode 100644 index 000000000000..f6f48fd84331 --- /dev/null +++ b/usr.bin/fib/Makefile @@ -0,0 +1,10 @@ +PROG= fib +NOMAN=notyet + +SRCS = fib.c parser.c lex.l +LIBS = -ll +CLEANFILES= parser.c lex.c y.tab.h + +CFLAGS += -I${.CURDIR} -I. + +.include diff --git a/usr.bin/fib/fib.c b/usr.bin/fib/fib.c new file mode 100644 index 000000000000..bd161134d35f --- /dev/null +++ b/usr.bin/fib/fib.c @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 1995 + * Paul Richards. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Richards. + * 4. The name Paul Richards may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include + +main(int argc, char **argv) +{ + if (argc != 1) + if (!(freopen(*++argv, "r", stdin))) { + perror(*argv); + exit(1); + } + if (yyparse()) + exit(2); +} diff --git a/usr.bin/fib/lex.l b/usr.bin/fib/lex.l new file mode 100644 index 000000000000..41a6420faec7 --- /dev/null +++ b/usr.bin/fib/lex.l @@ -0,0 +1,83 @@ +%{ +/*- + * Copyright (c) 1995 + * Paul Richards. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Richards. + * 4. The name Paul Richards may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include "y.tab.h" +extern int lineno; +extern int charno; +extern int off; +%} + +%% +Form { return FORM; } +at { return AT; } +height { return HEIGHT; } += { return EQUALS; } +width { return WIDTH; } +disp_width { return DWIDTH; } +start { return STARTFIELD; } +text { return TEXT; } +Field { return FIELD; } +attributes { return ATTR; } +type { return TYPE; } +input { return INPUT; } +label { return LABEL; } +default { return DEFAULT; } +menu { return MENU; } +selected { return SELECTED; } +options { return OPTIONS; } +action { return ACTION; } +function { return FUNC; } +Link { return LINK; } +up { return UP; } +down { return DOWN; } +left { return LEFT; } +right { return RIGHT; } +next { return NEXT; } +, { return COLON; } +\{ { return LBRACE; } +\} { return RBRACE; } +[0-9]+ { yylval.ival = atoi(yytext); return NUMBER; } +[A-Za-z_][A-Za-z0-9_|&]* { yylval.sval = yytext; return NAME; } +\"[^"]* { + if (yytext[yyleng-1] == '\\') { + yymore(); + } else { + input(); + yylval.sval = yytext+1; + return STRING; + } + } +\n { lineno++; } +#.* { /* Ignored (comment) */; } +[ \t\f]* { /* Ignored (white space) */; } diff --git a/usr.bin/fib/parser.y b/usr.bin/fib/parser.y new file mode 100644 index 000000000000..5eec305aa698 --- /dev/null +++ b/usr.bin/fib/parser.y @@ -0,0 +1,633 @@ +%{ +/*- + * Copyright (c) 1995 + * Paul Richards. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer, + * verbatim and that no modifications are made prior to this + * point in the file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Paul Richards. + * 4. The name Paul Richards may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PAUL RICHARDS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +#include +#include +#include +#include + +char *cpstr(char *); + +extern int yyleng; +int lineno = 1; +int charno = 1; +int off; + +char *startname; +char *formname; +char *text; +char *label; +char *fieldname; +char *function; +char *up, *down, *left, *right, *next; +char *linkname; +int height, width; +int y, x; +int disp_width; +int width; +char *attr; +int type; +int lbl_flag; +int selected, no_options=0; +FILE *outf; + +struct field_list { + char *fieldname; + char *attr; + 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 link_list *cur_link; +struct link_list *link_list; +struct link_list *link; + +struct form_list { + char *formname; + struct form form; + struct form_list *next; + struct field_list *fields; + char *startfield; +}; + +struct form_list *cur_form; +struct form_list *form_list; +struct form_list *form; + +struct menu_list { + char *option; + struct menu_list *next; +}; + +struct menu_list *cur_menu; +struct menu_list *menu_list; +struct menu_list *menu; +%} + +%union { + int ival; + char *sval; +} + +%token FORM +%token NAME +%token STRING +%token AT +%token HEIGHT +%token EQUALS +%token NUMBER +%token WIDTH +%token STARTFIELD +%token COLON +%token LBRACE +%token RBRACE +%token FIELD +%token TYPE +%token TEXT +%token DWIDTH +%token ATTR +%token INPUT +%token DEFAULT +%token LABEL +%token SELECTED +%token MENU +%token OPTIONS +%token ACTION +%token FUNC +%token LINK +%token UP +%token DOWN +%token LEFT +%token RIGHT +%token NEXT + +%start spec + +%% + +spec: fields links forms + { + outf = fopen("frm.tab.h", "w"); + if (!outf) { + perror("Couldn't open output file:"); + exit (1); + } + output_fields(outf); + output_forms(outf); + if (fclose(outf) == EOF) { + perror("Error closing output file:"); + exit (1); + } + } + ; + +fields: field + | fields field + ; + +links: link + | links link + ; + +link: LINK NAME + { + linkname = cpstr($2); + fieldname = 0; + up = 0; + down = 0; + left = 0; + right = 0; + next = 0; + } + 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; + } + } + ; + +connspec: conns + | connspec conns + ; + +conns: FIELD EQUALS NAME + { fieldname = cpstr($3); } + | 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 + { + form = malloc(sizeof (struct form_list)); + if (!form) { + fprintf(stderr,"Failed to allocate memory for form\n"); + exit(1); + } + form->form.y = y; + form->form.x = x; + } + LBRACE formspec RBRACE + { + form->startfield = startname; + form->formname = formname; + form->form.height = height; + form->form.width = width; + form->fields = form_field_list; + cur_form_field = 0; + if (!cur_form) { + form_list = form; + cur_form = form; + } else { + cur_form->next = form; + cur_form = form; + } + } + ; + +formspec: height width startfield fieldlocs + ; + +height: HEIGHT EQUALS NUMBER + { height = $3; } + ; + +width: WIDTH EQUALS NUMBER + { width = $3; } + ; + +startfield: STARTFIELD EQUALS NAME + { startname = cpstr($3); } + ; + +fieldlocs: /* empty */ + | afield + | fieldlocs afield + ; + +afield: FIELD NAME + { fieldname = cpstr($2); } + 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; + field->field.y = y; + field->field.x = x; + if (!cur_form_field) { + form_field_list = field; + cur_form_field = field; + } else { + cur_form_field->next = field; + cur_form_field = field; + } + } + ; + +coord: NUMBER COLON NUMBER + { y = $1; x = $3; } + ; + +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.disp_width = disp_width; + field->field.width = width; + field->attr = attr; + 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; + 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; + } + } + ; + +fieldspec: dispwidth width attr type + ; + +type: textfield + | inputfield + | menufield + | actionfield + ; + +textfield: TYPE EQUALS TEXT TEXT EQUALS STRING + { type = F_TEXT; text = cpstr($6); } + ; + +inputfield: TYPE EQUALS INPUT inputspec + { type = F_INPUT; } + ; + +inputspec: LABEL EQUALS STRING + { lbl_flag = 1; label = cpstr($3); } + | DEFAULT EQUALS STRING + { lbl_flag = 0; label = cpstr($3); } + ; + +menufield: TYPE EQUALS MENU SELECTED EQUALS NUMBER OPTIONS EQUALS menuoptions + { type = F_MENU; selected = $6; } + ; + +menuoptions: menuoption + | menuoptions COLON menuoption + ; + +menuoption: STRING + { menu = malloc(sizeof(struct menu_list)); + if (!menu) { + fprintf(stderr, + "Couldn't allocate memory for menu option\n"); + exit (1); + } + menu->option = cpstr($1); + ++no_options; + if (!cur_menu) { + menu_list = menu; + cur_menu = menu; + } else { + cur_menu->next = menu; + cur_menu = menu; + } + } + ; + +actionfield: TYPE EQUALS ACTION TEXT EQUALS STRING FUNC EQUALS NAME + { type = F_ACTION; text = cpstr($6); function = cpstr($9); } + ; + +dispwidth: DWIDTH EQUALS NUMBER + { disp_width = $3; } + ; + +width: WIDTH EQUALS NUMBER + { width = $3; } + ; + +attr: ATTR EQUALS NAME + { attr = cpstr($3); } + ; + +%% + +yyerror (char *error) +{ + fprintf(stderr, "%s at line %d\n",error, lineno); + exit(1); +} + +yywrap() +{ + return(1); +} + +char * +cpstr(char *ostr) +{ + char *nstr; + + nstr = malloc(strlen(ostr)+1); + if (!nstr) { + fprintf(stderr, "Couldn't allocate memory for string\n"); + exit(1); + } + strcpy(nstr, ostr); + return (nstr); +} + +output_fields(FILE *outf) +{ + struct field_list *fields; + struct menu_list *menu; + int i; + + for (fields=field_list; fields; fields = fields->next) { + switch(fields->field.type) { + case F_TEXT: + fprintf(outf, "struct text_field %s = {\"%s\"};\n", + fields->fieldname, + fields->field.field.text->text); + break; + case F_INPUT: + fprintf(outf, "struct input_field %s = {%d, \"%s\", 0};\n", + fields->fieldname, + (fields->field.field.input->lbl_flag ? 1 : 0), + fields->field.field.input->label); + break; + case F_MENU: + fprintf(outf, "char *%s_options[] = {", + fields->fieldname); + menu = (struct menu_list *)fields->field.field.menu->options; + for (i=0; i < fields->field.field.menu->no_options - 1; i++) { + fprintf(outf, "\"%s\", ", menu->option); + menu = menu->next; + } + fprintf(outf, "\"%s\"};\n", menu->option); + fprintf(outf, "struct menu_field %s = {%d, %d, %s_options};\n", + fields->fieldname, + fields->field.field.menu->no_options, + fields->field.field.menu->selected, + fields->fieldname); + break; + case F_ACTION: + fprintf(outf, "struct action_field %s = {\"%s\", &%s};\n", + fields->fieldname, + fields->field.field.action->text, + fields->field.field.action->fn); + break; + default: + break; + } + } + fprintf(outf, "\n"); +} + +output_forms(FILE *outf) +{ + struct form_list *forms; + + for(forms=form_list; forms; forms = forms->next) { + parse_form(forms, outf); + } +} + +parse_form(struct form_list *form, FILE *outf) +{ + struct field_list *fields; + struct field_list *info; + struct link_list *links; + char *fieldname; + int no_fields = 0; + + fprintf(outf, "struct field %s_fields[] = {\n", form->formname); + + for(fields=form->fields; fields; fields=fields->next) { + fieldname = fields->fieldname; + + /* 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 alternate fieldname */ + if (links->fieldname) + fieldname = links->fieldname; + 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); + break; + } + } + + 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; + } + + + /* + * If we find a definition of this fieldname then we + * can output the field, otherwise we skip it. + */ + for(info=field_list; info; info = info->next) { + if (!strcmp(info->fieldname, fieldname)) { + ++no_fields; + fprintf(outf, "\t{%d, %d, %d, %d, %d, %s, ", + info->field.type, fields->field.y, fields->field.x, + info->field.disp_width, info->field.width, + info->attr); + 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", + fieldname); + break; + } + } + + if (!info) + fprintf(stderr, + "%s not found in field definitions, field not output\n", + fieldname); + } + + /* Output rest of form */ + fprintf(outf, "\t{%d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}\n};\n", F_END); + fprintf(outf, + "struct form %s = {%d, %d, %s_fields, %d, %d, %d, %d, 0};\n\n", + form->formname, no_fields, + field_id(form->startfield, form->fields), + form->formname, form->form.height, form->form.width, + form->form.y, form->form.x); +} + +/* + * Search a field list for a particular fieldname + * and return an integer id for that field based on + * it's position in the list [0..n]. Return -1 if + * there's no match. + */ + +int +field_id(char *fieldname, struct field_list *field_list) +{ + struct field_list *fields; + int id=0; + + /* If the strings null then fail immediately */ + + if (!fieldname) + return (-1); + + for (fields = field_list; fields; fields = fields->next, id++) { + if (!strcmp(fieldname, fields->fieldname)) + return (id); + } + + fprintf(stderr, "Field %s, not found in specification\n", fieldname); + return (-1); +}