1*438b94bfSchristos /* $NetBSD: pic.y,v 1.2 2016/01/13 19:01:58 christos Exp $ */
204ac863bSchristos
304ac863bSchristos /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2005
404ac863bSchristos Free Software Foundation, Inc.
504ac863bSchristos Written by James Clark (jjc@jclark.com)
604ac863bSchristos
704ac863bSchristos This file is part of groff.
804ac863bSchristos
904ac863bSchristos groff is free software; you can redistribute it and/or modify it under
1004ac863bSchristos the terms of the GNU General Public License as published by the Free
1104ac863bSchristos Software Foundation; either version 2, or (at your option) any later
1204ac863bSchristos version.
1304ac863bSchristos
1404ac863bSchristos groff is distributed in the hope that it will be useful, but WITHOUT ANY
1504ac863bSchristos WARRANTY; without even the implied warranty of MERCHANTABILITY or
1604ac863bSchristos FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1704ac863bSchristos for more details.
1804ac863bSchristos
1904ac863bSchristos You should have received a copy of the GNU General Public License along
2004ac863bSchristos with groff; see the file COPYING. If not, write to the Free Software
2104ac863bSchristos Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */
2204ac863bSchristos %{
2304ac863bSchristos #include "pic.h"
2404ac863bSchristos #include "ptable.h"
2504ac863bSchristos #include "object.h"
2604ac863bSchristos
2704ac863bSchristos extern int delim_flag;
2804ac863bSchristos extern void copy_rest_thru(const char *, const char *);
2904ac863bSchristos extern void copy_file_thru(const char *, const char *, const char *);
3004ac863bSchristos extern void push_body(const char *);
3104ac863bSchristos extern void do_for(char *var, double from, double to,
3204ac863bSchristos int by_is_multiplicative, double by, char *body);
3304ac863bSchristos extern void do_lookahead();
3404ac863bSchristos
3504ac863bSchristos /* Maximum number of characters produced by printf("%g") */
3604ac863bSchristos #define GDIGITS 14
3704ac863bSchristos
3804ac863bSchristos int yylex();
3904ac863bSchristos void yyerror(const char *);
4004ac863bSchristos
4104ac863bSchristos void reset(const char *nm);
4204ac863bSchristos void reset_all();
4304ac863bSchristos
4404ac863bSchristos place *lookup_label(const char *);
4504ac863bSchristos void define_label(const char *label, const place *pl);
4604ac863bSchristos
4704ac863bSchristos direction current_direction;
4804ac863bSchristos position current_position;
4904ac863bSchristos
5004ac863bSchristos implement_ptable(place)
5104ac863bSchristos
5204ac863bSchristos PTABLE(place) top_table;
5304ac863bSchristos
5404ac863bSchristos PTABLE(place) *current_table = &top_table;
5504ac863bSchristos saved_state *current_saved_state = 0;
5604ac863bSchristos
5704ac863bSchristos object_list olist;
5804ac863bSchristos
5904ac863bSchristos const char *ordinal_postfix(int n);
6004ac863bSchristos const char *object_type_name(object_type type);
6104ac863bSchristos char *format_number(const char *form, double n);
6204ac863bSchristos char *do_sprintf(const char *form, const double *v, int nv);
6304ac863bSchristos
6404ac863bSchristos %}
6504ac863bSchristos
6604ac863bSchristos
6704ac863bSchristos %union {
6804ac863bSchristos char *str;
6904ac863bSchristos int n;
7004ac863bSchristos double x;
7104ac863bSchristos struct { double x, y; } pair;
7204ac863bSchristos struct { double x; char *body; } if_data;
7304ac863bSchristos struct { char *str; const char *filename; int lineno; } lstr;
7404ac863bSchristos struct { double *v; int nv; int maxv; } dv;
7504ac863bSchristos struct { double val; int is_multiplicative; } by;
7604ac863bSchristos place pl;
7704ac863bSchristos object *obj;
7804ac863bSchristos corner crn;
7904ac863bSchristos path *pth;
8004ac863bSchristos object_spec *spec;
8104ac863bSchristos saved_state *pstate;
8204ac863bSchristos graphics_state state;
8304ac863bSchristos object_type obtype;
8404ac863bSchristos }
8504ac863bSchristos
8604ac863bSchristos %token <str> LABEL
8704ac863bSchristos %token <str> VARIABLE
8804ac863bSchristos %token <x> NUMBER
8904ac863bSchristos %token <lstr> TEXT
9004ac863bSchristos %token <lstr> COMMAND_LINE
9104ac863bSchristos %token <str> DELIMITED
9204ac863bSchristos %token <n> ORDINAL
9304ac863bSchristos %token TH
9404ac863bSchristos %token LEFT_ARROW_HEAD
9504ac863bSchristos %token RIGHT_ARROW_HEAD
9604ac863bSchristos %token DOUBLE_ARROW_HEAD
9704ac863bSchristos %token LAST
9804ac863bSchristos %token UP
9904ac863bSchristos %token DOWN
10004ac863bSchristos %token LEFT
10104ac863bSchristos %token RIGHT
10204ac863bSchristos %token BOX
10304ac863bSchristos %token CIRCLE
10404ac863bSchristos %token ELLIPSE
10504ac863bSchristos %token ARC
10604ac863bSchristos %token LINE
10704ac863bSchristos %token ARROW
10804ac863bSchristos %token MOVE
10904ac863bSchristos %token SPLINE
11004ac863bSchristos %token HEIGHT
11104ac863bSchristos %token RADIUS
11204ac863bSchristos %token FIGNAME
11304ac863bSchristos %token WIDTH
11404ac863bSchristos %token DIAMETER
11504ac863bSchristos %token UP
11604ac863bSchristos %token DOWN
11704ac863bSchristos %token RIGHT
11804ac863bSchristos %token LEFT
11904ac863bSchristos %token FROM
12004ac863bSchristos %token TO
12104ac863bSchristos %token AT
12204ac863bSchristos %token WITH
12304ac863bSchristos %token BY
12404ac863bSchristos %token THEN
12504ac863bSchristos %token SOLID
12604ac863bSchristos %token DOTTED
12704ac863bSchristos %token DASHED
12804ac863bSchristos %token CHOP
12904ac863bSchristos %token SAME
13004ac863bSchristos %token INVISIBLE
13104ac863bSchristos %token LJUST
13204ac863bSchristos %token RJUST
13304ac863bSchristos %token ABOVE
13404ac863bSchristos %token BELOW
13504ac863bSchristos %token OF
13604ac863bSchristos %token THE
13704ac863bSchristos %token WAY
13804ac863bSchristos %token BETWEEN
13904ac863bSchristos %token AND
14004ac863bSchristos %token HERE
14104ac863bSchristos %token DOT_N
14204ac863bSchristos %token DOT_E
14304ac863bSchristos %token DOT_W
14404ac863bSchristos %token DOT_S
14504ac863bSchristos %token DOT_NE
14604ac863bSchristos %token DOT_SE
14704ac863bSchristos %token DOT_NW
14804ac863bSchristos %token DOT_SW
14904ac863bSchristos %token DOT_C
15004ac863bSchristos %token DOT_START
15104ac863bSchristos %token DOT_END
15204ac863bSchristos %token DOT_X
15304ac863bSchristos %token DOT_Y
15404ac863bSchristos %token DOT_HT
15504ac863bSchristos %token DOT_WID
15604ac863bSchristos %token DOT_RAD
15704ac863bSchristos %token SIN
15804ac863bSchristos %token COS
15904ac863bSchristos %token ATAN2
16004ac863bSchristos %token LOG
16104ac863bSchristos %token EXP
16204ac863bSchristos %token SQRT
16304ac863bSchristos %token K_MAX
16404ac863bSchristos %token K_MIN
16504ac863bSchristos %token INT
16604ac863bSchristos %token RAND
16704ac863bSchristos %token SRAND
16804ac863bSchristos %token COPY
16904ac863bSchristos %token THRU
17004ac863bSchristos %token TOP
17104ac863bSchristos %token BOTTOM
17204ac863bSchristos %token UPPER
17304ac863bSchristos %token LOWER
17404ac863bSchristos %token SH
17504ac863bSchristos %token PRINT
17604ac863bSchristos %token CW
17704ac863bSchristos %token CCW
17804ac863bSchristos %token FOR
17904ac863bSchristos %token DO
18004ac863bSchristos %token IF
18104ac863bSchristos %token ELSE
18204ac863bSchristos %token ANDAND
18304ac863bSchristos %token OROR
18404ac863bSchristos %token NOTEQUAL
18504ac863bSchristos %token EQUALEQUAL
18604ac863bSchristos %token LESSEQUAL
18704ac863bSchristos %token GREATEREQUAL
18804ac863bSchristos %token LEFT_CORNER
18904ac863bSchristos %token RIGHT_CORNER
19004ac863bSchristos %token NORTH
19104ac863bSchristos %token SOUTH
19204ac863bSchristos %token EAST
19304ac863bSchristos %token WEST
19404ac863bSchristos %token CENTER
19504ac863bSchristos %token END
19604ac863bSchristos %token START
19704ac863bSchristos %token RESET
19804ac863bSchristos %token UNTIL
19904ac863bSchristos %token PLOT
20004ac863bSchristos %token THICKNESS
20104ac863bSchristos %token FILL
20204ac863bSchristos %token COLORED
20304ac863bSchristos %token OUTLINED
20404ac863bSchristos %token SHADED
20504ac863bSchristos %token ALIGNED
20604ac863bSchristos %token SPRINTF
20704ac863bSchristos %token COMMAND
20804ac863bSchristos
20904ac863bSchristos %token DEFINE
21004ac863bSchristos %token UNDEF
21104ac863bSchristos
21204ac863bSchristos %left '.'
21304ac863bSchristos
21404ac863bSchristos /* this ensures that plot 17 "%g" parses as (plot 17 "%g") */
21504ac863bSchristos %left PLOT
21604ac863bSchristos %left TEXT SPRINTF
21704ac863bSchristos
21804ac863bSchristos /* give text adjustments higher precedence than TEXT, so that
21904ac863bSchristos box "foo" above ljust == box ("foo" above ljust)
22004ac863bSchristos */
22104ac863bSchristos
22204ac863bSchristos %left LJUST RJUST ABOVE BELOW
22304ac863bSchristos
22404ac863bSchristos %left LEFT RIGHT
22504ac863bSchristos /* Give attributes that take an optional expression a higher
22604ac863bSchristos precedence than left and right, so that eg `line chop left'
22704ac863bSchristos parses properly. */
22804ac863bSchristos %left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED
22904ac863bSchristos %left LABEL
23004ac863bSchristos
23104ac863bSchristos %left VARIABLE NUMBER '(' SIN COS ATAN2 LOG EXP SQRT K_MAX K_MIN INT RAND SRAND LAST
23204ac863bSchristos %left ORDINAL HERE '`'
23304ac863bSchristos
23404ac863bSchristos %left BOX CIRCLE ELLIPSE ARC LINE ARROW SPLINE '['
23504ac863bSchristos
23604ac863bSchristos /* these need to be lower than '-' */
23704ac863bSchristos %left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS
23804ac863bSchristos
23904ac863bSchristos /* these must have higher precedence than CHOP so that `label %prec CHOP'
24004ac863bSchristos works */
24104ac863bSchristos %left DOT_N DOT_E DOT_W DOT_S DOT_NE DOT_SE DOT_NW DOT_SW DOT_C
24204ac863bSchristos %left DOT_START DOT_END TOP BOTTOM LEFT_CORNER RIGHT_CORNER
24304ac863bSchristos %left UPPER LOWER NORTH SOUTH EAST WEST CENTER START END
24404ac863bSchristos
24504ac863bSchristos %left ','
24604ac863bSchristos %left OROR
24704ac863bSchristos %left ANDAND
24804ac863bSchristos %left EQUALEQUAL NOTEQUAL
24904ac863bSchristos %left '<' '>' LESSEQUAL GREATEREQUAL
25004ac863bSchristos
25104ac863bSchristos %left BETWEEN OF
25204ac863bSchristos %left AND
25304ac863bSchristos
25404ac863bSchristos %left '+' '-'
25504ac863bSchristos %left '*' '/' '%'
25604ac863bSchristos %right '!'
25704ac863bSchristos %right '^'
25804ac863bSchristos
25904ac863bSchristos %type <x> expr any_expr text_expr
26004ac863bSchristos %type <by> optional_by
26104ac863bSchristos %type <pair> expr_pair position_not_place
26204ac863bSchristos %type <if_data> simple_if
26304ac863bSchristos %type <obj> nth_primitive
26404ac863bSchristos %type <crn> corner
26504ac863bSchristos %type <pth> path label_path relative_path
26604ac863bSchristos %type <pl> place label element element_list middle_element_list
26704ac863bSchristos %type <spec> object_spec
26804ac863bSchristos %type <pair> position
26904ac863bSchristos %type <obtype> object_type
27004ac863bSchristos %type <n> optional_ordinal_last ordinal
27104ac863bSchristos %type <str> macro_name until
27204ac863bSchristos %type <dv> sprintf_args
27304ac863bSchristos %type <lstr> text print_args print_arg
27404ac863bSchristos
27504ac863bSchristos %%
27604ac863bSchristos
27704ac863bSchristos top:
27804ac863bSchristos optional_separator
27904ac863bSchristos | element_list
28004ac863bSchristos {
28104ac863bSchristos if (olist.head)
28204ac863bSchristos print_picture(olist.head);
28304ac863bSchristos }
28404ac863bSchristos ;
28504ac863bSchristos
28604ac863bSchristos
28704ac863bSchristos element_list:
28804ac863bSchristos optional_separator middle_element_list optional_separator
28904ac863bSchristos { $$ = $2; }
29004ac863bSchristos ;
29104ac863bSchristos
29204ac863bSchristos middle_element_list:
29304ac863bSchristos element
29404ac863bSchristos { $$ = $1; }
29504ac863bSchristos | middle_element_list separator element
29604ac863bSchristos { $$ = $1; }
29704ac863bSchristos ;
29804ac863bSchristos
29904ac863bSchristos optional_separator:
30004ac863bSchristos /* empty */
30104ac863bSchristos | separator
30204ac863bSchristos ;
30304ac863bSchristos
30404ac863bSchristos separator:
30504ac863bSchristos ';'
30604ac863bSchristos | separator ';'
30704ac863bSchristos ;
30804ac863bSchristos
30904ac863bSchristos placeless_element:
31004ac863bSchristos FIGNAME '=' macro_name
31104ac863bSchristos {
31204ac863bSchristos a_delete graphname;
31304ac863bSchristos graphname = new char[strlen($3) + 1];
31404ac863bSchristos strcpy(graphname, $3);
31504ac863bSchristos a_delete $3;
31604ac863bSchristos }
31704ac863bSchristos |
31804ac863bSchristos VARIABLE '=' any_expr
31904ac863bSchristos {
32004ac863bSchristos define_variable($1, $3);
32104ac863bSchristos a_delete $1;
32204ac863bSchristos }
32304ac863bSchristos | VARIABLE ':' '=' any_expr
32404ac863bSchristos {
32504ac863bSchristos place *p = lookup_label($1);
32604ac863bSchristos if (!p) {
32704ac863bSchristos lex_error("variable `%1' not defined", $1);
32804ac863bSchristos YYABORT;
32904ac863bSchristos }
33004ac863bSchristos p->obj = 0;
33104ac863bSchristos p->x = $4;
33204ac863bSchristos p->y = 0.0;
33304ac863bSchristos a_delete $1;
33404ac863bSchristos }
33504ac863bSchristos | UP
33604ac863bSchristos { current_direction = UP_DIRECTION; }
33704ac863bSchristos | DOWN
33804ac863bSchristos { current_direction = DOWN_DIRECTION; }
33904ac863bSchristos | LEFT
34004ac863bSchristos { current_direction = LEFT_DIRECTION; }
34104ac863bSchristos | RIGHT
34204ac863bSchristos { current_direction = RIGHT_DIRECTION; }
34304ac863bSchristos | COMMAND_LINE
34404ac863bSchristos {
34504ac863bSchristos olist.append(make_command_object($1.str, $1.filename,
34604ac863bSchristos $1.lineno));
34704ac863bSchristos }
34804ac863bSchristos | COMMAND print_args
34904ac863bSchristos {
35004ac863bSchristos olist.append(make_command_object($2.str, $2.filename,
35104ac863bSchristos $2.lineno));
35204ac863bSchristos }
35304ac863bSchristos | PRINT print_args
35404ac863bSchristos {
35504ac863bSchristos fprintf(stderr, "%s\n", $2.str);
35604ac863bSchristos a_delete $2.str;
35704ac863bSchristos fflush(stderr);
35804ac863bSchristos }
35904ac863bSchristos | SH
36004ac863bSchristos { delim_flag = 1; }
36104ac863bSchristos DELIMITED
36204ac863bSchristos {
36304ac863bSchristos delim_flag = 0;
36404ac863bSchristos if (safer_flag)
36504ac863bSchristos lex_error("unsafe to run command `%1'", $3);
36604ac863bSchristos else
36704ac863bSchristos system($3);
36804ac863bSchristos a_delete $3;
36904ac863bSchristos }
37004ac863bSchristos | COPY TEXT
37104ac863bSchristos {
37204ac863bSchristos if (yychar < 0)
37304ac863bSchristos do_lookahead();
37404ac863bSchristos do_copy($2.str);
37504ac863bSchristos // do not delete the filename
37604ac863bSchristos }
37704ac863bSchristos | COPY TEXT THRU
37804ac863bSchristos { delim_flag = 2; }
37904ac863bSchristos DELIMITED
38004ac863bSchristos { delim_flag = 0; }
38104ac863bSchristos until
38204ac863bSchristos {
38304ac863bSchristos if (yychar < 0)
38404ac863bSchristos do_lookahead();
38504ac863bSchristos copy_file_thru($2.str, $5, $7);
38604ac863bSchristos // do not delete the filename
38704ac863bSchristos a_delete $5;
38804ac863bSchristos a_delete $7;
38904ac863bSchristos }
39004ac863bSchristos | COPY THRU
39104ac863bSchristos { delim_flag = 2; }
39204ac863bSchristos DELIMITED
39304ac863bSchristos { delim_flag = 0; }
39404ac863bSchristos until
39504ac863bSchristos {
39604ac863bSchristos if (yychar < 0)
39704ac863bSchristos do_lookahead();
39804ac863bSchristos copy_rest_thru($4, $6);
39904ac863bSchristos a_delete $4;
40004ac863bSchristos a_delete $6;
40104ac863bSchristos }
40204ac863bSchristos | FOR VARIABLE '=' expr TO expr optional_by DO
40304ac863bSchristos { delim_flag = 1; }
40404ac863bSchristos DELIMITED
40504ac863bSchristos {
40604ac863bSchristos delim_flag = 0;
40704ac863bSchristos if (yychar < 0)
40804ac863bSchristos do_lookahead();
40904ac863bSchristos do_for($2, $4, $6, $7.is_multiplicative, $7.val, $10);
41004ac863bSchristos }
41104ac863bSchristos | simple_if
41204ac863bSchristos {
41304ac863bSchristos if (yychar < 0)
41404ac863bSchristos do_lookahead();
41504ac863bSchristos if ($1.x != 0.0)
41604ac863bSchristos push_body($1.body);
41704ac863bSchristos a_delete $1.body;
41804ac863bSchristos }
41904ac863bSchristos | simple_if ELSE
42004ac863bSchristos { delim_flag = 1; }
42104ac863bSchristos DELIMITED
42204ac863bSchristos {
42304ac863bSchristos delim_flag = 0;
42404ac863bSchristos if (yychar < 0)
42504ac863bSchristos do_lookahead();
42604ac863bSchristos if ($1.x != 0.0)
42704ac863bSchristos push_body($1.body);
42804ac863bSchristos else
42904ac863bSchristos push_body($4);
43004ac863bSchristos a_delete $1.body;
43104ac863bSchristos a_delete $4;
43204ac863bSchristos }
43304ac863bSchristos | reset_variables
43404ac863bSchristos | RESET
43504ac863bSchristos { define_variable("scale", 1.0); }
43604ac863bSchristos ;
43704ac863bSchristos
43804ac863bSchristos macro_name:
43904ac863bSchristos VARIABLE
44004ac863bSchristos | LABEL
44104ac863bSchristos ;
44204ac863bSchristos
44304ac863bSchristos reset_variables:
44404ac863bSchristos RESET VARIABLE
44504ac863bSchristos {
44604ac863bSchristos reset($2);
44704ac863bSchristos a_delete $2;
44804ac863bSchristos }
44904ac863bSchristos | reset_variables VARIABLE
45004ac863bSchristos {
45104ac863bSchristos reset($2);
45204ac863bSchristos a_delete $2;
45304ac863bSchristos }
45404ac863bSchristos | reset_variables ',' VARIABLE
45504ac863bSchristos {
45604ac863bSchristos reset($3);
45704ac863bSchristos a_delete $3;
45804ac863bSchristos }
45904ac863bSchristos ;
46004ac863bSchristos
46104ac863bSchristos print_args:
46204ac863bSchristos print_arg
46304ac863bSchristos { $$ = $1; }
46404ac863bSchristos | print_args print_arg
46504ac863bSchristos {
46604ac863bSchristos $$.str = new char[strlen($1.str) + strlen($2.str) + 1];
46704ac863bSchristos strcpy($$.str, $1.str);
46804ac863bSchristos strcat($$.str, $2.str);
46904ac863bSchristos a_delete $1.str;
47004ac863bSchristos a_delete $2.str;
47104ac863bSchristos if ($1.filename) {
47204ac863bSchristos $$.filename = $1.filename;
47304ac863bSchristos $$.lineno = $1.lineno;
47404ac863bSchristos }
47504ac863bSchristos else if ($2.filename) {
47604ac863bSchristos $$.filename = $2.filename;
47704ac863bSchristos $$.lineno = $2.lineno;
47804ac863bSchristos }
47904ac863bSchristos }
48004ac863bSchristos ;
48104ac863bSchristos
48204ac863bSchristos print_arg:
48304ac863bSchristos expr %prec ','
48404ac863bSchristos {
48504ac863bSchristos $$.str = new char[GDIGITS + 1];
48604ac863bSchristos sprintf($$.str, "%g", $1);
48704ac863bSchristos $$.filename = 0;
48804ac863bSchristos $$.lineno = 0;
48904ac863bSchristos }
49004ac863bSchristos | text
49104ac863bSchristos { $$ = $1; }
49204ac863bSchristos | position %prec ','
49304ac863bSchristos {
49404ac863bSchristos $$.str = new char[GDIGITS + 2 + GDIGITS + 1];
49504ac863bSchristos sprintf($$.str, "%g, %g", $1.x, $1.y);
49604ac863bSchristos $$.filename = 0;
49704ac863bSchristos $$.lineno = 0;
49804ac863bSchristos }
49904ac863bSchristos ;
50004ac863bSchristos
50104ac863bSchristos simple_if:
50204ac863bSchristos IF any_expr THEN
50304ac863bSchristos { delim_flag = 1; }
50404ac863bSchristos DELIMITED
50504ac863bSchristos {
50604ac863bSchristos delim_flag = 0;
50704ac863bSchristos $$.x = $2;
50804ac863bSchristos $$.body = $5;
50904ac863bSchristos }
51004ac863bSchristos ;
51104ac863bSchristos
51204ac863bSchristos until:
51304ac863bSchristos /* empty */
51404ac863bSchristos { $$ = 0; }
51504ac863bSchristos | UNTIL TEXT
51604ac863bSchristos { $$ = $2.str; }
51704ac863bSchristos ;
51804ac863bSchristos
51904ac863bSchristos any_expr:
52004ac863bSchristos expr
52104ac863bSchristos { $$ = $1; }
52204ac863bSchristos | text_expr
52304ac863bSchristos { $$ = $1; }
52404ac863bSchristos ;
52504ac863bSchristos
52604ac863bSchristos text_expr:
52704ac863bSchristos text EQUALEQUAL text
52804ac863bSchristos {
52904ac863bSchristos $$ = strcmp($1.str, $3.str) == 0;
53004ac863bSchristos a_delete $1.str;
53104ac863bSchristos a_delete $3.str;
53204ac863bSchristos }
53304ac863bSchristos | text NOTEQUAL text
53404ac863bSchristos {
53504ac863bSchristos $$ = strcmp($1.str, $3.str) != 0;
53604ac863bSchristos a_delete $1.str;
53704ac863bSchristos a_delete $3.str;
53804ac863bSchristos }
53904ac863bSchristos | text_expr ANDAND text_expr
54004ac863bSchristos { $$ = ($1 != 0.0 && $3 != 0.0); }
54104ac863bSchristos | text_expr ANDAND expr
54204ac863bSchristos { $$ = ($1 != 0.0 && $3 != 0.0); }
54304ac863bSchristos | expr ANDAND text_expr
54404ac863bSchristos { $$ = ($1 != 0.0 && $3 != 0.0); }
54504ac863bSchristos | text_expr OROR text_expr
54604ac863bSchristos { $$ = ($1 != 0.0 || $3 != 0.0); }
54704ac863bSchristos | text_expr OROR expr
54804ac863bSchristos { $$ = ($1 != 0.0 || $3 != 0.0); }
54904ac863bSchristos | expr OROR text_expr
55004ac863bSchristos { $$ = ($1 != 0.0 || $3 != 0.0); }
55104ac863bSchristos | '!' text_expr
55204ac863bSchristos { $$ = ($2 == 0.0); }
55304ac863bSchristos ;
55404ac863bSchristos
55504ac863bSchristos
55604ac863bSchristos optional_by:
55704ac863bSchristos /* empty */
55804ac863bSchristos {
55904ac863bSchristos $$.val = 1.0;
56004ac863bSchristos $$.is_multiplicative = 0;
56104ac863bSchristos }
56204ac863bSchristos | BY expr
56304ac863bSchristos {
56404ac863bSchristos $$.val = $2;
56504ac863bSchristos $$.is_multiplicative = 0;
56604ac863bSchristos }
56704ac863bSchristos | BY '*' expr
56804ac863bSchristos {
56904ac863bSchristos $$.val = $3;
57004ac863bSchristos $$.is_multiplicative = 1;
57104ac863bSchristos }
57204ac863bSchristos ;
57304ac863bSchristos
57404ac863bSchristos element:
57504ac863bSchristos object_spec
57604ac863bSchristos {
57704ac863bSchristos $$.obj = $1->make_object(¤t_position,
57804ac863bSchristos ¤t_direction);
57904ac863bSchristos if ($$.obj == 0)
58004ac863bSchristos YYABORT;
58104ac863bSchristos delete $1;
58204ac863bSchristos if ($$.obj)
58304ac863bSchristos olist.append($$.obj);
58404ac863bSchristos else {
58504ac863bSchristos $$.x = current_position.x;
58604ac863bSchristos $$.y = current_position.y;
58704ac863bSchristos }
58804ac863bSchristos }
58904ac863bSchristos | LABEL ':' optional_separator element
59004ac863bSchristos {
59104ac863bSchristos $$ = $4;
59204ac863bSchristos define_label($1, & $$);
59304ac863bSchristos a_delete $1;
59404ac863bSchristos }
59504ac863bSchristos | LABEL ':' optional_separator position_not_place
59604ac863bSchristos {
59704ac863bSchristos $$.obj = 0;
59804ac863bSchristos $$.x = $4.x;
59904ac863bSchristos $$.y = $4.y;
60004ac863bSchristos define_label($1, & $$);
60104ac863bSchristos a_delete $1;
60204ac863bSchristos }
60304ac863bSchristos | LABEL ':' optional_separator place
60404ac863bSchristos {
60504ac863bSchristos $$ = $4;
60604ac863bSchristos define_label($1, & $$);
60704ac863bSchristos a_delete $1;
60804ac863bSchristos }
60904ac863bSchristos | '{'
61004ac863bSchristos {
61104ac863bSchristos $<state>$.x = current_position.x;
61204ac863bSchristos $<state>$.y = current_position.y;
61304ac863bSchristos $<state>$.dir = current_direction;
61404ac863bSchristos }
61504ac863bSchristos element_list '}'
61604ac863bSchristos {
61704ac863bSchristos current_position.x = $<state>2.x;
61804ac863bSchristos current_position.y = $<state>2.y;
61904ac863bSchristos current_direction = $<state>2.dir;
62004ac863bSchristos }
62104ac863bSchristos optional_element
62204ac863bSchristos {
62304ac863bSchristos $$ = $3;
62404ac863bSchristos }
62504ac863bSchristos | placeless_element
62604ac863bSchristos {
62704ac863bSchristos $$.obj = 0;
62804ac863bSchristos $$.x = current_position.x;
62904ac863bSchristos $$.y = current_position.y;
63004ac863bSchristos }
63104ac863bSchristos ;
63204ac863bSchristos
63304ac863bSchristos optional_element:
63404ac863bSchristos /* empty */
63504ac863bSchristos {}
63604ac863bSchristos | element
63704ac863bSchristos {}
63804ac863bSchristos ;
63904ac863bSchristos
64004ac863bSchristos object_spec:
64104ac863bSchristos BOX
64204ac863bSchristos { $$ = new object_spec(BOX_OBJECT); }
64304ac863bSchristos | CIRCLE
64404ac863bSchristos { $$ = new object_spec(CIRCLE_OBJECT); }
64504ac863bSchristos | ELLIPSE
64604ac863bSchristos { $$ = new object_spec(ELLIPSE_OBJECT); }
64704ac863bSchristos | ARC
64804ac863bSchristos {
64904ac863bSchristos $$ = new object_spec(ARC_OBJECT);
65004ac863bSchristos $$->dir = current_direction;
65104ac863bSchristos }
65204ac863bSchristos | LINE
65304ac863bSchristos {
65404ac863bSchristos $$ = new object_spec(LINE_OBJECT);
65504ac863bSchristos lookup_variable("lineht", & $$->segment_height);
65604ac863bSchristos lookup_variable("linewid", & $$->segment_width);
65704ac863bSchristos $$->dir = current_direction;
65804ac863bSchristos }
65904ac863bSchristos | ARROW
66004ac863bSchristos {
66104ac863bSchristos $$ = new object_spec(ARROW_OBJECT);
66204ac863bSchristos lookup_variable("lineht", & $$->segment_height);
66304ac863bSchristos lookup_variable("linewid", & $$->segment_width);
66404ac863bSchristos $$->dir = current_direction;
66504ac863bSchristos }
66604ac863bSchristos | MOVE
66704ac863bSchristos {
66804ac863bSchristos $$ = new object_spec(MOVE_OBJECT);
66904ac863bSchristos lookup_variable("moveht", & $$->segment_height);
67004ac863bSchristos lookup_variable("movewid", & $$->segment_width);
67104ac863bSchristos $$->dir = current_direction;
67204ac863bSchristos }
67304ac863bSchristos | SPLINE
67404ac863bSchristos {
67504ac863bSchristos $$ = new object_spec(SPLINE_OBJECT);
67604ac863bSchristos lookup_variable("lineht", & $$->segment_height);
67704ac863bSchristos lookup_variable("linewid", & $$->segment_width);
67804ac863bSchristos $$->dir = current_direction;
67904ac863bSchristos }
68004ac863bSchristos | text %prec TEXT
68104ac863bSchristos {
68204ac863bSchristos $$ = new object_spec(TEXT_OBJECT);
68304ac863bSchristos $$->text = new text_item($1.str, $1.filename, $1.lineno);
68404ac863bSchristos }
68504ac863bSchristos | PLOT expr
68604ac863bSchristos {
68704ac863bSchristos $$ = new object_spec(TEXT_OBJECT);
68804ac863bSchristos $$->text = new text_item(format_number(0, $2), 0, -1);
68904ac863bSchristos }
69004ac863bSchristos | PLOT expr text
69104ac863bSchristos {
69204ac863bSchristos $$ = new object_spec(TEXT_OBJECT);
69304ac863bSchristos $$->text = new text_item(format_number($3.str, $2),
69404ac863bSchristos $3.filename, $3.lineno);
69504ac863bSchristos a_delete $3.str;
69604ac863bSchristos }
69704ac863bSchristos | '['
69804ac863bSchristos {
69904ac863bSchristos saved_state *p = new saved_state;
70004ac863bSchristos $<pstate>$ = p;
70104ac863bSchristos p->x = current_position.x;
70204ac863bSchristos p->y = current_position.y;
70304ac863bSchristos p->dir = current_direction;
70404ac863bSchristos p->tbl = current_table;
70504ac863bSchristos p->prev = current_saved_state;
70604ac863bSchristos current_position.x = 0.0;
70704ac863bSchristos current_position.y = 0.0;
70804ac863bSchristos current_table = new PTABLE(place);
70904ac863bSchristos current_saved_state = p;
71004ac863bSchristos olist.append(make_mark_object());
71104ac863bSchristos }
71204ac863bSchristos element_list ']'
71304ac863bSchristos {
71404ac863bSchristos current_position.x = $<pstate>2->x;
71504ac863bSchristos current_position.y = $<pstate>2->y;
71604ac863bSchristos current_direction = $<pstate>2->dir;
71704ac863bSchristos $$ = new object_spec(BLOCK_OBJECT);
71804ac863bSchristos olist.wrap_up_block(& $$->oblist);
71904ac863bSchristos $$->tbl = current_table;
72004ac863bSchristos current_table = $<pstate>2->tbl;
72104ac863bSchristos current_saved_state = $<pstate>2->prev;
72204ac863bSchristos delete $<pstate>2;
72304ac863bSchristos }
72404ac863bSchristos | object_spec HEIGHT expr
72504ac863bSchristos {
72604ac863bSchristos $$ = $1;
72704ac863bSchristos $$->height = $3;
72804ac863bSchristos $$->flags |= HAS_HEIGHT;
72904ac863bSchristos }
73004ac863bSchristos | object_spec RADIUS expr
73104ac863bSchristos {
73204ac863bSchristos $$ = $1;
73304ac863bSchristos $$->radius = $3;
73404ac863bSchristos $$->flags |= HAS_RADIUS;
73504ac863bSchristos }
73604ac863bSchristos | object_spec WIDTH expr
73704ac863bSchristos {
73804ac863bSchristos $$ = $1;
73904ac863bSchristos $$->width = $3;
74004ac863bSchristos $$->flags |= HAS_WIDTH;
74104ac863bSchristos }
74204ac863bSchristos | object_spec DIAMETER expr
74304ac863bSchristos {
74404ac863bSchristos $$ = $1;
74504ac863bSchristos $$->radius = $3/2.0;
74604ac863bSchristos $$->flags |= HAS_RADIUS;
74704ac863bSchristos }
74804ac863bSchristos | object_spec expr %prec HEIGHT
74904ac863bSchristos {
75004ac863bSchristos $$ = $1;
75104ac863bSchristos $$->flags |= HAS_SEGMENT;
75204ac863bSchristos switch ($$->dir) {
75304ac863bSchristos case UP_DIRECTION:
75404ac863bSchristos $$->segment_pos.y += $2;
75504ac863bSchristos break;
75604ac863bSchristos case DOWN_DIRECTION:
75704ac863bSchristos $$->segment_pos.y -= $2;
75804ac863bSchristos break;
75904ac863bSchristos case RIGHT_DIRECTION:
76004ac863bSchristos $$->segment_pos.x += $2;
76104ac863bSchristos break;
76204ac863bSchristos case LEFT_DIRECTION:
76304ac863bSchristos $$->segment_pos.x -= $2;
76404ac863bSchristos break;
76504ac863bSchristos }
76604ac863bSchristos }
76704ac863bSchristos | object_spec UP
76804ac863bSchristos {
76904ac863bSchristos $$ = $1;
77004ac863bSchristos $$->dir = UP_DIRECTION;
77104ac863bSchristos $$->flags |= HAS_SEGMENT;
77204ac863bSchristos $$->segment_pos.y += $$->segment_height;
77304ac863bSchristos }
77404ac863bSchristos | object_spec UP expr
77504ac863bSchristos {
77604ac863bSchristos $$ = $1;
77704ac863bSchristos $$->dir = UP_DIRECTION;
77804ac863bSchristos $$->flags |= HAS_SEGMENT;
77904ac863bSchristos $$->segment_pos.y += $3;
78004ac863bSchristos }
78104ac863bSchristos | object_spec DOWN
78204ac863bSchristos {
78304ac863bSchristos $$ = $1;
78404ac863bSchristos $$->dir = DOWN_DIRECTION;
78504ac863bSchristos $$->flags |= HAS_SEGMENT;
78604ac863bSchristos $$->segment_pos.y -= $$->segment_height;
78704ac863bSchristos }
78804ac863bSchristos | object_spec DOWN expr
78904ac863bSchristos {
79004ac863bSchristos $$ = $1;
79104ac863bSchristos $$->dir = DOWN_DIRECTION;
79204ac863bSchristos $$->flags |= HAS_SEGMENT;
79304ac863bSchristos $$->segment_pos.y -= $3;
79404ac863bSchristos }
79504ac863bSchristos | object_spec RIGHT
79604ac863bSchristos {
79704ac863bSchristos $$ = $1;
79804ac863bSchristos $$->dir = RIGHT_DIRECTION;
79904ac863bSchristos $$->flags |= HAS_SEGMENT;
80004ac863bSchristos $$->segment_pos.x += $$->segment_width;
80104ac863bSchristos }
80204ac863bSchristos | object_spec RIGHT expr
80304ac863bSchristos {
80404ac863bSchristos $$ = $1;
80504ac863bSchristos $$->dir = RIGHT_DIRECTION;
80604ac863bSchristos $$->flags |= HAS_SEGMENT;
80704ac863bSchristos $$->segment_pos.x += $3;
80804ac863bSchristos }
80904ac863bSchristos | object_spec LEFT
81004ac863bSchristos {
81104ac863bSchristos $$ = $1;
81204ac863bSchristos $$->dir = LEFT_DIRECTION;
81304ac863bSchristos $$->flags |= HAS_SEGMENT;
81404ac863bSchristos $$->segment_pos.x -= $$->segment_width;
81504ac863bSchristos }
81604ac863bSchristos | object_spec LEFT expr
81704ac863bSchristos {
81804ac863bSchristos $$ = $1;
81904ac863bSchristos $$->dir = LEFT_DIRECTION;
82004ac863bSchristos $$->flags |= HAS_SEGMENT;
82104ac863bSchristos $$->segment_pos.x -= $3;
82204ac863bSchristos }
82304ac863bSchristos | object_spec FROM position
82404ac863bSchristos {
82504ac863bSchristos $$ = $1;
82604ac863bSchristos $$->flags |= HAS_FROM;
82704ac863bSchristos $$->from.x = $3.x;
82804ac863bSchristos $$->from.y = $3.y;
82904ac863bSchristos }
83004ac863bSchristos | object_spec TO position
83104ac863bSchristos {
83204ac863bSchristos $$ = $1;
83304ac863bSchristos if ($$->flags & HAS_SEGMENT)
83404ac863bSchristos $$->segment_list = new segment($$->segment_pos,
83504ac863bSchristos $$->segment_is_absolute,
83604ac863bSchristos $$->segment_list);
83704ac863bSchristos $$->flags |= HAS_SEGMENT;
83804ac863bSchristos $$->segment_pos.x = $3.x;
83904ac863bSchristos $$->segment_pos.y = $3.y;
84004ac863bSchristos $$->segment_is_absolute = 1;
84104ac863bSchristos $$->flags |= HAS_TO;
84204ac863bSchristos $$->to.x = $3.x;
84304ac863bSchristos $$->to.y = $3.y;
84404ac863bSchristos }
84504ac863bSchristos | object_spec AT position
84604ac863bSchristos {
84704ac863bSchristos $$ = $1;
84804ac863bSchristos $$->flags |= HAS_AT;
84904ac863bSchristos $$->at.x = $3.x;
85004ac863bSchristos $$->at.y = $3.y;
85104ac863bSchristos if ($$->type != ARC_OBJECT) {
85204ac863bSchristos $$->flags |= HAS_FROM;
85304ac863bSchristos $$->from.x = $3.x;
85404ac863bSchristos $$->from.y = $3.y;
85504ac863bSchristos }
85604ac863bSchristos }
85704ac863bSchristos | object_spec WITH path
85804ac863bSchristos {
85904ac863bSchristos $$ = $1;
86004ac863bSchristos $$->flags |= HAS_WITH;
86104ac863bSchristos $$->with = $3;
86204ac863bSchristos }
86304ac863bSchristos | object_spec WITH position %prec ','
86404ac863bSchristos {
86504ac863bSchristos $$ = $1;
86604ac863bSchristos $$->flags |= HAS_WITH;
86704ac863bSchristos position pos;
86804ac863bSchristos pos.x = $3.x;
86904ac863bSchristos pos.y = $3.y;
87004ac863bSchristos $$->with = new path(pos);
87104ac863bSchristos }
87204ac863bSchristos | object_spec BY expr_pair
87304ac863bSchristos {
87404ac863bSchristos $$ = $1;
87504ac863bSchristos $$->flags |= HAS_SEGMENT;
87604ac863bSchristos $$->segment_pos.x += $3.x;
87704ac863bSchristos $$->segment_pos.y += $3.y;
87804ac863bSchristos }
87904ac863bSchristos | object_spec THEN
88004ac863bSchristos {
88104ac863bSchristos $$ = $1;
88204ac863bSchristos if ($$->flags & HAS_SEGMENT) {
88304ac863bSchristos $$->segment_list = new segment($$->segment_pos,
88404ac863bSchristos $$->segment_is_absolute,
88504ac863bSchristos $$->segment_list);
88604ac863bSchristos $$->flags &= ~HAS_SEGMENT;
88704ac863bSchristos $$->segment_pos.x = $$->segment_pos.y = 0.0;
88804ac863bSchristos $$->segment_is_absolute = 0;
88904ac863bSchristos }
89004ac863bSchristos }
89104ac863bSchristos | object_spec SOLID
89204ac863bSchristos {
89304ac863bSchristos $$ = $1; // nothing
89404ac863bSchristos }
89504ac863bSchristos | object_spec DOTTED
89604ac863bSchristos {
89704ac863bSchristos $$ = $1;
89804ac863bSchristos $$->flags |= IS_DOTTED;
89904ac863bSchristos lookup_variable("dashwid", & $$->dash_width);
90004ac863bSchristos }
90104ac863bSchristos | object_spec DOTTED expr
90204ac863bSchristos {
90304ac863bSchristos $$ = $1;
90404ac863bSchristos $$->flags |= IS_DOTTED;
90504ac863bSchristos $$->dash_width = $3;
90604ac863bSchristos }
90704ac863bSchristos | object_spec DASHED
90804ac863bSchristos {
90904ac863bSchristos $$ = $1;
91004ac863bSchristos $$->flags |= IS_DASHED;
91104ac863bSchristos lookup_variable("dashwid", & $$->dash_width);
91204ac863bSchristos }
91304ac863bSchristos | object_spec DASHED expr
91404ac863bSchristos {
91504ac863bSchristos $$ = $1;
91604ac863bSchristos $$->flags |= IS_DASHED;
91704ac863bSchristos $$->dash_width = $3;
91804ac863bSchristos }
91904ac863bSchristos | object_spec FILL
92004ac863bSchristos {
92104ac863bSchristos $$ = $1;
92204ac863bSchristos $$->flags |= IS_DEFAULT_FILLED;
92304ac863bSchristos }
92404ac863bSchristos | object_spec FILL expr
92504ac863bSchristos {
92604ac863bSchristos $$ = $1;
92704ac863bSchristos $$->flags |= IS_FILLED;
92804ac863bSchristos $$->fill = $3;
92904ac863bSchristos }
93004ac863bSchristos | object_spec SHADED text
93104ac863bSchristos {
93204ac863bSchristos $$ = $1;
93304ac863bSchristos $$->flags |= (IS_SHADED | IS_FILLED);
93404ac863bSchristos $$->shaded = new char[strlen($3.str)+1];
93504ac863bSchristos strcpy($$->shaded, $3.str);
93604ac863bSchristos }
93704ac863bSchristos | object_spec COLORED text
93804ac863bSchristos {
93904ac863bSchristos $$ = $1;
94004ac863bSchristos $$->flags |= (IS_SHADED | IS_OUTLINED | IS_FILLED);
94104ac863bSchristos $$->shaded = new char[strlen($3.str)+1];
94204ac863bSchristos strcpy($$->shaded, $3.str);
94304ac863bSchristos $$->outlined = new char[strlen($3.str)+1];
94404ac863bSchristos strcpy($$->outlined, $3.str);
94504ac863bSchristos }
94604ac863bSchristos | object_spec OUTLINED text
94704ac863bSchristos {
94804ac863bSchristos $$ = $1;
94904ac863bSchristos $$->flags |= IS_OUTLINED;
95004ac863bSchristos $$->outlined = new char[strlen($3.str)+1];
95104ac863bSchristos strcpy($$->outlined, $3.str);
95204ac863bSchristos }
95304ac863bSchristos | object_spec CHOP
95404ac863bSchristos {
95504ac863bSchristos $$ = $1;
95604ac863bSchristos // line chop chop means line chop 0 chop 0
95704ac863bSchristos if ($$->flags & IS_DEFAULT_CHOPPED) {
95804ac863bSchristos $$->flags |= IS_CHOPPED;
95904ac863bSchristos $$->flags &= ~IS_DEFAULT_CHOPPED;
96004ac863bSchristos $$->start_chop = $$->end_chop = 0.0;
96104ac863bSchristos }
96204ac863bSchristos else if ($$->flags & IS_CHOPPED) {
96304ac863bSchristos $$->end_chop = 0.0;
96404ac863bSchristos }
96504ac863bSchristos else {
96604ac863bSchristos $$->flags |= IS_DEFAULT_CHOPPED;
96704ac863bSchristos }
96804ac863bSchristos }
96904ac863bSchristos | object_spec CHOP expr
97004ac863bSchristos {
97104ac863bSchristos $$ = $1;
97204ac863bSchristos if ($$->flags & IS_DEFAULT_CHOPPED) {
97304ac863bSchristos $$->flags |= IS_CHOPPED;
97404ac863bSchristos $$->flags &= ~IS_DEFAULT_CHOPPED;
97504ac863bSchristos $$->start_chop = 0.0;
97604ac863bSchristos $$->end_chop = $3;
97704ac863bSchristos }
97804ac863bSchristos else if ($$->flags & IS_CHOPPED) {
97904ac863bSchristos $$->end_chop = $3;
98004ac863bSchristos }
98104ac863bSchristos else {
98204ac863bSchristos $$->start_chop = $$->end_chop = $3;
98304ac863bSchristos $$->flags |= IS_CHOPPED;
98404ac863bSchristos }
98504ac863bSchristos }
98604ac863bSchristos | object_spec SAME
98704ac863bSchristos {
98804ac863bSchristos $$ = $1;
98904ac863bSchristos $$->flags |= IS_SAME;
99004ac863bSchristos }
99104ac863bSchristos | object_spec INVISIBLE
99204ac863bSchristos {
99304ac863bSchristos $$ = $1;
99404ac863bSchristos $$->flags |= IS_INVISIBLE;
99504ac863bSchristos }
99604ac863bSchristos | object_spec LEFT_ARROW_HEAD
99704ac863bSchristos {
99804ac863bSchristos $$ = $1;
99904ac863bSchristos $$->flags |= HAS_LEFT_ARROW_HEAD;
100004ac863bSchristos }
100104ac863bSchristos | object_spec RIGHT_ARROW_HEAD
100204ac863bSchristos {
100304ac863bSchristos $$ = $1;
100404ac863bSchristos $$->flags |= HAS_RIGHT_ARROW_HEAD;
100504ac863bSchristos }
100604ac863bSchristos | object_spec DOUBLE_ARROW_HEAD
100704ac863bSchristos {
100804ac863bSchristos $$ = $1;
100904ac863bSchristos $$->flags |= (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD);
101004ac863bSchristos }
101104ac863bSchristos | object_spec CW
101204ac863bSchristos {
101304ac863bSchristos $$ = $1;
101404ac863bSchristos $$->flags |= IS_CLOCKWISE;
101504ac863bSchristos }
101604ac863bSchristos | object_spec CCW
101704ac863bSchristos {
101804ac863bSchristos $$ = $1;
101904ac863bSchristos $$->flags &= ~IS_CLOCKWISE;
102004ac863bSchristos }
102104ac863bSchristos | object_spec text %prec TEXT
102204ac863bSchristos {
102304ac863bSchristos $$ = $1;
102404ac863bSchristos text_item **p;
102504ac863bSchristos for (p = & $$->text; *p; p = &(*p)->next)
102604ac863bSchristos ;
102704ac863bSchristos *p = new text_item($2.str, $2.filename, $2.lineno);
102804ac863bSchristos }
102904ac863bSchristos | object_spec LJUST
103004ac863bSchristos {
103104ac863bSchristos $$ = $1;
103204ac863bSchristos if ($$->text) {
103304ac863bSchristos text_item *p;
103404ac863bSchristos for (p = $$->text; p->next; p = p->next)
103504ac863bSchristos ;
103604ac863bSchristos p->adj.h = LEFT_ADJUST;
103704ac863bSchristos }
103804ac863bSchristos }
103904ac863bSchristos | object_spec RJUST
104004ac863bSchristos {
104104ac863bSchristos $$ = $1;
104204ac863bSchristos if ($$->text) {
104304ac863bSchristos text_item *p;
104404ac863bSchristos for (p = $$->text; p->next; p = p->next)
104504ac863bSchristos ;
104604ac863bSchristos p->adj.h = RIGHT_ADJUST;
104704ac863bSchristos }
104804ac863bSchristos }
104904ac863bSchristos | object_spec ABOVE
105004ac863bSchristos {
105104ac863bSchristos $$ = $1;
105204ac863bSchristos if ($$->text) {
105304ac863bSchristos text_item *p;
105404ac863bSchristos for (p = $$->text; p->next; p = p->next)
105504ac863bSchristos ;
105604ac863bSchristos p->adj.v = ABOVE_ADJUST;
105704ac863bSchristos }
105804ac863bSchristos }
105904ac863bSchristos | object_spec BELOW
106004ac863bSchristos {
106104ac863bSchristos $$ = $1;
106204ac863bSchristos if ($$->text) {
106304ac863bSchristos text_item *p;
106404ac863bSchristos for (p = $$->text; p->next; p = p->next)
106504ac863bSchristos ;
106604ac863bSchristos p->adj.v = BELOW_ADJUST;
106704ac863bSchristos }
106804ac863bSchristos }
106904ac863bSchristos | object_spec THICKNESS expr
107004ac863bSchristos {
107104ac863bSchristos $$ = $1;
107204ac863bSchristos $$->flags |= HAS_THICKNESS;
107304ac863bSchristos $$->thickness = $3;
107404ac863bSchristos }
107504ac863bSchristos | object_spec ALIGNED
107604ac863bSchristos {
107704ac863bSchristos $$ = $1;
107804ac863bSchristos $$->flags |= IS_ALIGNED;
107904ac863bSchristos }
108004ac863bSchristos ;
108104ac863bSchristos
108204ac863bSchristos text:
108304ac863bSchristos TEXT
108404ac863bSchristos { $$ = $1; }
108504ac863bSchristos | SPRINTF '(' TEXT sprintf_args ')'
108604ac863bSchristos {
108704ac863bSchristos $$.filename = $3.filename;
108804ac863bSchristos $$.lineno = $3.lineno;
108904ac863bSchristos $$.str = do_sprintf($3.str, $4.v, $4.nv);
109004ac863bSchristos a_delete $4.v;
109104ac863bSchristos a_delete $3.str;
109204ac863bSchristos }
109304ac863bSchristos ;
109404ac863bSchristos
109504ac863bSchristos sprintf_args:
109604ac863bSchristos /* empty */
109704ac863bSchristos {
109804ac863bSchristos $$.v = 0;
109904ac863bSchristos $$.nv = 0;
110004ac863bSchristos $$.maxv = 0;
110104ac863bSchristos }
110204ac863bSchristos | sprintf_args ',' expr
110304ac863bSchristos {
110404ac863bSchristos $$ = $1;
110504ac863bSchristos if ($$.nv >= $$.maxv) {
110604ac863bSchristos if ($$.nv == 0) {
110704ac863bSchristos $$.v = new double[4];
110804ac863bSchristos $$.maxv = 4;
110904ac863bSchristos }
111004ac863bSchristos else {
111104ac863bSchristos double *oldv = $$.v;
111204ac863bSchristos $$.maxv *= 2;
111304ac863bSchristos #if 0
111404ac863bSchristos $$.v = new double[$$.maxv];
111504ac863bSchristos memcpy($$.v, oldv, $$.nv*sizeof(double));
111604ac863bSchristos #else
111704ac863bSchristos // workaround for bug in Compaq C++ V6.5-033
111804ac863bSchristos // for Compaq Tru64 UNIX V5.1A (Rev. 1885)
111904ac863bSchristos double *foo = new double[$$.maxv];
112004ac863bSchristos memcpy(foo, oldv, $$.nv*sizeof(double));
112104ac863bSchristos $$.v = foo;
112204ac863bSchristos #endif
112304ac863bSchristos a_delete oldv;
112404ac863bSchristos }
112504ac863bSchristos }
112604ac863bSchristos $$.v[$$.nv] = $3;
112704ac863bSchristos $$.nv += 1;
112804ac863bSchristos }
112904ac863bSchristos ;
113004ac863bSchristos
113104ac863bSchristos position:
113204ac863bSchristos position_not_place
113304ac863bSchristos { $$ = $1; }
113404ac863bSchristos | place
113504ac863bSchristos {
113604ac863bSchristos position pos = $1;
113704ac863bSchristos $$.x = pos.x;
113804ac863bSchristos $$.y = pos.y;
113904ac863bSchristos }
114004ac863bSchristos | '(' place ')'
114104ac863bSchristos {
114204ac863bSchristos position pos = $2;
114304ac863bSchristos $$.x = pos.x;
114404ac863bSchristos $$.y = pos.y;
114504ac863bSchristos }
114604ac863bSchristos ;
114704ac863bSchristos
114804ac863bSchristos position_not_place:
114904ac863bSchristos expr_pair
115004ac863bSchristos { $$ = $1; }
115104ac863bSchristos | position '+' expr_pair
115204ac863bSchristos {
115304ac863bSchristos $$.x = $1.x + $3.x;
115404ac863bSchristos $$.y = $1.y + $3.y;
115504ac863bSchristos }
115604ac863bSchristos | '(' position '+' expr_pair ')'
115704ac863bSchristos {
115804ac863bSchristos $$.x = $2.x + $4.x;
115904ac863bSchristos $$.y = $2.y + $4.y;
116004ac863bSchristos }
116104ac863bSchristos | position '-' expr_pair
116204ac863bSchristos {
116304ac863bSchristos $$.x = $1.x - $3.x;
116404ac863bSchristos $$.y = $1.y - $3.y;
116504ac863bSchristos }
116604ac863bSchristos | '(' position '-' expr_pair ')'
116704ac863bSchristos {
116804ac863bSchristos $$.x = $2.x - $4.x;
116904ac863bSchristos $$.y = $2.y - $4.y;
117004ac863bSchristos }
117104ac863bSchristos | '(' position ',' position ')'
117204ac863bSchristos {
117304ac863bSchristos $$.x = $2.x;
117404ac863bSchristos $$.y = $4.y;
117504ac863bSchristos }
117604ac863bSchristos | expr between position AND position
117704ac863bSchristos {
117804ac863bSchristos $$.x = (1.0 - $1)*$3.x + $1*$5.x;
117904ac863bSchristos $$.y = (1.0 - $1)*$3.y + $1*$5.y;
118004ac863bSchristos }
118104ac863bSchristos | '(' expr between position AND position ')'
118204ac863bSchristos {
118304ac863bSchristos $$.x = (1.0 - $2)*$4.x + $2*$6.x;
118404ac863bSchristos $$.y = (1.0 - $2)*$4.y + $2*$6.y;
118504ac863bSchristos }
118604ac863bSchristos | expr '<' position ',' position '>'
118704ac863bSchristos {
118804ac863bSchristos $$.x = (1.0 - $1)*$3.x + $1*$5.x;
118904ac863bSchristos $$.y = (1.0 - $1)*$3.y + $1*$5.y;
119004ac863bSchristos }
119104ac863bSchristos | '(' expr '<' position ',' position '>' ')'
119204ac863bSchristos {
119304ac863bSchristos $$.x = (1.0 - $2)*$4.x + $2*$6.x;
119404ac863bSchristos $$.y = (1.0 - $2)*$4.y + $2*$6.y;
119504ac863bSchristos }
119604ac863bSchristos ;
119704ac863bSchristos
119804ac863bSchristos between:
119904ac863bSchristos BETWEEN
120004ac863bSchristos | OF THE WAY BETWEEN
120104ac863bSchristos ;
120204ac863bSchristos
120304ac863bSchristos expr_pair:
120404ac863bSchristos expr ',' expr
120504ac863bSchristos {
120604ac863bSchristos $$.x = $1;
120704ac863bSchristos $$.y = $3;
120804ac863bSchristos }
120904ac863bSchristos | '(' expr_pair ')'
121004ac863bSchristos { $$ = $2; }
121104ac863bSchristos ;
121204ac863bSchristos
121304ac863bSchristos place:
121404ac863bSchristos /* line at A left == line (at A) left */
121504ac863bSchristos label %prec CHOP
121604ac863bSchristos { $$ = $1; }
121704ac863bSchristos | label corner
121804ac863bSchristos {
121904ac863bSchristos path pth($2);
122004ac863bSchristos if (!pth.follow($1, & $$))
122104ac863bSchristos YYABORT;
122204ac863bSchristos }
122304ac863bSchristos | corner label
122404ac863bSchristos {
122504ac863bSchristos path pth($1);
122604ac863bSchristos if (!pth.follow($2, & $$))
122704ac863bSchristos YYABORT;
122804ac863bSchristos }
122904ac863bSchristos | corner OF label
123004ac863bSchristos {
123104ac863bSchristos path pth($1);
123204ac863bSchristos if (!pth.follow($3, & $$))
123304ac863bSchristos YYABORT;
123404ac863bSchristos }
123504ac863bSchristos | HERE
123604ac863bSchristos {
123704ac863bSchristos $$.x = current_position.x;
123804ac863bSchristos $$.y = current_position.y;
123904ac863bSchristos $$.obj = 0;
124004ac863bSchristos }
124104ac863bSchristos ;
124204ac863bSchristos
124304ac863bSchristos label:
124404ac863bSchristos LABEL
124504ac863bSchristos {
124604ac863bSchristos place *p = lookup_label($1);
124704ac863bSchristos if (!p) {
124804ac863bSchristos lex_error("there is no place `%1'", $1);
124904ac863bSchristos YYABORT;
125004ac863bSchristos }
125104ac863bSchristos $$ = *p;
125204ac863bSchristos a_delete $1;
125304ac863bSchristos }
125404ac863bSchristos | nth_primitive
125504ac863bSchristos { $$.obj = $1; }
125604ac863bSchristos | label '.' LABEL
125704ac863bSchristos {
125804ac863bSchristos path pth($3);
125904ac863bSchristos if (!pth.follow($1, & $$))
126004ac863bSchristos YYABORT;
126104ac863bSchristos }
126204ac863bSchristos ;
126304ac863bSchristos
126404ac863bSchristos ordinal:
126504ac863bSchristos ORDINAL
126604ac863bSchristos { $$ = $1; }
126704ac863bSchristos | '`' any_expr TH
126804ac863bSchristos {
126904ac863bSchristos // XXX Check for overflow (and non-integers?).
127004ac863bSchristos $$ = (int)$2;
127104ac863bSchristos }
127204ac863bSchristos ;
127304ac863bSchristos
127404ac863bSchristos optional_ordinal_last:
127504ac863bSchristos LAST
127604ac863bSchristos { $$ = 1; }
127704ac863bSchristos | ordinal LAST
127804ac863bSchristos { $$ = $1; }
127904ac863bSchristos ;
128004ac863bSchristos
128104ac863bSchristos nth_primitive:
128204ac863bSchristos ordinal object_type
128304ac863bSchristos {
128404ac863bSchristos int count = 0;
128504ac863bSchristos object *p;
128604ac863bSchristos for (p = olist.head; p != 0; p = p->next)
128704ac863bSchristos if (p->type() == $2 && ++count == $1) {
128804ac863bSchristos $$ = p;
128904ac863bSchristos break;
129004ac863bSchristos }
129104ac863bSchristos if (p == 0) {
129204ac863bSchristos lex_error("there is no %1%2 %3", $1, ordinal_postfix($1),
129304ac863bSchristos object_type_name($2));
129404ac863bSchristos YYABORT;
129504ac863bSchristos }
129604ac863bSchristos }
129704ac863bSchristos | optional_ordinal_last object_type
129804ac863bSchristos {
129904ac863bSchristos int count = 0;
130004ac863bSchristos object *p;
130104ac863bSchristos for (p = olist.tail; p != 0; p = p->prev)
130204ac863bSchristos if (p->type() == $2 && ++count == $1) {
130304ac863bSchristos $$ = p;
130404ac863bSchristos break;
130504ac863bSchristos }
130604ac863bSchristos if (p == 0) {
130704ac863bSchristos lex_error("there is no %1%2 last %3", $1,
130804ac863bSchristos ordinal_postfix($1), object_type_name($2));
130904ac863bSchristos YYABORT;
131004ac863bSchristos }
131104ac863bSchristos }
131204ac863bSchristos ;
131304ac863bSchristos
131404ac863bSchristos object_type:
131504ac863bSchristos BOX
131604ac863bSchristos { $$ = BOX_OBJECT; }
131704ac863bSchristos | CIRCLE
131804ac863bSchristos { $$ = CIRCLE_OBJECT; }
131904ac863bSchristos | ELLIPSE
132004ac863bSchristos { $$ = ELLIPSE_OBJECT; }
132104ac863bSchristos | ARC
132204ac863bSchristos { $$ = ARC_OBJECT; }
132304ac863bSchristos | LINE
132404ac863bSchristos { $$ = LINE_OBJECT; }
132504ac863bSchristos | ARROW
132604ac863bSchristos { $$ = ARROW_OBJECT; }
132704ac863bSchristos | SPLINE
132804ac863bSchristos { $$ = SPLINE_OBJECT; }
132904ac863bSchristos | '[' ']'
133004ac863bSchristos { $$ = BLOCK_OBJECT; }
133104ac863bSchristos | TEXT
133204ac863bSchristos { $$ = TEXT_OBJECT; }
133304ac863bSchristos ;
133404ac863bSchristos
133504ac863bSchristos label_path:
133604ac863bSchristos '.' LABEL
133704ac863bSchristos { $$ = new path($2); }
133804ac863bSchristos | label_path '.' LABEL
133904ac863bSchristos {
134004ac863bSchristos $$ = $1;
134104ac863bSchristos $$->append($3);
134204ac863bSchristos }
134304ac863bSchristos ;
134404ac863bSchristos
134504ac863bSchristos relative_path:
134604ac863bSchristos corner %prec CHOP
134704ac863bSchristos { $$ = new path($1); }
134804ac863bSchristos /* give this a lower precedence than LEFT and RIGHT so that
134904ac863bSchristos [A: box] with .A left == [A: box] with (.A left) */
135004ac863bSchristos | label_path %prec TEXT
135104ac863bSchristos { $$ = $1; }
135204ac863bSchristos | label_path corner
135304ac863bSchristos {
135404ac863bSchristos $$ = $1;
135504ac863bSchristos $$->append($2);
135604ac863bSchristos }
135704ac863bSchristos ;
135804ac863bSchristos
135904ac863bSchristos path:
136004ac863bSchristos relative_path
136104ac863bSchristos { $$ = $1; }
136204ac863bSchristos | '(' relative_path ',' relative_path ')'
136304ac863bSchristos {
136404ac863bSchristos $$ = $2;
136504ac863bSchristos $$->set_ypath($4);
136604ac863bSchristos }
136704ac863bSchristos /* The rest of these rules are a compatibility sop. */
136804ac863bSchristos | ORDINAL LAST object_type relative_path
136904ac863bSchristos {
137004ac863bSchristos lex_warning("`%1%2 last %3' in `with' argument ignored",
137104ac863bSchristos $1, ordinal_postfix($1), object_type_name($3));
137204ac863bSchristos $$ = $4;
137304ac863bSchristos }
137404ac863bSchristos | LAST object_type relative_path
137504ac863bSchristos {
137604ac863bSchristos lex_warning("`last %1' in `with' argument ignored",
137704ac863bSchristos object_type_name($2));
137804ac863bSchristos $$ = $3;
137904ac863bSchristos }
138004ac863bSchristos | ORDINAL object_type relative_path
138104ac863bSchristos {
138204ac863bSchristos lex_warning("`%1%2 %3' in `with' argument ignored",
138304ac863bSchristos $1, ordinal_postfix($1), object_type_name($2));
138404ac863bSchristos $$ = $3;
138504ac863bSchristos }
138604ac863bSchristos | LABEL relative_path
138704ac863bSchristos {
138804ac863bSchristos lex_warning("initial `%1' in `with' argument ignored", $1);
138904ac863bSchristos a_delete $1;
139004ac863bSchristos $$ = $2;
139104ac863bSchristos }
139204ac863bSchristos ;
139304ac863bSchristos
139404ac863bSchristos corner:
139504ac863bSchristos DOT_N
139604ac863bSchristos { $$ = &object::north; }
139704ac863bSchristos | DOT_E
139804ac863bSchristos { $$ = &object::east; }
139904ac863bSchristos | DOT_W
140004ac863bSchristos { $$ = &object::west; }
140104ac863bSchristos | DOT_S
140204ac863bSchristos { $$ = &object::south; }
140304ac863bSchristos | DOT_NE
140404ac863bSchristos { $$ = &object::north_east; }
140504ac863bSchristos | DOT_SE
140604ac863bSchristos { $$ = &object:: south_east; }
140704ac863bSchristos | DOT_NW
140804ac863bSchristos { $$ = &object::north_west; }
140904ac863bSchristos | DOT_SW
141004ac863bSchristos { $$ = &object::south_west; }
141104ac863bSchristos | DOT_C
141204ac863bSchristos { $$ = &object::center; }
141304ac863bSchristos | DOT_START
141404ac863bSchristos { $$ = &object::start; }
141504ac863bSchristos | DOT_END
141604ac863bSchristos { $$ = &object::end; }
141704ac863bSchristos | TOP
141804ac863bSchristos { $$ = &object::north; }
141904ac863bSchristos | BOTTOM
142004ac863bSchristos { $$ = &object::south; }
142104ac863bSchristos | LEFT
142204ac863bSchristos { $$ = &object::west; }
142304ac863bSchristos | RIGHT
142404ac863bSchristos { $$ = &object::east; }
142504ac863bSchristos | UPPER LEFT
142604ac863bSchristos { $$ = &object::north_west; }
142704ac863bSchristos | LOWER LEFT
142804ac863bSchristos { $$ = &object::south_west; }
142904ac863bSchristos | UPPER RIGHT
143004ac863bSchristos { $$ = &object::north_east; }
143104ac863bSchristos | LOWER RIGHT
143204ac863bSchristos { $$ = &object::south_east; }
143304ac863bSchristos | LEFT_CORNER
143404ac863bSchristos { $$ = &object::west; }
143504ac863bSchristos | RIGHT_CORNER
143604ac863bSchristos { $$ = &object::east; }
143704ac863bSchristos | UPPER LEFT_CORNER
143804ac863bSchristos { $$ = &object::north_west; }
143904ac863bSchristos | LOWER LEFT_CORNER
144004ac863bSchristos { $$ = &object::south_west; }
144104ac863bSchristos | UPPER RIGHT_CORNER
144204ac863bSchristos { $$ = &object::north_east; }
144304ac863bSchristos | LOWER RIGHT_CORNER
144404ac863bSchristos { $$ = &object::south_east; }
144504ac863bSchristos | NORTH
144604ac863bSchristos { $$ = &object::north; }
144704ac863bSchristos | SOUTH
144804ac863bSchristos { $$ = &object::south; }
144904ac863bSchristos | EAST
145004ac863bSchristos { $$ = &object::east; }
145104ac863bSchristos | WEST
145204ac863bSchristos { $$ = &object::west; }
145304ac863bSchristos | CENTER
145404ac863bSchristos { $$ = &object::center; }
145504ac863bSchristos | START
145604ac863bSchristos { $$ = &object::start; }
145704ac863bSchristos | END
145804ac863bSchristos { $$ = &object::end; }
145904ac863bSchristos ;
146004ac863bSchristos
146104ac863bSchristos expr:
146204ac863bSchristos VARIABLE
146304ac863bSchristos {
146404ac863bSchristos if (!lookup_variable($1, & $$)) {
146504ac863bSchristos lex_error("there is no variable `%1'", $1);
146604ac863bSchristos YYABORT;
146704ac863bSchristos }
146804ac863bSchristos a_delete $1;
146904ac863bSchristos }
147004ac863bSchristos | NUMBER
147104ac863bSchristos { $$ = $1; }
147204ac863bSchristos | place DOT_X
147304ac863bSchristos {
147404ac863bSchristos if ($1.obj != 0)
147504ac863bSchristos $$ = $1.obj->origin().x;
147604ac863bSchristos else
147704ac863bSchristos $$ = $1.x;
147804ac863bSchristos }
147904ac863bSchristos | place DOT_Y
148004ac863bSchristos {
148104ac863bSchristos if ($1.obj != 0)
148204ac863bSchristos $$ = $1.obj->origin().y;
148304ac863bSchristos else
148404ac863bSchristos $$ = $1.y;
148504ac863bSchristos }
148604ac863bSchristos | place DOT_HT
148704ac863bSchristos {
148804ac863bSchristos if ($1.obj != 0)
148904ac863bSchristos $$ = $1.obj->height();
149004ac863bSchristos else
149104ac863bSchristos $$ = 0.0;
149204ac863bSchristos }
149304ac863bSchristos | place DOT_WID
149404ac863bSchristos {
149504ac863bSchristos if ($1.obj != 0)
149604ac863bSchristos $$ = $1.obj->width();
149704ac863bSchristos else
149804ac863bSchristos $$ = 0.0;
149904ac863bSchristos }
150004ac863bSchristos | place DOT_RAD
150104ac863bSchristos {
150204ac863bSchristos if ($1.obj != 0)
150304ac863bSchristos $$ = $1.obj->radius();
150404ac863bSchristos else
150504ac863bSchristos $$ = 0.0;
150604ac863bSchristos }
150704ac863bSchristos | expr '+' expr
150804ac863bSchristos { $$ = $1 + $3; }
150904ac863bSchristos | expr '-' expr
151004ac863bSchristos { $$ = $1 - $3; }
151104ac863bSchristos | expr '*' expr
151204ac863bSchristos { $$ = $1 * $3; }
151304ac863bSchristos | expr '/' expr
151404ac863bSchristos {
151504ac863bSchristos if ($3 == 0.0) {
151604ac863bSchristos lex_error("division by zero");
151704ac863bSchristos YYABORT;
151804ac863bSchristos }
151904ac863bSchristos $$ = $1/$3;
152004ac863bSchristos }
152104ac863bSchristos | expr '%' expr
152204ac863bSchristos {
152304ac863bSchristos if ($3 == 0.0) {
152404ac863bSchristos lex_error("modulus by zero");
152504ac863bSchristos YYABORT;
152604ac863bSchristos }
152704ac863bSchristos $$ = fmod($1, $3);
152804ac863bSchristos }
152904ac863bSchristos | expr '^' expr
153004ac863bSchristos {
153104ac863bSchristos errno = 0;
153204ac863bSchristos $$ = pow($1, $3);
153304ac863bSchristos if (errno == EDOM) {
153404ac863bSchristos lex_error("arguments to `^' operator out of domain");
153504ac863bSchristos YYABORT;
153604ac863bSchristos }
153704ac863bSchristos if (errno == ERANGE) {
153804ac863bSchristos lex_error("result of `^' operator out of range");
153904ac863bSchristos YYABORT;
154004ac863bSchristos }
154104ac863bSchristos }
154204ac863bSchristos | '-' expr %prec '!'
154304ac863bSchristos { $$ = -$2; }
154404ac863bSchristos | '(' any_expr ')'
154504ac863bSchristos { $$ = $2; }
154604ac863bSchristos | SIN '(' any_expr ')'
154704ac863bSchristos {
154804ac863bSchristos errno = 0;
154904ac863bSchristos $$ = sin($3);
155004ac863bSchristos if (errno == ERANGE) {
155104ac863bSchristos lex_error("sin result out of range");
155204ac863bSchristos YYABORT;
155304ac863bSchristos }
155404ac863bSchristos }
155504ac863bSchristos | COS '(' any_expr ')'
155604ac863bSchristos {
155704ac863bSchristos errno = 0;
155804ac863bSchristos $$ = cos($3);
155904ac863bSchristos if (errno == ERANGE) {
156004ac863bSchristos lex_error("cos result out of range");
156104ac863bSchristos YYABORT;
156204ac863bSchristos }
156304ac863bSchristos }
156404ac863bSchristos | ATAN2 '(' any_expr ',' any_expr ')'
156504ac863bSchristos {
156604ac863bSchristos errno = 0;
156704ac863bSchristos $$ = atan2($3, $5);
156804ac863bSchristos if (errno == EDOM) {
156904ac863bSchristos lex_error("atan2 argument out of domain");
157004ac863bSchristos YYABORT;
157104ac863bSchristos }
157204ac863bSchristos if (errno == ERANGE) {
157304ac863bSchristos lex_error("atan2 result out of range");
157404ac863bSchristos YYABORT;
157504ac863bSchristos }
157604ac863bSchristos }
157704ac863bSchristos | LOG '(' any_expr ')'
157804ac863bSchristos {
157904ac863bSchristos errno = 0;
158004ac863bSchristos $$ = log10($3);
158104ac863bSchristos if (errno == ERANGE) {
158204ac863bSchristos lex_error("log result out of range");
158304ac863bSchristos YYABORT;
158404ac863bSchristos }
158504ac863bSchristos }
158604ac863bSchristos | EXP '(' any_expr ')'
158704ac863bSchristos {
158804ac863bSchristos errno = 0;
158904ac863bSchristos $$ = pow(10.0, $3);
159004ac863bSchristos if (errno == ERANGE) {
159104ac863bSchristos lex_error("exp result out of range");
159204ac863bSchristos YYABORT;
159304ac863bSchristos }
159404ac863bSchristos }
159504ac863bSchristos | SQRT '(' any_expr ')'
159604ac863bSchristos {
159704ac863bSchristos errno = 0;
159804ac863bSchristos $$ = sqrt($3);
159904ac863bSchristos if (errno == EDOM) {
160004ac863bSchristos lex_error("sqrt argument out of domain");
160104ac863bSchristos YYABORT;
160204ac863bSchristos }
160304ac863bSchristos }
160404ac863bSchristos | K_MAX '(' any_expr ',' any_expr ')'
160504ac863bSchristos { $$ = $3 > $5 ? $3 : $5; }
160604ac863bSchristos | K_MIN '(' any_expr ',' any_expr ')'
160704ac863bSchristos { $$ = $3 < $5 ? $3 : $5; }
160804ac863bSchristos | INT '(' any_expr ')'
160904ac863bSchristos { $$ = floor($3); }
161004ac863bSchristos | RAND '(' any_expr ')'
161104ac863bSchristos { $$ = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*$3); }
161204ac863bSchristos | RAND '(' ')'
161304ac863bSchristos {
161404ac863bSchristos /* return a random number in the range [0,1) */
161504ac863bSchristos /* portable, but not very random */
161604ac863bSchristos $$ = (rand() & 0x7fff) / double(0x8000);
161704ac863bSchristos }
161804ac863bSchristos | SRAND '(' any_expr ')'
161904ac863bSchristos {
162004ac863bSchristos $$ = 0;
162104ac863bSchristos srand((unsigned int)$3);
162204ac863bSchristos }
162304ac863bSchristos | expr '<' expr
162404ac863bSchristos { $$ = ($1 < $3); }
162504ac863bSchristos | expr LESSEQUAL expr
162604ac863bSchristos { $$ = ($1 <= $3); }
162704ac863bSchristos | expr '>' expr
162804ac863bSchristos { $$ = ($1 > $3); }
162904ac863bSchristos | expr GREATEREQUAL expr
163004ac863bSchristos { $$ = ($1 >= $3); }
163104ac863bSchristos | expr EQUALEQUAL expr
163204ac863bSchristos { $$ = ($1 == $3); }
163304ac863bSchristos | expr NOTEQUAL expr
163404ac863bSchristos { $$ = ($1 != $3); }
163504ac863bSchristos | expr ANDAND expr
163604ac863bSchristos { $$ = ($1 != 0.0 && $3 != 0.0); }
163704ac863bSchristos | expr OROR expr
163804ac863bSchristos { $$ = ($1 != 0.0 || $3 != 0.0); }
163904ac863bSchristos | '!' expr
164004ac863bSchristos { $$ = ($2 == 0.0); }
164104ac863bSchristos
164204ac863bSchristos ;
164304ac863bSchristos
164404ac863bSchristos %%
164504ac863bSchristos
164604ac863bSchristos /* bison defines const to be empty unless __STDC__ is defined, which it
164704ac863bSchristos isn't under cfront */
164804ac863bSchristos
164904ac863bSchristos #ifdef const
165004ac863bSchristos #undef const
165104ac863bSchristos #endif
165204ac863bSchristos
165304ac863bSchristos static struct {
165404ac863bSchristos const char *name;
165504ac863bSchristos double val;
165604ac863bSchristos int scaled; // non-zero if val should be multiplied by scale
165704ac863bSchristos } defaults_table[] = {
165804ac863bSchristos { "arcrad", .25, 1 },
165904ac863bSchristos { "arrowht", .1, 1 },
166004ac863bSchristos { "arrowwid", .05, 1 },
166104ac863bSchristos { "circlerad", .25, 1 },
166204ac863bSchristos { "boxht", .5, 1 },
166304ac863bSchristos { "boxwid", .75, 1 },
166404ac863bSchristos { "boxrad", 0.0, 1 },
166504ac863bSchristos { "dashwid", .05, 1 },
166604ac863bSchristos { "ellipseht", .5, 1 },
166704ac863bSchristos { "ellipsewid", .75, 1 },
166804ac863bSchristos { "moveht", .5, 1 },
166904ac863bSchristos { "movewid", .5, 1 },
167004ac863bSchristos { "lineht", .5, 1 },
167104ac863bSchristos { "linewid", .5, 1 },
167204ac863bSchristos { "textht", 0.0, 1 },
167304ac863bSchristos { "textwid", 0.0, 1 },
167404ac863bSchristos { "scale", 1.0, 0 },
167504ac863bSchristos { "linethick", -1.0, 0 }, // in points
167604ac863bSchristos { "fillval", .5, 0 },
167704ac863bSchristos { "arrowhead", 1.0, 0 },
167804ac863bSchristos { "maxpswid", 8.5, 0 },
167904ac863bSchristos { "maxpsht", 11.0, 0 },
168004ac863bSchristos };
168104ac863bSchristos
lookup_label(const char * label)168204ac863bSchristos place *lookup_label(const char *label)
168304ac863bSchristos {
168404ac863bSchristos saved_state *state = current_saved_state;
168504ac863bSchristos PTABLE(place) *tbl = current_table;
168604ac863bSchristos for (;;) {
168704ac863bSchristos place *pl = tbl->lookup(label);
168804ac863bSchristos if (pl)
168904ac863bSchristos return pl;
169004ac863bSchristos if (!state)
169104ac863bSchristos return 0;
169204ac863bSchristos tbl = state->tbl;
169304ac863bSchristos state = state->prev;
169404ac863bSchristos }
169504ac863bSchristos }
169604ac863bSchristos
define_label(const char * label,const place * pl)169704ac863bSchristos void define_label(const char *label, const place *pl)
169804ac863bSchristos {
169904ac863bSchristos place *p = new place[1];
170004ac863bSchristos *p = *pl;
170104ac863bSchristos current_table->define(label, p);
170204ac863bSchristos }
170304ac863bSchristos
lookup_variable(const char * name,double * val)170404ac863bSchristos int lookup_variable(const char *name, double *val)
170504ac863bSchristos {
170604ac863bSchristos place *pl = lookup_label(name);
170704ac863bSchristos if (pl) {
170804ac863bSchristos *val = pl->x;
170904ac863bSchristos return 1;
171004ac863bSchristos }
171104ac863bSchristos return 0;
171204ac863bSchristos }
171304ac863bSchristos
define_variable(const char * name,double val)171404ac863bSchristos void define_variable(const char *name, double val)
171504ac863bSchristos {
171604ac863bSchristos place *p = new place[1];
171704ac863bSchristos p->obj = 0;
171804ac863bSchristos p->x = val;
171904ac863bSchristos p->y = 0.0;
172004ac863bSchristos current_table->define(name, p);
172104ac863bSchristos if (strcmp(name, "scale") == 0) {
172204ac863bSchristos // When the scale changes, reset all scaled pre-defined variables to
172304ac863bSchristos // their default values.
172404ac863bSchristos for (unsigned int i = 0;
172504ac863bSchristos i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
172604ac863bSchristos if (defaults_table[i].scaled)
172704ac863bSchristos define_variable(defaults_table[i].name, val*defaults_table[i].val);
172804ac863bSchristos }
172904ac863bSchristos }
173004ac863bSchristos
173104ac863bSchristos // called once only (not once per parse)
173204ac863bSchristos
parse_init()173304ac863bSchristos void parse_init()
173404ac863bSchristos {
173504ac863bSchristos current_direction = RIGHT_DIRECTION;
173604ac863bSchristos current_position.x = 0.0;
173704ac863bSchristos current_position.y = 0.0;
173804ac863bSchristos // This resets everything to its default value.
173904ac863bSchristos reset_all();
174004ac863bSchristos }
174104ac863bSchristos
reset(const char * nm)174204ac863bSchristos void reset(const char *nm)
174304ac863bSchristos {
174404ac863bSchristos for (unsigned int i = 0;
174504ac863bSchristos i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
174604ac863bSchristos if (strcmp(nm, defaults_table[i].name) == 0) {
174704ac863bSchristos double val = defaults_table[i].val;
174804ac863bSchristos if (defaults_table[i].scaled) {
174904ac863bSchristos double scale;
175004ac863bSchristos lookup_variable("scale", &scale);
175104ac863bSchristos val *= scale;
175204ac863bSchristos }
175304ac863bSchristos define_variable(defaults_table[i].name, val);
175404ac863bSchristos return;
175504ac863bSchristos }
175604ac863bSchristos lex_error("`%1' is not a predefined variable", nm);
175704ac863bSchristos }
175804ac863bSchristos
reset_all()175904ac863bSchristos void reset_all()
176004ac863bSchristos {
176104ac863bSchristos // We only have to explicitly reset the pre-defined variables that
176204ac863bSchristos // aren't scaled because `scale' is not scaled, and changing the
176304ac863bSchristos // value of `scale' will reset all the pre-defined variables that
176404ac863bSchristos // are scaled.
176504ac863bSchristos for (unsigned int i = 0;
176604ac863bSchristos i < sizeof(defaults_table)/sizeof(defaults_table[0]); i++)
176704ac863bSchristos if (!defaults_table[i].scaled)
176804ac863bSchristos define_variable(defaults_table[i].name, defaults_table[i].val);
176904ac863bSchristos }
177004ac863bSchristos
177104ac863bSchristos // called after each parse
177204ac863bSchristos
parse_cleanup()177304ac863bSchristos void parse_cleanup()
177404ac863bSchristos {
177504ac863bSchristos while (current_saved_state != 0) {
177604ac863bSchristos delete current_table;
177704ac863bSchristos current_table = current_saved_state->tbl;
177804ac863bSchristos saved_state *tem = current_saved_state;
177904ac863bSchristos current_saved_state = current_saved_state->prev;
178004ac863bSchristos delete tem;
178104ac863bSchristos }
178204ac863bSchristos assert(current_table == &top_table);
178304ac863bSchristos PTABLE_ITERATOR(place) iter(current_table);
178404ac863bSchristos const char *key;
178504ac863bSchristos place *pl;
178604ac863bSchristos while (iter.next(&key, &pl))
178704ac863bSchristos if (pl->obj != 0) {
178804ac863bSchristos position pos = pl->obj->origin();
178904ac863bSchristos pl->obj = 0;
179004ac863bSchristos pl->x = pos.x;
179104ac863bSchristos pl->y = pos.y;
179204ac863bSchristos }
179304ac863bSchristos while (olist.head != 0) {
179404ac863bSchristos object *tem = olist.head;
179504ac863bSchristos olist.head = olist.head->next;
179604ac863bSchristos delete tem;
179704ac863bSchristos }
179804ac863bSchristos olist.tail = 0;
179904ac863bSchristos current_direction = RIGHT_DIRECTION;
180004ac863bSchristos current_position.x = 0.0;
180104ac863bSchristos current_position.y = 0.0;
180204ac863bSchristos }
180304ac863bSchristos
ordinal_postfix(int n)180404ac863bSchristos const char *ordinal_postfix(int n)
180504ac863bSchristos {
180604ac863bSchristos if (n < 10 || n > 20)
180704ac863bSchristos switch (n % 10) {
180804ac863bSchristos case 1:
180904ac863bSchristos return "st";
181004ac863bSchristos case 2:
181104ac863bSchristos return "nd";
181204ac863bSchristos case 3:
181304ac863bSchristos return "rd";
181404ac863bSchristos }
181504ac863bSchristos return "th";
181604ac863bSchristos }
181704ac863bSchristos
object_type_name(object_type type)181804ac863bSchristos const char *object_type_name(object_type type)
181904ac863bSchristos {
182004ac863bSchristos switch (type) {
182104ac863bSchristos case BOX_OBJECT:
182204ac863bSchristos return "box";
182304ac863bSchristos case CIRCLE_OBJECT:
182404ac863bSchristos return "circle";
182504ac863bSchristos case ELLIPSE_OBJECT:
182604ac863bSchristos return "ellipse";
182704ac863bSchristos case ARC_OBJECT:
182804ac863bSchristos return "arc";
182904ac863bSchristos case SPLINE_OBJECT:
183004ac863bSchristos return "spline";
183104ac863bSchristos case LINE_OBJECT:
183204ac863bSchristos return "line";
183304ac863bSchristos case ARROW_OBJECT:
183404ac863bSchristos return "arrow";
183504ac863bSchristos case MOVE_OBJECT:
183604ac863bSchristos return "move";
183704ac863bSchristos case TEXT_OBJECT:
183804ac863bSchristos return "\"\"";
183904ac863bSchristos case BLOCK_OBJECT:
184004ac863bSchristos return "[]";
184104ac863bSchristos case OTHER_OBJECT:
184204ac863bSchristos case MARK_OBJECT:
184304ac863bSchristos default:
184404ac863bSchristos break;
184504ac863bSchristos }
184604ac863bSchristos return "object";
184704ac863bSchristos }
184804ac863bSchristos
184904ac863bSchristos static char sprintf_buf[1024];
185004ac863bSchristos
format_number(const char * form,double n)185104ac863bSchristos char *format_number(const char *form, double n)
185204ac863bSchristos {
185304ac863bSchristos if (form == 0)
185404ac863bSchristos form = "%g";
185504ac863bSchristos return do_sprintf(form, &n, 1);
185604ac863bSchristos }
185704ac863bSchristos
do_sprintf(const char * form,const double * v,int nv)185804ac863bSchristos char *do_sprintf(const char *form, const double *v, int nv)
185904ac863bSchristos {
186004ac863bSchristos string result;
186104ac863bSchristos int i = 0;
186204ac863bSchristos string one_format;
186304ac863bSchristos while (*form) {
186404ac863bSchristos if (*form == '%') {
186504ac863bSchristos one_format += *form++;
186604ac863bSchristos for (; *form != '\0' && strchr("#-+ 0123456789.", *form) != 0; form++)
186704ac863bSchristos one_format += *form;
186804ac863bSchristos if (*form == '\0' || strchr("eEfgG%", *form) == 0) {
186904ac863bSchristos lex_error("bad sprintf format");
187004ac863bSchristos result += one_format;
187104ac863bSchristos result += form;
187204ac863bSchristos break;
187304ac863bSchristos }
187404ac863bSchristos if (*form == '%') {
187504ac863bSchristos one_format += *form++;
187604ac863bSchristos one_format += '\0';
187704ac863bSchristos snprintf(sprintf_buf, sizeof(sprintf_buf),
187804ac863bSchristos "%s", one_format.contents());
187904ac863bSchristos }
188004ac863bSchristos else {
188104ac863bSchristos if (i >= nv) {
188204ac863bSchristos lex_error("too few arguments to snprintf");
188304ac863bSchristos result += one_format;
188404ac863bSchristos result += form;
188504ac863bSchristos break;
188604ac863bSchristos }
188704ac863bSchristos one_format += *form++;
188804ac863bSchristos one_format += '\0';
188904ac863bSchristos snprintf(sprintf_buf, sizeof(sprintf_buf),
189004ac863bSchristos one_format.contents(), v[i++]);
189104ac863bSchristos }
189204ac863bSchristos one_format.clear();
189304ac863bSchristos result += sprintf_buf;
189404ac863bSchristos }
189504ac863bSchristos else
189604ac863bSchristos result += *form++;
189704ac863bSchristos }
189804ac863bSchristos result += '\0';
189904ac863bSchristos return strsave(result.contents());
190004ac863bSchristos }
1901