diff options
author | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2011-03-12 19:04:03 +0000 |
---|---|---|
committer | Ingo Schwarze <schwarze@cvs.openbsd.org> | 2011-03-12 19:04:03 +0000 |
commit | 872b6ee7400edb775c362a39717e7942528eb707 (patch) | |
tree | 99903d255fb5924b4d19de8861964f4a93f6afc0 /gnu/usr.bin/groff/pic/pic.y | |
parent | 30c1ecbeb90c0d739a2f8dd74d15e05b79aba36e (diff) |
Replaced by mandoc(1) for base and xenocara purposes,
and comes with 4.9 ports.
ok deraadt@
Diffstat (limited to 'gnu/usr.bin/groff/pic/pic.y')
-rw-r--r-- | gnu/usr.bin/groff/pic/pic.y | 1784 |
1 files changed, 0 insertions, 1784 deletions
diff --git a/gnu/usr.bin/groff/pic/pic.y b/gnu/usr.bin/groff/pic/pic.y deleted file mode 100644 index d0420acd793..00000000000 --- a/gnu/usr.bin/groff/pic/pic.y +++ /dev/null @@ -1,1784 +0,0 @@ -/* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc. - Written by James Clark (jjc@jclark.com) - -This file is part of groff. - -groff is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later -version. - -groff is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License along -with groff; see the file COPYING. If not, write to the Free Software -Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -%{ -#include "pic.h" -#include "ptable.h" -#include "object.h" - -extern int delim_flag; -extern void do_copy(const char *); -extern void copy_rest_thru(const char *, const char *); -extern void copy_file_thru(const char *, const char *, const char *); -extern void push_body(const char *); -extern void do_for(char *var, double from, double to, - int by_is_multiplicative, double by, char *body); -extern void do_lookahead(); - -#ifndef HAVE_FMOD -extern "C" { - double fmod(double, double); -} -#endif - -#undef rand -extern "C" { - int rand(); -} - -/* Maximum number of characters produced by printf("%g") */ -#define GDIGITS 14 - -int yylex(); -void yyerror(const char *); - -void reset(const char *nm); -void reset_all(); - -place *lookup_label(const char *); -void define_label(const char *label, const place *pl); - -direction current_direction; -position current_position; - -implement_ptable(place) - -PTABLE(place) top_table; - -PTABLE(place) *current_table = &top_table; -saved_state *current_saved_state = 0; - -object_list olist; - -const char *ordinal_postfix(int n); -const char *object_type_name(object_type type); -char *format_number(const char *form, double n); -char *do_sprintf(const char *form, const double *v, int nv); - -%} - - -%union { - char *str; - int n; - double x; - struct { double x, y; } pair; - struct { double x; char *body; } if_data; - struct { char *str; const char *filename; int lineno; } lstr; - struct { double *v; int nv; int maxv; } dv; - struct { double val; int is_multiplicative; } by; - place pl; - object *obj; - corner crn; - path *pth; - object_spec *spec; - saved_state *pstate; - graphics_state state; - object_type obtype; -} - -%token <str> LABEL -%token <str> VARIABLE -%token <x> NUMBER -%token <lstr> TEXT -%token <lstr> COMMAND_LINE -%token <str> DELIMITED -%token <n> ORDINAL -%token TH -%token LEFT_ARROW_HEAD -%token RIGHT_ARROW_HEAD -%token DOUBLE_ARROW_HEAD -%token LAST -%token UP -%token DOWN -%token LEFT -%token RIGHT -%token BOX -%token CIRCLE -%token ELLIPSE -%token ARC -%token LINE -%token ARROW -%token MOVE -%token SPLINE -%token HEIGHT -%token RADIUS -%token WIDTH -%token DIAMETER -%token UP -%token DOWN -%token RIGHT -%token LEFT -%token FROM -%token TO -%token AT -%token WITH -%token BY -%token THEN -%token DOTTED -%token DASHED -%token CHOP -%token SAME -%token INVISIBLE -%token LJUST -%token RJUST -%token ABOVE -%token BELOW -%token OF -%token THE -%token WAY -%token BETWEEN -%token AND -%token HERE -%token DOT_N -%token DOT_E -%token DOT_W -%token DOT_S -%token DOT_NE -%token DOT_SE -%token DOT_NW -%token DOT_SW -%token DOT_C -%token DOT_START -%token DOT_END -%token DOT_X -%token DOT_Y -%token DOT_HT -%token DOT_WID -%token DOT_RAD -%token SIN -%token COS -%token ATAN2 -%token LOG -%token EXP -%token SQRT -%token K_MAX -%token K_MIN -%token INT -%token RAND -%token COPY -%token THRU -%token TOP -%token BOTTOM -%token UPPER -%token LOWER -%token SH -%token PRINT -%token CW -%token CCW -%token FOR -%token DO -%token IF -%token ELSE -%token ANDAND -%token OROR -%token NOTEQUAL -%token EQUALEQUAL -%token LESSEQUAL -%token GREATEREQUAL -%token LEFT_CORNER -%token RIGHT_CORNER -%token CENTER -%token END -%token START -%token RESET -%token UNTIL -%token PLOT -%token THICKNESS -%token FILL -%token ALIGNED -%token SPRINTF -%token COMMAND - -%token DEFINE -%token UNDEF - -/* this ensures that plot 17 "%g" parses as (plot 17 "%g") */ -%left PLOT -%left TEXT SPRINTF - -/* give text adjustments higher precedence than TEXT, so that -box "foo" above ljust == box ("foo" above ljust) -*/ - -%left LJUST RJUST ABOVE BELOW - -%left LEFT RIGHT -/* Give attributes that take an optional expression a higher -precedence than left and right, so that eg `line chop left' -parses properly. */ -%left CHOP DASHED DOTTED UP DOWN FILL -%left LABEL - -%left VARIABLE NUMBER '(' SIN COS ATAN2 LOG EXP SQRT K_MAX K_MIN INT RAND LAST -%left ORDINAL HERE '`' - -/* these need to be lower than '-' */ -%left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS - -/* these must have higher precedence than CHOP so that `label %prec CHOP' -works */ -%left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C -%left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER -%left UPPER LOWER CENTER START END - -%left ',' -%left OROR -%left ANDAND -%left EQUALEQUAL NOTEQUAL -%left '<' '>' LESSEQUAL GREATEREQUAL - -%left BETWEEN OF -%left AND - -%left '+' '-' -%left '*' '/' '%' -%right '!' -%right '^' - -%type <x> expr any_expr text_expr -%type <by> optional_by -%type <pair> expr_pair position_not_place -%type <if_data> simple_if -%type <obj> nth_primitive -%type <crn> corner -%type <pth> path label_path relative_path -%type <pl> place label element element_list middle_element_list -%type <spec> object_spec -%type <pair> position -%type <obtype> object_type -%type <n> optional_ordinal_last ordinal -%type <str> until -%type <dv> sprintf_args -%type <lstr> text print_args print_arg - -%% - -top: - optional_separator - | element_list - { - if (olist.head) - print_picture(olist.head); - } - ; - - -element_list: - optional_separator middle_element_list optional_separator - { $$ = $2; } - ; - -middle_element_list: - element - { $$ = $1; } - | middle_element_list separator element - { $$ = $1; } - ; - -optional_separator: - /* empty */ - | separator - ; - -separator: - ';' - | separator ';' - ; - -placeless_element: - VARIABLE '=' any_expr - { - define_variable($1, $3); - a_delete $1; - } - | VARIABLE ':' '=' any_expr - { - place *p = lookup_label($1); - if (!p) { - lex_error("variable `%1' not defined", $1); - YYABORT; - } - p->obj = 0; - p->x = $4; - p->y = 0.0; - a_delete $1; - } - | UP - { current_direction = UP_DIRECTION; } - | DOWN - { current_direction = DOWN_DIRECTION; } - | LEFT - { current_direction = LEFT_DIRECTION; } - | RIGHT - { current_direction = RIGHT_DIRECTION; } - | COMMAND_LINE - { - olist.append(make_command_object($1.str, $1.filename, - $1.lineno)); - } - | COMMAND print_args - { - olist.append(make_command_object($2.str, $2.filename, - $2.lineno)); - } - | PRINT print_args - { - fprintf(stderr, "%s\n", $2.str); - a_delete $2.str; - fflush(stderr); - } - | SH - { delim_flag = 1; } - DELIMITED - { - delim_flag = 0; - if (safer_flag) - lex_error("unsafe to run command `%1'", $3); - else - system($3); - a_delete $3; - } - | COPY TEXT - { - if (yychar < 0) - do_lookahead(); - do_copy($2.str); - // do not delete the filename - } - | COPY TEXT THRU - { delim_flag = 2; } - DELIMITED - { delim_flag = 0; } - until - { - if (yychar < 0) - do_lookahead(); - copy_file_thru($2.str, $5, $7); - // do not delete the filename - a_delete $5; - a_delete $7; - } - | COPY THRU - { delim_flag = 2; } - DELIMITED - { delim_flag = 0; } - until - { - if (yychar < 0) - do_lookahead(); - copy_rest_thru($4, $6); - a_delete $4; - a_delete $6; - } - | FOR VARIABLE '=' expr TO expr optional_by DO - { delim_flag = 1; } - DELIMITED - { - delim_flag = 0; - if (yychar < 0) - do_lookahead(); - do_for($2, $4, $6, $7.is_multiplicative, $7.val, $10); - } - | simple_if - { - if (yychar < 0) - do_lookahead(); - if ($1.x != 0.0) - push_body($1.body); - a_delete $1.body; - } - | simple_if ELSE - { delim_flag = 1; } - DELIMITED - { - delim_flag = 0; - if (yychar < 0) - do_lookahead(); - if ($1.x != 0.0) - push_body($1.body); - else - push_body($4); - a_delete $1.body; - a_delete $4; - } - | reset_variables - | RESET - { define_variable("scale", 1.0); } - ; - -reset_variables: - RESET VARIABLE - { reset($2); a_delete $2; } - | reset_variables VARIABLE - { reset($2); a_delete $2; } - | reset_variables ',' VARIABLE - { reset($3); a_delete $3; } - ; - -print_args: - print_arg - { $$ = $1; } - | print_args print_arg - { - $$.str = new char[strlen($1.str) + strlen($2.str) + 1]; - strcpy($$.str, $1.str); - strcat($$.str, $2.str); - a_delete $1.str; - a_delete $2.str; - if ($1.filename) { - $$.filename = $1.filename; - $$.lineno = $1.lineno; - } - else if ($2.filename) { - $$.filename = $2.filename; - $$.lineno = $2.lineno; - } - } - ; - -print_arg: - expr %prec ',' - { - $$.str = new char[GDIGITS + 1]; - sprintf($$.str, "%g", $1); - $$.filename = 0; - $$.lineno = 0; - } - | text - { $$ = $1; } - | position %prec ',' - { - $$.str = new char[GDIGITS + 2 + GDIGITS + 1]; - sprintf($$.str, "%g, %g", $1.x, $1.y); - $$.filename = 0; - $$.lineno = 0; - } - -simple_if: - IF any_expr THEN - { delim_flag = 1; } - DELIMITED - { delim_flag = 0; $$.x = $2; $$.body = $5; } - ; - -until: - /* empty */ - { $$ = 0; } - | UNTIL TEXT - { $$ = $2.str; } - ; - -any_expr: - expr - { $$ = $1; } - | text_expr - { $$ = $1; } - ; - -text_expr: - text EQUALEQUAL text - { - $$ = strcmp($1.str, $3.str) == 0; - a_delete $1.str; - a_delete $3.str; - } - | text NOTEQUAL text - { - $$ = strcmp($1.str, $3.str) != 0; - a_delete $1.str; - a_delete $3.str; - } - | text_expr ANDAND text_expr - { $$ = ($1 != 0.0 && $3 != 0.0); } - | text_expr ANDAND expr - { $$ = ($1 != 0.0 && $3 != 0.0); } - | expr ANDAND text_expr - { $$ = ($1 != 0.0 && $3 != 0.0); } - | text_expr OROR text_expr - { $$ = ($1 != 0.0 || $3 != 0.0); } - | text_expr OROR expr - { $$ = ($1 != 0.0 || $3 != 0.0); } - | expr OROR text_expr - { $$ = ($1 != 0.0 || $3 != 0.0); } - | '!' text_expr - { $$ = ($2 == 0.0); } - ; - - -optional_by: - /* empty */ - { $$.val = 1.0; $$.is_multiplicative = 0; } - | BY expr - { $$.val = $2; $$.is_multiplicative = 0; } - | BY '*' expr - { $$.val = $3; $$.is_multiplicative = 1; } - ; - -element: - object_spec - { - $$.obj = $1->make_object(¤t_position, - ¤t_direction); - if ($$.obj == 0) - YYABORT; - delete $1; - if ($$.obj) - olist.append($$.obj); - else { - $$.x = current_position.x; - $$.y = current_position.y; - } - } - | LABEL ':' optional_separator element - { $$ = $4; define_label($1, & $$); a_delete $1; } - | LABEL ':' optional_separator position_not_place - { - $$.obj = 0; - $$.x = $4.x; - $$.y = $4.y; - define_label($1, & $$); - a_delete $1; - } - | LABEL ':' optional_separator place - { - $$ = $4; - define_label($1, & $$); - a_delete $1; - } - | '{' - { - $<state>$.x = current_position.x; - $<state>$.y = current_position.y; - $<state>$.dir = current_direction; - } - element_list '}' - { - current_position.x = $<state>2.x; - current_position.y = $<state>2.y; - current_direction = $<state>2.dir; - } - optional_element - { - $$ = $3; - } - | placeless_element - { - $$.obj = 0; - $$.x = current_position.x; - $$.y = current_position.y; - } - ; - -optional_element: - /* empty */ - {} - | element - {} - ; - -object_spec: - BOX - { - $$ = new object_spec(BOX_OBJECT); - } - | CIRCLE - { - $$ = new object_spec(CIRCLE_OBJECT); - } - | ELLIPSE - { - $$ = new object_spec(ELLIPSE_OBJECT); - } - | ARC - { - $$ = new object_spec(ARC_OBJECT); - $$->dir = current_direction; - } - | LINE - { - $$ = new object_spec(LINE_OBJECT); - lookup_variable("lineht", & $$->segment_height); - lookup_variable("linewid", & $$->segment_width); - $$->dir = current_direction; - } - | ARROW - { - $$ = new object_spec(ARROW_OBJECT); - lookup_variable("lineht", & $$->segment_height); - lookup_variable("linewid", & $$->segment_width); - $$->dir = current_direction; - } - | MOVE - { - $$ = new object_spec(MOVE_OBJECT); - lookup_variable("moveht", & $$->segment_height); - lookup_variable("movewid", & $$->segment_width); - $$->dir = current_direction; - } - | SPLINE - { - $$ = new object_spec(SPLINE_OBJECT); - lookup_variable("lineht", & $$->segment_height); - lookup_variable("linewid", & $$->segment_width); - $$->dir = current_direction; - } - | text %prec TEXT - { - $$ = new object_spec(TEXT_OBJECT); - $$->text = new text_item($1.str, $1.filename, $1.lineno); - } - | PLOT expr - { - $$ = new object_spec(TEXT_OBJECT); - $$->text = new text_item(format_number(0, $2), 0, -1); - } - | PLOT expr text - { - $$ = new object_spec(TEXT_OBJECT); - $$->text = new text_item(format_number($3.str, $2), - $3.filename, $3.lineno); - a_delete $3.str; - } - | '[' - { - saved_state *p = new saved_state; - $<pstate>$ = p; - p->x = current_position.x; - p->y = current_position.y; - p->dir = current_direction; - p->tbl = current_table; - p->prev = current_saved_state; - current_position.x = 0.0; - current_position.y = 0.0; - current_table = new PTABLE(place); - current_saved_state = p; - olist.append(make_mark_object()); - } - element_list ']' - { - current_position.x = $<pstate>2->x; - current_position.y = $<pstate>2->y; - current_direction = $<pstate>2->dir; - $$ = new object_spec(BLOCK_OBJECT); - olist.wrap_up_block(& $$->oblist); - $$->tbl = current_table; - current_table = $<pstate>2->tbl; - current_saved_state = $<pstate>2->prev; - delete $<pstate>2; - } - | object_spec HEIGHT expr - { - $$ = $1; - $$->height = $3; - $$->flags |= HAS_HEIGHT; - } - | object_spec RADIUS expr - { - $$ = $1; - $$->radius = $3; - $$->flags |= HAS_RADIUS; - } - | object_spec WIDTH expr - { - $$ = $1; - $$->width = $3; - $$->flags |= HAS_WIDTH; - } - | object_spec DIAMETER expr - { - $$ = $1; - $$->radius = $3/2.0; - $$->flags |= HAS_RADIUS; - } - | object_spec expr %prec HEIGHT - { - $$ = $1; - $$->flags |= HAS_SEGMENT; - switch ($$->dir) { - case UP_DIRECTION: - $$->segment_pos.y += $2; - break; - case DOWN_DIRECTION: - $$->segment_pos.y -= $2; - break; - case RIGHT_DIRECTION: - $$->segment_pos.x += $2; - break; - case LEFT_DIRECTION: - $$->segment_pos.x -= $2; - break; - } - } - | object_spec UP - { - $$ = $1; - $$->dir = UP_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y += $$->segment_height; - } - | object_spec UP expr - { - $$ = $1; - $$->dir = UP_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y += $3; - } - | object_spec DOWN - { - $$ = $1; - $$->dir = DOWN_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y -= $$->segment_height; - } - | object_spec DOWN expr - { - $$ = $1; - $$->dir = DOWN_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.y -= $3; - } - | object_spec RIGHT - { - $$ = $1; - $$->dir = RIGHT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x += $$->segment_width; - } - | object_spec RIGHT expr - { - $$ = $1; - $$->dir = RIGHT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x += $3; - } - | object_spec LEFT - { - $$ = $1; - $$->dir = LEFT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x -= $$->segment_width; - } - | object_spec LEFT expr - { - $$ = $1; - $$->dir = LEFT_DIRECTION; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x -= $3; - } - | object_spec FROM position - { - $$ = $1; - $$->flags |= HAS_FROM; - $$->from.x = $3.x; - $$->from.y = $3.y; - } - | object_spec TO position - { - $$ = $1; - if ($$->flags & HAS_SEGMENT) - $$->segment_list = new segment($$->segment_pos, - $$->segment_is_absolute, - $$->segment_list); - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x = $3.x; - $$->segment_pos.y = $3.y; - $$->segment_is_absolute = 1; - $$->flags |= HAS_TO; - $$->to.x = $3.x; - $$->to.y = $3.y; - } - | object_spec AT position - { - $$ = $1; - $$->flags |= HAS_AT; - $$->at.x = $3.x; - $$->at.y = $3.y; - if ($$->type != ARC_OBJECT) { - $$->flags |= HAS_FROM; - $$->from.x = $3.x; - $$->from.y = $3.y; - } - } - | object_spec WITH path - { - $$ = $1; - $$->flags |= HAS_WITH; - $$->with = $3; - } - | object_spec BY expr_pair - { - $$ = $1; - $$->flags |= HAS_SEGMENT; - $$->segment_pos.x += $3.x; - $$->segment_pos.y += $3.y; - } - | object_spec THEN - { - $$ = $1; - if ($$->flags & HAS_SEGMENT) { - $$->segment_list = new segment($$->segment_pos, - $$->segment_is_absolute, - $$->segment_list); - $$->flags &= ~HAS_SEGMENT; - $$->segment_pos.x = $$->segment_pos.y = 0.0; - $$->segment_is_absolute = 0; - } - } - | object_spec DOTTED - { - $$ = $1; - $$->flags |= IS_DOTTED; - lookup_variable("dashwid", & $$->dash_width); - } - | object_spec DOTTED expr - { - $$ = $1; - $$->flags |= IS_DOTTED; - $$->dash_width = $3; - } - | object_spec DASHED - { - $$ = $1; - $$->flags |= IS_DASHED; - lookup_variable("dashwid", & $$->dash_width); - } - | object_spec DASHED expr - { - $$ = $1; - $$->flags |= IS_DASHED; - $$->dash_width = $3; - } - | object_spec FILL - { - $$ = $1; - $$->flags |= IS_DEFAULT_FILLED; - } - | object_spec FILL expr - { - $$ = $1; - $$->flags |= IS_FILLED; - $$->fill = $3; - } - | object_spec CHOP - { - $$ = $1; - // line chop chop means line chop 0 chop 0 - if ($$->flags & IS_DEFAULT_CHOPPED) { - $$->flags |= IS_CHOPPED; - $$->flags &= ~IS_DEFAULT_CHOPPED; - $$->start_chop = $$->end_chop = 0.0; - } - else if ($$->flags & IS_CHOPPED) { - $$->end_chop = 0.0; - } - else { - $$->flags |= IS_DEFAULT_CHOPPED; - } - } - | object_spec CHOP expr - { - $$ = $1; - if ($$->flags & IS_DEFAULT_CHOPPED) { - $$->flags |= IS_CHOPPED; - $$->flags &= ~IS_DEFAULT_CHOPPED; - $$->start_chop = 0.0; - $$->end_chop = $3; - } - else if ($$->flags & IS_CHOPPED) { - $$->end_chop = $3; - } - else { - $$->start_chop = $$->end_chop = $3; - $$->flags |= IS_CHOPPED; - } - } - | object_spec SAME - { - $$ = $1; - $$->flags |= IS_SAME; - } - | object_spec INVISIBLE - { - $$ = $1; - $$->flags |= IS_INVISIBLE; - } - | object_spec LEFT_ARROW_HEAD - { - $$ = $1; - $$->flags |= HAS_LEFT_ARROW_HEAD; - } - | object_spec RIGHT_ARROW_HEAD - { - $$ = $1; - $$->flags |= HAS_RIGHT_ARROW_HEAD; - } - | object_spec DOUBLE_ARROW_HEAD - { - $$ = $1; - $$->flags |= (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD); - } - | object_spec CW - { - $$ = $1; - $$->flags |= IS_CLOCKWISE; - } - | object_spec CCW - { - $$ = $1; - $$->flags &= ~IS_CLOCKWISE; - } - | object_spec text %prec TEXT - { - $$ = $1; - text_item **p; - for (p = & $$->text; *p; p = &(*p)->next) - ; - *p = new text_item($2.str, $2.filename, $2.lineno); - } - | object_spec LJUST - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.h = LEFT_ADJUST; - } - } - | object_spec RJUST - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.h = RIGHT_ADJUST; - } - } - | object_spec ABOVE - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.v = ABOVE_ADJUST; - } - } - | object_spec BELOW - { - $$ = $1; - if ($$->text) { - text_item *p; - for (p = $$->text; p->next; p = p->next) - ; - p->adj.v = BELOW_ADJUST; - } - } - | object_spec THICKNESS expr - { - $$ = $1; - $$->flags |= HAS_THICKNESS; - $$->thickness = $3; - } - | object_spec ALIGNED - { - $$ = $1; - $$->flags |= IS_ALIGNED; - } - ; - -text: - TEXT - { - $$ = $1; - } - | SPRINTF '(' TEXT sprintf_args ')' - { - $$.filename = $3.filename; - $$.lineno = $3.lineno; - $$.str = do_sprintf($3.str, $4.v, $4.nv); - a_delete $4.v; - a_delete $3.str; - } - ; - -sprintf_args: - /* empty */ - { - $$.v = 0; - $$.nv = 0; - $$.maxv = 0; - } - | sprintf_args ',' expr - { - $$ = $1; - if ($$.nv >= $$.maxv) { - if ($$.nv == 0) { - $$.v = new double[4]; - $$.maxv = 4; - } - else { - double *oldv = $$.v; - $$.maxv *= 2; - $$.v = new double[$$.maxv]; - memcpy($$.v, oldv, $$.nv*sizeof(double)); - a_delete oldv; - } - } - $$.v[$$.nv] = $3; - $$.nv += 1; - } - ; - -position: - position_not_place - { $$ = $1; } - | place - { - position pos = $1; - $$.x = pos.x; - $$.y = pos.y; - } - ; - -position_not_place: - expr_pair - { $$ = $1; } - | position '+' expr_pair - { - $$.x = $1.x + $3.x; - $$.y = $1.y + $3.y; - } - | position '-' expr_pair - { - $$.x = $1.x - $3.x; - $$.y = $1.y - $3.y; - } - | '(' position ',' position ')' - { - $$.x = $2.x; - $$.y = $4.y; - } - | expr between position AND position - { - $$.x = (1.0 - $1)*$3.x + $1*$5.x; - $$.y = (1.0 - $1)*$3.y + $1*$5.y; - } - | expr '<' position ',' position '>' - { - $$.x = (1.0 - $1)*$3.x + $1*$5.x; - $$.y = (1.0 - $1)*$3.y + $1*$5.y; - } - ; - -between: - BETWEEN - | OF THE WAY BETWEEN - ; - -expr_pair: - expr ',' expr - { $$.x = $1; $$.y = $3; } - | '(' expr_pair ')' - { $$ = $2; } - ; - -place: - label %prec CHOP /* line at A left == line (at A) left */ - { $$ = $1; } - | label corner - { - path pth($2); - if (!pth.follow($1, & $$)) - YYABORT; - } - | corner label - { - path pth($1); - if (!pth.follow($2, & $$)) - YYABORT; - } - | corner OF label - { - path pth($1); - if (!pth.follow($3, & $$)) - YYABORT; - } - | HERE - { - $$.x = current_position.x; - $$.y = current_position.y; - $$.obj = 0; - } - ; - -label: - LABEL - { - place *p = lookup_label($1); - if (!p) { - lex_error("there is no place `%1'", $1); - YYABORT; - } - $$ = *p; - a_delete $1; - } - | nth_primitive - { - $$.obj = $1; - } - | label '.' LABEL - { - path pth($3); - if (!pth.follow($1, & $$)) - YYABORT; - } - ; - -ordinal: - ORDINAL - { $$ = $1; } - | '`' any_expr TH - { - // XXX Check for overflow (and non-integers?). - $$ = (int)$2; - } - ; - -optional_ordinal_last: - LAST - { $$ = 1; } - | ordinal LAST - { $$ = $1; } - ; - -nth_primitive: - ordinal object_type - { - int count = 0; - object *p; - for (p = olist.head; p != 0; p = p->next) - if (p->type() == $2 && ++count == $1) { - $$ = p; - break; - } - if (p == 0) { - lex_error("there is no %1%2 %3", $1, ordinal_postfix($1), - object_type_name($2)); - YYABORT; - } - } - | optional_ordinal_last object_type - { - int count = 0; - object *p; - for (p = olist.tail; p != 0; p = p->prev) - if (p->type() == $2 && ++count == $1) { - $$ = p; - break; - } - if (p == 0) { - lex_error("there is no %1%2 last %3", $1, - ordinal_postfix($1), object_type_name($2)); - YYABORT; - } - } - ; - -object_type: - BOX - { $$ = BOX_OBJECT; } - | CIRCLE - { $$ = CIRCLE_OBJECT; } - | ELLIPSE - { $$ = ELLIPSE_OBJECT; } - | ARC - { $$ = ARC_OBJECT; } - | LINE - { $$ = LINE_OBJECT; } - | ARROW - { $$ = ARROW_OBJECT; } - | SPLINE - { $$ = SPLINE_OBJECT; } - | '[' ']' - { $$ = BLOCK_OBJECT; } - | TEXT - { $$ = TEXT_OBJECT; } - ; - -label_path: - '.' LABEL - { - $$ = new path($2); - } - | label_path '.' LABEL - { - $$ = $1; - $$->append($3); - } - ; - -relative_path: - corner - { - $$ = new path($1); - } - /* give this a lower precedence than LEFT and RIGHT so that - [A: box] with .A left == [A: box] with (.A left) */ - - | label_path %prec TEXT - { - $$ = $1; - } - | label_path corner - { - $$ = $1; - $$->append($2); - } - ; - -path: - relative_path - { - $$ = $1; - } - | '(' relative_path ',' relative_path ')' - { - $$ = $2; - $$->set_ypath($4); - } - /* The rest of these rules are a compatibility sop. */ - | ORDINAL LAST object_type relative_path - { - lex_warning("`%1%2 last %3' in `with' argument ignored", - $1, ordinal_postfix($1), object_type_name($3)); - $$ = $4; - } - | LAST object_type relative_path - { - lex_warning("`last %1' in `with' argument ignored", - object_type_name($2)); - $$ = $3; - } - | ORDINAL object_type relative_path - { - lex_warning("`%1%2 %3' in `with' argument ignored", - $1, ordinal_postfix($1), object_type_name($2)); - $$ = $3; - } - | LABEL relative_path - { - lex_warning("initial `%1' in `with' argument ignored", $1); - a_delete $1; - $$ = $2; - } - ; - -corner: - DOT_N - { $$ = &object::north; } - | DOT_E - { $$ = &object::east; } - | DOT_W - { $$ = &object::west; } - | DOT_S - { $$ = &object::south; } - | DOT_NE - { $$ = &object::north_east; } - | DOT_SE - { $$ = &object:: south_east; } - | DOT_NW - { $$ = &object::north_west; } - | DOT_SW - { $$ = &object::south_west; } - | DOT_C - { $$ = &object::center; } - | DOT_START - { $$ = &object::start; } - | DOT_END - { $$ = &object::end; } - | TOP - { $$ = &object::north; } - | BOTTOM - { $$ = &object::south; } - | LEFT - { $$ = &object::west; } - | RIGHT - { $$ = &object::east; } - | UPPER LEFT - { $$ = &object::north_west; } - | LOWER LEFT - { $$ = &object::south_west; } - | UPPER RIGHT - { $$ = &object::north_east; } - | LOWER RIGHT - { $$ = &object::south_east; } - | LEFT_CORNER - { $$ = &object::west; } - | RIGHT_CORNER - { $$ = &object::east; } - | UPPER LEFT_CORNER - { $$ = &object::north_west; } - | LOWER LEFT_CORNER - { $$ = &object::south_west; } - | UPPER RIGHT_CORNER - { $$ = &object::north_east; } - | LOWER RIGHT_CORNER - { $$ = &object::south_east; } - | CENTER - { $$ = &object::center; } - | START - { $$ = &object::start; } - | END - { $$ = &object::end; } - ; - -expr: - VARIABLE - { - if (!lookup_variable($1, & $$)) { - lex_error("there is no variable `%1'", $1); - YYABORT; - } - a_delete $1; - } - | NUMBER - { $$ = $1; } - | place DOT_X - { - if ($1.obj != 0) - $$ = $1.obj->origin().x; - else - $$ = $1.x; - } - | place DOT_Y - { - if ($1.obj != 0) - $$ = $1.obj->origin().y; - else - $$ = $1.y; - } - | place DOT_HT - { - if ($1.obj != 0) - $$ = $1.obj->height(); - else - $$ = 0.0; - } - | place DOT_WID - { - if ($1.obj != 0) - $$ = $1.obj->width(); - else - $$ = 0.0; - } - | place DOT_RAD - { - if ($1.obj != 0) - $$ = $1.obj->radius(); - else - $$ = 0.0; - } - | expr '+' expr - { $$ = $1 + $3; } - | expr '-' expr - { $$ = $1 - $3; } - | expr '*' expr - { $$ = $1 * $3; } - | expr '/' expr - { - if ($3 == 0.0) { - lex_error("division by zero"); - YYABORT; - } - $$ = $1/$3; - } - | expr '%' expr - { - if ($3 == 0.0) { - lex_error("modulus by zero"); - YYABORT; - } - $$ = fmod($1, $3); - } - | expr '^' expr - { - errno = 0; - $$ = pow($1, $3); - if (errno == EDOM) { - lex_error("arguments to `^' operator out of domain"); - YYABORT; - } - if (errno == ERANGE) { - lex_error("result of `^' operator out of range"); - YYABORT; - } - } - | '-' expr %prec '!' - { $$ = -$2; } - | '(' any_expr ')' - { $$ = $2; } - | SIN '(' any_expr ')' - { - errno = 0; - $$ = sin($3); - if (errno == ERANGE) { - lex_error("sin result out of range"); - YYABORT; - } - } - | COS '(' any_expr ')' - { - errno = 0; - $$ = cos($3); - if (errno == ERANGE) { - lex_error("cos result out of range"); - YYABORT; - } - } - | ATAN2 '(' any_expr ',' any_expr ')' - { - errno = 0; - $$ = atan2($3, $5); - if (errno == EDOM) { - lex_error("atan2 argument out of domain"); - YYABORT; - } - if (errno == ERANGE) { - lex_error("atan2 result out of range"); - YYABORT; - } - } - | LOG '(' any_expr ')' - { - errno = 0; - $$ = log10($3); - if (errno == ERANGE) { - lex_error("log result out of range"); - YYABORT; - } - } - | EXP '(' any_expr ')' - { - errno = 0; - $$ = pow(10.0, $3); - if (errno == ERANGE) { - lex_error("exp result out of range"); - YYABORT; - } - } - | SQRT '(' any_expr ')' - { - errno = 0; - $$ = sqrt($3); - if (errno == EDOM) { - lex_error("sqrt argument out of domain"); - YYABORT; - } - } - | K_MAX '(' any_expr ',' any_expr ')' - { $$ = $3 > $5 ? $3 : $5; } - | K_MIN '(' any_expr ',' any_expr ')' - { $$ = $3 < $5 ? $3 : $5; } - | INT '(' any_expr ')' - { $$ = floor($3); } - | RAND '(' any_expr ')' - { $$ = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*$3); } - | RAND '(' ')' - { - /* return a random number in the range [0,1) */ - /* portable, but not very random */ - $$ = (rand() & 0x7fff) / double(0x8000); - } - | expr '<' expr - { $$ = ($1 < $3); } - | expr LESSEQUAL expr - { $$ = ($1 <= $3); } - | expr '>' expr - { $$ = ($1 > $3); } - | expr GREATEREQUAL expr - { $$ = ($1 >= $3); } - | expr EQUALEQUAL expr - { $$ = ($1 == $3); } - | expr NOTEQUAL expr - { $$ = ($1 != $3); } - | expr ANDAND expr - { $$ = ($1 != 0.0 && $3 != 0.0); } - | expr OROR expr - { $$ = ($1 != 0.0 || $3 != 0.0); } - | '!' expr - { $$ = ($2 == 0.0); } - - ; - -%% - -/* bison defines const to be empty unless __STDC__ is defined, which it -isn't under cfront */ - -#ifdef const -#undef const -#endif - -static struct { - const char *name; - double val; - int scaled; // non-zero if val should be multiplied by scale -} defaults_table[] = { - { "arcrad", .25, 1 }, - { "arrowht", .1, 1 }, - { "arrowwid", .05, 1 }, - { "circlerad", .25, 1 }, - { "boxht", .5, 1 }, - { "boxwid", .75, 1 }, - { "boxrad", 0.0, 1 }, - { "dashwid", .05, 1 }, - { "ellipseht", .5, 1 }, - { "ellipsewid", .75, 1 }, - { "moveht", .5, 1 }, - { "movewid", .5, 1 }, - { "lineht", .5, 1 }, - { "linewid", .5, 1 }, - { "textht", 0.0, 1 }, - { "textwid", 0.0, 1 }, - { "scale", 1.0, 0 }, - { "linethick", -1.0, 0 }, // in points - { "fillval", .5, 0 }, - { "arrowhead", 1.0, 0 }, - { "maxpswid", 8.5, 0 }, - { "maxpsht", 11.0, 0 }, -}; - -place *lookup_label(const char *label) -{ - saved_state *state = current_saved_state; - PTABLE(place) *tbl = current_table; - for (;;) { - place *pl = tbl->lookup(label); - if (pl) - return pl; - if (!state) - return 0; - tbl = state->tbl; - state = state->prev; - } -} - -void define_label(const char *label, const place *pl) -{ - place *p = new place; - *p = *pl; - current_table->define(label, p); -} - -int lookup_variable(const char *name, double *val) -{ - place *pl = lookup_label(name); - if (pl) { - *val = pl->x; - return 1; - } - return 0; -} - -void define_variable(const char *name, double val) -{ - place *p = new place; - p->obj = 0; - p->x = val; - p->y = 0.0; - current_table->define(name, p); - if (strcmp(name, "scale") == 0) { - // When the scale changes, reset all scaled pre-defined variables to - // their default values. - for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++) - if (defaults_table[i].scaled) - define_variable(defaults_table[i].name, val*defaults_table[i].val); - } -} - -// called once only (not once per parse) - -void parse_init() -{ - current_direction = RIGHT_DIRECTION; - current_position.x = 0.0; - current_position.y = 0.0; - // This resets everything to its default value. - reset_all(); -} - -void reset(const char *nm) -{ - for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++) - if (strcmp(nm, defaults_table[i].name) == 0) { - double val = defaults_table[i].val; - if (defaults_table[i].scaled) { - double scale; - lookup_variable("scale", &scale); - val *= scale; - } - define_variable(defaults_table[i].name, val); - return; - } - lex_error("`%1' is not a predefined variable", nm); -} - -void reset_all() -{ - // We only have to explicitly reset the pre-defined variables that - // aren't scaled because `scale' is not scaled, and changing the - // value of `scale' will reset all the pre-defined variables that - // are scaled. - for (int i = 0; i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++) - if (!defaults_table[i].scaled) - define_variable(defaults_table[i].name, defaults_table[i].val); -} - -// called after each parse - -void parse_cleanup() -{ - while (current_saved_state != 0) { - delete current_table; - current_table = current_saved_state->tbl; - saved_state *tem = current_saved_state; - current_saved_state = current_saved_state->prev; - delete tem; - } - assert(current_table == &top_table); - PTABLE_ITERATOR(place) iter(current_table); - const char *key; - place *pl; - while (iter.next(&key, &pl)) - if (pl->obj != 0) { - position pos = pl->obj->origin(); - pl->obj = 0; - pl->x = pos.x; - pl->y = pos.y; - } - while (olist.head != 0) { - object *tem = olist.head; - olist.head = olist.head->next; - delete tem; - } - olist.tail = 0; - current_direction = RIGHT_DIRECTION; - current_position.x = 0.0; - current_position.y = 0.0; -} - -const char *ordinal_postfix(int n) -{ - if (n < 10 || n > 20) - switch (n % 10) { - case 1: - return "st"; - case 2: - return "nd"; - case 3: - return "rd"; - } - return "th"; -} - -const char *object_type_name(object_type type) -{ - switch (type) { - case BOX_OBJECT: - return "box"; - case CIRCLE_OBJECT: - return "circle"; - case ELLIPSE_OBJECT: - return "ellipse"; - case ARC_OBJECT: - return "arc"; - case SPLINE_OBJECT: - return "spline"; - case LINE_OBJECT: - return "line"; - case ARROW_OBJECT: - return "arrow"; - case MOVE_OBJECT: - return "move"; - case TEXT_OBJECT: - return "\"\""; - case BLOCK_OBJECT: - return "[]"; - case OTHER_OBJECT: - case MARK_OBJECT: - default: - break; - } - return "object"; -} - -static char sprintf_buf[1024]; - -char *format_number(const char *form, double n) -{ - if (form == 0) - form = "%g"; - return do_sprintf(form, &n, 1); -} - -char *do_sprintf(const char *form, const double *v, int nv) -{ - string result; - int i = 0; - string one_format; - while (*form) { - if (*form == '%') { - one_format += *form++; - for (; *form != '\0' && strchr("#-+ 0123456789.", *form) != 0; form++) - one_format += *form; - if (*form == '\0' || strchr("eEfgG%", *form) == 0) { - lex_error("bad sprintf format"); - result += one_format; - result += form; - break; - } - if (*form == '%') { - one_format += *form++; - one_format += '\0'; - snprintf(sprintf_buf, sizeof(sprintf_buf), - "%s", one_format.contents()); - } - else { - if (i >= nv) { - lex_error("too few arguments to snprintf"); - result += one_format; - result += form; - break; - } - one_format += *form++; - one_format += '\0'; - snprintf(sprintf_buf, sizeof(sprintf_buf), - one_format.contents(), v[i++]); - } - one_format.clear(); - result += sprintf_buf; - } - else - result += *form++; - } - result += '\0'; - return strsave(result.contents()); -} |