freebsd-skq/lib/libforms/parser.y
paul 65e32573aa New libforms.
Bumped major number.

Ncurses backend still needs improving.
Other back-ends need to be written.
1995-05-12 17:20:06 +00:00

729 lines
16 KiB
Plaintext

%{
/*-
* 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 <strhash.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ncurses.h>
#include <forms.h>
#include <err.h>
#include "internal.h"
extern int yyleng;
int lineno = 1;
OBJECT *parent;
extern hash_table *cbind;
/* Some variables for holding temporary values as we parse objects */
OBJECT *object, *tmpobj;
DISPLAY *display;
int tmp, len;
char *tmpstr, *objname, *dispname, *useobj;
TUPLE *tmptuple;
TupleType t_type;
%}
%union {
int ival;
char *sval;
}
%token <ival> ACTION
%token <ival> ACTIVE
%token <ival> AS
%token <ival> AT
%token <ival> ATTR
%token <ival> ATTRTABLE
%token <ival> CALLFUNC
%token <ival> COLORPAIRS
%token <ival> DEFAULT
%token <ival> A_DISPLAY
%token <ival> DOWN
%token <ival> FORMS
%token <ival> FUNCTION
%token <ival> HANDLER
%token <ival> HEIGHT
%token <ival> INPUT
%token <ival> INPUTFILE
%token <ival> LABEL
%token <ival> LEFT
%token <ival> LIMIT
%token <ival> MENU
%token <ival> NCURSES
%token <ival> NEXT
%token <ival> AN_OBJECT
%token <ival> ON
%token <ival> ONENTRY
%token <ival> ONEXIT
%token <ival> OPTIONS
%token <ival> OUTPUTFILE
%token <ival> RIGHT
%token <ival> HIGHLIGHT
%token <ival> SELECTED
%token <ival> TEXT
%token <ival> TTYNAME
%token <ival> TYPE
%token <ival> UP
%token <ival> USE
%token <ival> USERDRAWFUNC
%token <ival> USERPROCFUNC
%token <ival> VERSION
%token <ival> WIDTH
%token <ival> WINDOW
%token <ival> BLACK
%token <ival> RED
%token <ival> GREEN
%token <ival> YELLOW
%token <ival> BLUE
%token <ival> MAGENTA
%token <ival> CYAN
%token <ival> WHITE
%token <ival> COMMA
%token <ival> SEMICOLON
%token <ival> LBRACE
%token <ival> RBRACE
%token <sval> NAME
%token <ival> NUMBER
%token <sval> STRING
%type <ival> color
%start forms
%%
forms: FORMS VERSION NAME spec
{
#ifdef DEBUG
printf("Forms language version %s\n", $3);
#endif
}
;
spec: /* empty */
| spec display
| spec window
| spec object
;
display: A_DISPLAY NAME
{
dispname = $2;
display = malloc(sizeof (DISPLAY));
if (!display)
errx(-1,
"Failed to allocate memory for display (%d)", lineno);
}
LBRACE HEIGHT NUMBER
{
display->virt_height = $6;
}
WIDTH NUMBER
{
display->virt_width = $9;
}
disp_type disp_attr_table RBRACE
{
if (!display)
errx(-1, "Failed to open display (%d)", lineno);
bind_tuple(root_table, dispname, TT_DISPLAY, (FUNCP)display);
dispname = 0;
}
;
disp_type: /* empty */
{
display->type = DT_ANY;
display->device = 0;
display = default_open(display);
}
| TYPE NCURSES device_ncurses
{ display->type = DT_NCURSES; }
;
device_ncurses: /* empty */
{
/* Use ncurses drivers but on a default tty */
display->device.ncurses = 0;
display = ncurses_open(display);
}
| LBRACE device_ncurses_tty
{
display = ncurses_open(display);
}
device_ncurses_colors RBRACE
;
device_ncurses_tty: /* empty */
{
/* Use ncurses drivers but on a default tty */
display->device.ncurses = 0;
}
| TTYNAME STRING INPUTFILE STRING OUTPUTFILE STRING
{
display->device.ncurses = (NCURSDEV *)malloc(sizeof (NCURSDEV));
if (!display->device.ncurses)
errx(-1, "Failed to allocate memory for ncurses device (%d)", lineno);
display->device.ncurses->ttyname = $2;
display->device.ncurses->input = $4;
display->device.ncurses->output = $6;
}
;
device_ncurses_colors: /* empty */
| COLORPAIRS LBRACE color_pairs RBRACE
;
color_pairs: /* empty */
| color_pairs color_pair
;
color_pair: NUMBER color color
{
if (display)
init_pair($1, $2, $3);
}
;
color: BLACK
{ $$ = COLOR_BLACK; }
| RED
{ $$ = COLOR_RED; }
| GREEN
{ $$ = COLOR_GREEN; }
| YELLOW
{ $$ = COLOR_YELLOW; }
| BLUE
{ $$ = COLOR_BLUE; }
| MAGENTA
{ $$ = COLOR_MAGENTA; }
| CYAN
{ $$ = COLOR_CYAN; }
| WHITE
{ $$ = COLOR_WHITE; }
;
disp_attr_table: /* empty */
{ display->bind = 0; }
| ATTRTABLE
{
display->bind = hash_create(0);
if (!display->bind)
errx(-1, "Failed to allocate memory for display bindings (%d)", lineno);
}
LBRACE disp_attrs RBRACE
;
disp_attrs: /* empty */
| disp_attrs disp_attr
;
disp_attr: NAME NUMBER
{ bind_tuple(display->bind, $1, TT_ATTR, (FUNCP)$2); }
;
window: WINDOW NAME ON NAME AT NUMBER COMMA NUMBER LBRACE
{
objname = $2;
dispname = $4;
object = malloc(sizeof (OBJECT));
if (!object)
errx(-1, "Failed to allocate memory for window (%d)", lineno);
object->y = $6;
object->x = $8;
object->status = O_VISIBLE;
object->bind = hash_create(0);
if (!object->bind)
errx(-1, "Failed to allocate memory for window's bindings (%d)", lineno);
}
object_params
{
tmptuple = tuple_search(object, dispname, TT_DISPLAY);
if (!tmptuple)
errx(-1, "Couldn't find binding for display (%d)", lineno);
free(dispname);
object->display = (struct Display *)tmptuple->addr;
switch (object->display->type) {
case DT_NCURSES:
default:
object->window.ncurses = malloc(sizeof (NCURSES_WINDOW));
if (!object->window.ncurses)
errx(-1, "Failed to allocate memory for ncurses window, (%d)", lineno);
ncurses_open_window(object);
break;
}
object->parent = 0;
if (!object->height)
object->height = display->height;
if (!object->width)
object->width = display->width;
bind_tuple(root_table, objname, TT_OBJ_INST, (FUNCP)object);
parent = object;
cbind = parent->bind;
}
object RBRACE
{
parent = 0;
cbind = root_table;
}
;
objects: /* empty */
| objects object
;
object: NAME
{
objname = $1;
object = malloc(sizeof (OBJECT));
if (!object)
errx(-1, "Failed to allocate memory for object (%d)", lineno);
object->bind = hash_create(0);
if (!object->bind)
errx(-1, "Failed to allocate memory for ",
"object's bindings (%d)", lineno);
}
at LBRACE use_copy
{
if (useobj) {
/* Need to declare parent to see previous scope levels */
object->parent = parent;
if (use_defined_object(object, useobj) == ST_NOBIND)
errx(-1, "Object, %s, not found in scope (%d)",
useobj, lineno);
}
}
object_params
{
/*
* If this is a function object convert it from
* a definition to an instance (see 'at' below).
*/
if (object->type == OT_FUNCTION)
t_type = TT_OBJ_INST;
/*
* If this is an instance object and it doesn't
* have a parent then there's a syntax error since
* instances can only be specified inside windows.
*/
if (parent)
inherit_properties(object, parent);
else if (t_type != TT_OBJ_DEF)
errx(-1, "Object, %s, has no parent (%d)", objname, lineno);
/* Propagate defobj up through nested compounds */
if (t_type == TT_OBJ_INST &&
parent && parent->type == OT_COMPOUND &&
!parent->object.compound->defobj)
parent->object.compound->defobj =
strdup(objname);
/* Add object and go down to next object */
bind_tuple(cbind, objname, t_type, (FUNCP)object);
parent = object;
cbind = object->bind;
}
objects RBRACE
{
parent = object->parent;
if (parent)
cbind = parent->bind;
else
cbind = root_table;
object = parent;
}
;
at: /* empty */
{
/*
* If there's no 'at' part specified then this is
* either a definition rather than an instance of
* an object or it's a function. Set it to a definition,
* we deal with the function case above.
*/
t_type = TT_OBJ_DEF;
object->y = 0;
object->x = 0;
}
| AT NUMBER COMMA NUMBER
{
t_type = TT_OBJ_INST;
object->y = $2;
object->x = $4;
}
;
use_copy: /* empty */
{ useobj = 0; }
| USE NAME
{ useobj = $2; }
;
object_params: user_draw_func user_proc_func height width attributes highlight on_entry on_exit links object_type
;
object_type: /* empty */
{
/* If we haven't inherited a type assume it's a compound */
if (!object->type) {
object->type = OT_COMPOUND;
object->object.compound = malloc(sizeof (COMPOUND_OBJECT));
if (!object->object.compound)
errx(-1, "Failed to allocate memory for object, (%d)\n",
lineno);
object->object.compound->defobj = 0;
}
}
| object_action
| object_compound
| object_function
| object_input
| object_menu
| object_text
;
links: /* empty */
| links conns
;
conns: UP NAME
{
if (object->lup)
free(object->lup);
object->lup = $2;
}
| DOWN NAME
{
if (object->ldown)
free(object->ldown);
object->ldown = $2;
}
| LEFT NAME
{
if (object->lleft)
free(object->lleft);
object->lleft = $2;
}
| RIGHT NAME
{
if (object->lright)
free(object->lright);
object->lright = $2;
}
| NEXT NAME
{
if (object->lnext)
free(object->lnext);
object->lnext = $2;
}
;
/*
* Parse the action object type.
*/
object_action: ACTION NAME LABEL STRING
{
object->type = OT_ACTION;
object->object.action = malloc(sizeof (ACTION_OBJECT));
if (!object->object.action)
errx(-1, "Failed to allocate memory for object, (%d)\n", lineno);
object->object.action->action = $2;
object->object.action->text = $4;
if (!object->width)
object->width = calc_string_width(object->object.text->text);
if (!object->height)
calc_object_height(object, object->object.text->text);
}
;
/*
* Parse the compound object type.
*/
object_compound: ACTIVE NAME
{
object->type = OT_COMPOUND;
object->object.compound = malloc(sizeof (COMPOUND_OBJECT));
if (!object->object.compound)
errx(-1, "Failed to allocate memory for object, (%d)\n", lineno);
object->object.compound->defobj = $2;
}
;
/*
* Parse the function object type
*/
object_function: CALLFUNC NAME
{
object->type = OT_FUNCTION;
object->object.function = malloc(sizeof (FUNCTION_OBJECT));
if (!object->object.function)
errx(-1, "Failed to allocate memory for object (%d)", lineno);
object->object.function->fn = $2;
}
;
/*
* Parse the input object type
*/
object_input: INPUT
{
object->type = OT_INPUT;
object->object.input = malloc(sizeof (INPUT_OBJECT));
if (!object->object.input)
errx(-1, "Failed to allocate memory for object (%d)", lineno);
}
input_params limit
{
/* Force height to 1 regardless */
object->height = 1;
if (!object->width && !object->object.input->limit) {
if (!object->object.input->label)
errx(-1, "Unable to determine size of input object (%d)",
lineno);
object->width = calc_string_width(object->object.input->label);
object->object.input->limit = object->width;
} else if (!object->width)
object->width = object->object.input->limit;
else if (!object->object.input->limit)
object->object.input->limit = object->width;
if (object->object.input->limit < object->width)
object->width = object->object.input->limit;
object->object.input->input =
malloc(object->object.input->limit + 1);
if (!object->object.input->input)
errx(-1, "Failed to allocate memory for object (%d)", lineno);
/*
* If it's a label then clear the input string
* otherwise copy the default there.
*/
if (object->object.input->lbl_flag)
object->object.input->input[0] = '\0';
else if (object->object.input->label) {
tmp = strlen(object->object.input->label);
strncpy(object->object.input->input,
object->object.input->label,
tmp);
object->object.input->input[tmp] = 0;
}
}
;
input_params: /* empty */
{
object->object.input->lbl_flag = 0;
object->object.input->label = 0;
}
| STRING
{
object->object.input->lbl_flag = 0;
object->object.input->label = $1;
}
| DEFAULT STRING
{
object->object.input->lbl_flag = 0;
object->object.input->label = $2;
}
| LABEL STRING
{
object->object.input->lbl_flag = 1;
object->object.input->label = $2;
}
;
limit: /* empty */
{ object->object.input->limit = 0; }
| LIMIT NUMBER
{ object->object.input->limit = $2; }
;
/*
* Parse the menu object type
*/
object_menu: OPTIONS LBRACE
{
object->type = OT_MENU;
object->object.menu = malloc(sizeof (MENU_OBJECT));
if (!object->object.menu)
errx(-1, "Failed to allocate memory for object (%d)", lineno);
object->object.menu->no_options = 0;
object->object.menu->options = 0;
len = 0;
}
menuoptions
{
object->height = 1;
if (!object->width)
object->width = len;
}
RBRACE option_selected
;
menuoptions: menuoption
| menuoptions menuoption
;
menuoption: STRING
{
tmpstr = $1;
object->object.menu->no_options =
add_menu_option(object->object.menu, tmpstr);
if (!object->object.menu->no_options)
errx(-1, "Failed to allocate memory for option (%d)", lineno);
tmp = calc_string_width(tmpstr);
if (tmp > len)
len = tmp;
free(tmpstr);
}
;
option_selected: /* empty */
{ object->object.menu->selected = 0; }
| SELECTED NUMBER
{ object->object.menu->selected = $2; }
;
/*
* Parse the text object type
*/
object_text: TEXT STRING
{
object->type = OT_TEXT;
object->object.text = malloc(sizeof (TEXT_OBJECT));
if (!object->object.text)
errx(-1, "Failed to allocate memory for object (%d)", lineno);
object->object.text->text = $2;
if (!object->width)
object->width = calc_string_width(object->object.text->text);
if (!object->height)
calc_object_height(object, object->object.text->text);
}
;
user_draw_func: /* empty */
| USERDRAWFUNC NAME
{
if (object->UserDrawFunc)
free(object->UserDrawFunc);
object->UserDrawFunc = $2;
}
;
user_proc_func: /* empty */
| USERPROCFUNC NAME
{
if (object->UserProcFunc)
free(object->UserProcFunc);
object->UserProcFunc = $2;
}
;
height: /* empty */
| HEIGHT NUMBER
{ object->height = $2; }
;
width: /* empty */
| WIDTH NUMBER
{ object->width = $2; }
;
attributes: /* empty */
| ATTR STRING
{
if (object->attributes)
free(object->attributes);
object->attributes = $2;
}
;
highlight: /* empty */
| HIGHLIGHT STRING
{
if (object->highlight)
free(object->highlight);
object->highlight = $2;
}
;
on_entry: /* empty */
| ONENTRY NAME
{
if (object->OnEntry)
free(object->OnEntry);
object->OnEntry = $2;
}
;
on_exit: /* empty */
| ONEXIT NAME
{
if (object->OnExit)
free(object->OnExit);
object->OnExit = $2;
}
;
%%
void
yyerror (char *error)
{
errx(-1, "%s at line %d\n", error, lineno);
}