diff options
author | Paul Traina <pst@FreeBSD.org> | 1996-09-07 16:18:32 +0000 |
---|---|---|
committer | Paul Traina <pst@FreeBSD.org> | 1996-09-07 16:18:32 +0000 |
commit | 4e5867aa82604bc07408d50845eff8fa467f671b (patch) | |
tree | 0abcbad9804fcf7a7157983937cadcf61449b840 /contrib/groff/pic |
Virgin import of FSF groff v1.10
Notes
Notes:
svn path=/vendor/groff/dist/; revision=18099
Diffstat (limited to 'contrib/groff/pic')
-rw-r--r-- | contrib/groff/pic/Makefile.dep | 24 | ||||
-rw-r--r-- | contrib/groff/pic/Makefile.sub | 11 | ||||
-rw-r--r-- | contrib/groff/pic/TODO | 37 | ||||
-rw-r--r-- | contrib/groff/pic/common.cc | 497 | ||||
-rw-r--r-- | contrib/groff/pic/common.h | 70 | ||||
-rw-r--r-- | contrib/groff/pic/depend | 21 | ||||
-rw-r--r-- | contrib/groff/pic/lex.cc | 1939 | ||||
-rw-r--r-- | contrib/groff/pic/main.cc | 621 | ||||
-rw-r--r-- | contrib/groff/pic/object.cc | 1833 | ||||
-rw-r--r-- | contrib/groff/pic/object.h | 217 | ||||
-rw-r--r-- | contrib/groff/pic/output.h | 79 | ||||
-rw-r--r-- | contrib/groff/pic/pic.cc | 5283 | ||||
-rw-r--r-- | contrib/groff/pic/pic.h | 102 | ||||
-rw-r--r-- | contrib/groff/pic/pic.man | 753 | ||||
-rw-r--r-- | contrib/groff/pic/pic.tab.h | 129 | ||||
-rw-r--r-- | contrib/groff/pic/pic.y | 1795 | ||||
-rw-r--r-- | contrib/groff/pic/position.h | 47 | ||||
-rw-r--r-- | contrib/groff/pic/tex.cc | 411 | ||||
-rw-r--r-- | contrib/groff/pic/text.h | 28 | ||||
-rw-r--r-- | contrib/groff/pic/troff.cc | 500 |
20 files changed, 14397 insertions, 0 deletions
diff --git a/contrib/groff/pic/Makefile.dep b/contrib/groff/pic/Makefile.dep new file mode 100644 index 000000000000..1e07874890b7 --- /dev/null +++ b/contrib/groff/pic/Makefile.dep @@ -0,0 +1,24 @@ +lex.o: lex.cc pic.h ../include/assert.h ../include/cset.h \ + ../include/lib.h ../include/stringclass.h ../include/errarg.h \ + ../include/error.h position.h text.h output.h ../include/ptable.h \ + object.h pic.cc +main.o: main.cc pic.h ../include/assert.h ../include/cset.h \ + ../include/lib.h ../include/stringclass.h ../include/errarg.h \ + ../include/error.h position.h text.h output.h +object.o: object.cc pic.h ../include/assert.h ../include/cset.h \ + ../include/lib.h ../include/stringclass.h ../include/errarg.h \ + ../include/error.h position.h text.h output.h ../include/ptable.h \ + object.h +common.o: common.cc pic.h ../include/assert.h ../include/cset.h \ + ../include/lib.h ../include/stringclass.h ../include/errarg.h \ + ../include/error.h position.h text.h output.h common.h +troff.o: troff.cc pic.h ../include/assert.h ../include/cset.h \ + ../include/lib.h ../include/stringclass.h ../include/errarg.h \ + ../include/error.h position.h text.h output.h common.h +tex.o: tex.cc pic.h ../include/assert.h ../include/cset.h \ + ../include/lib.h ../include/stringclass.h ../include/errarg.h \ + ../include/error.h position.h text.h output.h common.h +pic.o: pic.cc pic.h ../include/assert.h ../include/cset.h \ + ../include/lib.h ../include/stringclass.h ../include/errarg.h \ + ../include/error.h position.h text.h output.h ../include/ptable.h \ + object.h diff --git a/contrib/groff/pic/Makefile.sub b/contrib/groff/pic/Makefile.sub new file mode 100644 index 000000000000..06d19750dff6 --- /dev/null +++ b/contrib/groff/pic/Makefile.sub @@ -0,0 +1,11 @@ +PROG=pic +MAN1=pic.n +XLIBS=$(LIBGROFF) +MLIB=$(LIBM) +OBJS=pic.o lex.o main.o object.o common.o troff.o tex.o # fig.o +CCSRCS=lex.cc main.cc object.cc common.cc troff.cc tex.cc +HDRS=common.h object.h output.h pic.h position.h text.h +GRAM=pic.y +YTABC=pic.cc +YTABH=pic.tab.h +NAMEPREFIX=$(g) diff --git a/contrib/groff/pic/TODO b/contrib/groff/pic/TODO new file mode 100644 index 000000000000..2346b575e1de --- /dev/null +++ b/contrib/groff/pic/TODO @@ -0,0 +1,37 @@ +Dotted and dashed ellipses. + +In troff mode, dotted and dashed splines. + +Make DELIMITED have type lstr; this would allow us to give better +error messages for problems within the body of for and if constructs. + +In troff mode without -x, fake \D't' with .ps commands. + +Perhaps an option to set command char. + +Add an output class for dumb line printers. It wouldn't be pretty but +it would be better than nothing. Integrate it with texinfo. Useful +for groff -Tascii as well. + +Option to allow better positioning of arrowheads on arcs. + +Perhaps add PostScript output mode. + +Change the interface to the output class so that output devices have +the opportunity to handle arrowheads themselves. + +Consider whether the line thickness should scale. + +Consider whether the test in a for loop should be fuzzy (as it +apparently is in grap). + +Possibly change fillval so that zero is black. + +Provide a way of getting text blocks (positioned with `.in' rather +than \h), into pic. Should be possible to use block of diverted text +in pic. Possibly something similar to T{ and T} in tbl. + +Option to provide macro backtraces. + +Have a path that is searched by `copy' statement. Set by environment +variable or command line option. diff --git a/contrib/groff/pic/common.cc b/contrib/groff/pic/common.cc new file mode 100644 index 000000000000..e83ef3122583 --- /dev/null +++ b/contrib/groff/pic/common.cc @@ -0,0 +1,497 @@ +// -*- C++ -*- +/* 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 "common.h" + +// output a dashed circle as a series of arcs + +void common_output::dashed_circle(const position ¢, double rad, + const line_type <) +{ + assert(lt.type == line_type::dashed); + line_type slt = lt; + slt.type = line_type::solid; + double dash_angle = lt.dash_width/rad; + int ndashes; + double gap_angle; + if (dash_angle >= M_PI/4.0) { + if (dash_angle < M_PI/2.0) { + gap_angle = M_PI/2.0 - dash_angle; + ndashes = 4; + } + else if (dash_angle < M_PI) { + gap_angle = M_PI - dash_angle; + ndashes = 2; + } + else { + circle(cent, rad, slt, -1.0); + return; + } + } + else { + ndashes = 4*int(ceil(M_PI/(4.0*dash_angle))); + gap_angle = (M_PI*2.0)/ndashes - dash_angle; + } + for (int i = 0; i < ndashes; i++) { + double start_angle = i*(dash_angle+gap_angle) - dash_angle/2.0; + solid_arc(cent, rad, start_angle, start_angle + dash_angle, lt); + } +} + +// output a dotted circle as a series of dots + +void common_output::dotted_circle(const position ¢, double rad, + const line_type <) +{ + assert(lt.type == line_type::dotted); + double gap_angle = lt.dash_width/rad; + int ndots; + if (gap_angle >= M_PI/2.0) { + // always have at least 2 dots + gap_angle = M_PI; + ndots = 2; + } + else { + ndots = 4*int(M_PI/(2.0*gap_angle)); + gap_angle = (M_PI*2.0)/ndots; + } + double ang = 0.0; + for (int i = 0; i < ndots; i++, ang += gap_angle) + dot(cent + position(cos(ang), sin(ang))*rad, lt); +} + +// return non-zero iff we can compute a center + +int compute_arc_center(const position &start, const position ¢, + const position &end, position *result) +{ + // This finds the point along the vector from start to cent that + // is equidistant between start and end. + distance c = cent - start; + distance e = end - start; + double n = c*e; + if (n == 0.0) + return 0; + *result = start + c*((e*e)/(2.0*n)); + return 1; +} + +// output a dashed arc as a series of arcs + +void common_output::dashed_arc(const position &start, const position ¢, + const position &end, const line_type <) +{ + assert(lt.type == line_type::dashed); + position c; + if (!compute_arc_center(start, cent, end, &c)) { + line(start, &end, 1, lt); + return; + } + distance start_offset = start - c; + distance end_offset = end - c; + double start_angle = atan2(start_offset.y, start_offset.x); + double end_angle = atan2(end_offset.y, end_offset.x); + double rad = hypot(c - start); + double dash_angle = lt.dash_width/rad; + double total_angle = end_angle - start_angle; + while (total_angle < 0) + total_angle += M_PI + M_PI; + if (total_angle <= dash_angle*2.0) { + solid_arc(cent, rad, start_angle, end_angle, lt); + return; + } + int ndashes = int((total_angle - dash_angle)/(dash_angle*2.0) + .5); + double dash_and_gap_angle = (total_angle - dash_angle)/ndashes; + for (int i = 0; i <= ndashes; i++) + solid_arc(cent, rad, start_angle + i*dash_and_gap_angle, + start_angle + i*dash_and_gap_angle + dash_angle, lt); +} + +// output a dotted arc as a series of dots + +void common_output::dotted_arc(const position &start, const position ¢, + const position &end, const line_type <) +{ + assert(lt.type == line_type::dotted); + position c; + if (!compute_arc_center(start, cent, end, &c)) { + line(start, &end, 1, lt); + return; + } + distance start_offset = start - c; + distance end_offset = end - c; + double start_angle = atan2(start_offset.y, start_offset.x); + double total_angle = atan2(end_offset.y, end_offset.x) - start_angle; + while (total_angle < 0) + total_angle += M_PI + M_PI; + double rad = hypot(c - start); + int ndots = int(total_angle/(lt.dash_width/rad) + .5); + if (ndots == 0) + dot(start, lt); + else { + for (int i = 0; i <= ndots; i++) { + double a = start_angle + (total_angle*i)/ndots; + dot(cent + position(cos(a), sin(a))*rad, lt); + } + } +} + +void common_output::solid_arc(const position ¢, double rad, + double start_angle, double end_angle, + const line_type <) +{ + line_type slt = lt; + slt.type = line_type::solid; + arc(cent + position(cos(start_angle), sin(start_angle))*rad, + cent, + cent + position(cos(end_angle), sin(end_angle))*rad, + slt); +} + + +void common_output::rounded_box(const position ¢, const distance &dim, + double rad, const line_type <, double fill) +{ + if (fill >= 0.0) + filled_rounded_box(cent, dim, rad, fill); + switch (lt.type) { + case line_type::invisible: + break; + case line_type::dashed: + dashed_rounded_box(cent, dim, rad, lt); + break; + case line_type::dotted: + dotted_rounded_box(cent, dim, rad, lt); + break; + case line_type::solid: + solid_rounded_box(cent, dim, rad, lt); + break; + default: + assert(0); + } +} + + +void common_output::dashed_rounded_box(const position ¢, + const distance &dim, double rad, + const line_type <) +{ + line_type slt = lt; + slt.type = line_type::solid; + + double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad; + int n_hor_dashes = int(hor_length/(lt.dash_width*2.0) + .5); + double hor_gap_width = (n_hor_dashes != 0 + ? hor_length/n_hor_dashes - lt.dash_width + : 0.0); + + double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad; + int n_vert_dashes = int(vert_length/(lt.dash_width*2.0) + .5); + double vert_gap_width = (n_vert_dashes != 0 + ? vert_length/n_vert_dashes - lt.dash_width + : 0.0); + // Note that each corner arc has to be split into two for dashing, + // because one part is dashed using vert_gap_width, and the other + // using hor_gap_width. + double offset = lt.dash_width/2.0; + dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, + -M_PI/4.0, 0, slt, lt.dash_width, vert_gap_width, &offset); + dash_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad), + cent + position(dim.x/2.0, dim.y/2.0 - rad), + slt, lt.dash_width, vert_gap_width, &offset); + dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, + 0, M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset); + + offset = lt.dash_width/2.0; + dash_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, + M_PI/4.0, M_PI/2, slt, lt.dash_width, hor_gap_width, &offset); + dash_line(cent + position(dim.x/2.0 - rad, dim.y/2.0), + cent + position(-dim.x/2.0 + rad, dim.y/2.0), + slt, lt.dash_width, hor_gap_width, &offset); + dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, + M_PI/2, 3*M_PI/4.0, slt, lt.dash_width, hor_gap_width, &offset); + + offset = lt.dash_width/2.0; + dash_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, + 3.0*M_PI/4.0, M_PI, slt, lt.dash_width, vert_gap_width, &offset); + dash_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad), + cent + position(-dim.x/2.0, -dim.y/2.0 + rad), + slt, lt.dash_width, vert_gap_width, &offset); + dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, + M_PI, 5.0*M_PI/4.0, slt, lt.dash_width, vert_gap_width, &offset); + + offset = lt.dash_width/2.0; + dash_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, + 5*M_PI/4.0, 3*M_PI/2.0, slt, lt.dash_width, hor_gap_width, &offset); + dash_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0), + cent + position(dim.x/2.0 - rad, -dim.y/2.0), + slt, lt.dash_width, hor_gap_width, &offset); + dash_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, + 3*M_PI/2, 7*M_PI/4, slt, lt.dash_width, hor_gap_width, &offset); +} + +// Used by dashed_rounded_box. + +void common_output::dash_arc(const position ¢, double rad, + double start_angle, double end_angle, + const line_type <, + double dash_width, double gap_width, + double *offsetp) +{ + double length = (end_angle - start_angle)*rad; + double pos = 0.0; + for (;;) { + if (*offsetp >= dash_width) { + double rem = dash_width + gap_width - *offsetp; + if (pos + rem > length) { + *offsetp += length - pos; + break; + } + else { + pos += rem; + *offsetp = 0.0; + } + } + else { + double rem = dash_width - *offsetp; + if (pos + rem > length) { + solid_arc(cent, rad, start_angle + pos/rad, end_angle, lt); + *offsetp += length - pos; + break; + } + else { + solid_arc(cent, rad, start_angle + pos/rad, + start_angle + (pos + rem)/rad, lt); + pos += rem; + *offsetp = dash_width; + } + } + } +} + +// Used by dashed_rounded_box. + +void common_output::dash_line(const position &start, const position &end, + const line_type <, + double dash_width, double gap_width, + double *offsetp) +{ + distance dist = end - start; + double length = hypot(dist); + if (length == 0.0) + return; + double pos = 0.0; + for (;;) { + if (*offsetp >= dash_width) { + double rem = dash_width + gap_width - *offsetp; + if (pos + rem > length) { + *offsetp += length - pos; + break; + } + else { + pos += rem; + *offsetp = 0.0; + } + } + else { + double rem = dash_width - *offsetp; + if (pos + rem > length) { + line(start + dist*(pos/length), &end, 1, lt); + *offsetp += length - pos; + break; + } + else { + position p(start + dist*((pos + rem)/length)); + line(start + dist*(pos/length), &p, 1, lt); + pos += rem; + *offsetp = dash_width; + } + } + } +} + +void common_output::dotted_rounded_box(const position ¢, + const distance &dim, double rad, + const line_type <) +{ + line_type slt = lt; + slt.type = line_type::solid; + + double hor_length = dim.x + (M_PI/2.0 - 2.0)*rad; + int n_hor_dots = int(hor_length/lt.dash_width + .5); + double hor_gap_width = (n_hor_dots != 0 + ? hor_length/n_hor_dots + : lt.dash_width); + + double vert_length = dim.y + (M_PI/2.0 - 2.0)*rad; + int n_vert_dots = int(vert_length/lt.dash_width + .5); + double vert_gap_width = (n_vert_dots != 0 + ? vert_length/n_vert_dots + : lt.dash_width); + double epsilon = lt.dash_width/(rad*100.0); + + double offset = 0.0; + dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, + -M_PI/4.0, 0, slt, vert_gap_width, &offset); + dot_line(cent + position(dim.x/2.0, -dim.y/2.0 + rad), + cent + position(dim.x/2.0, dim.y/2.0 - rad), + slt, vert_gap_width, &offset); + dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, + 0, M_PI/4.0 - epsilon, slt, vert_gap_width, &offset); + + offset = 0.0; + dot_arc(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, + M_PI/4.0, M_PI/2, slt, hor_gap_width, &offset); + dot_line(cent + position(dim.x/2.0 - rad, dim.y/2.0), + cent + position(-dim.x/2.0 + rad, dim.y/2.0), + slt, hor_gap_width, &offset); + dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, + M_PI/2, 3*M_PI/4.0 - epsilon, slt, hor_gap_width, &offset); + + offset = 0.0; + dot_arc(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, + 3.0*M_PI/4.0, M_PI, slt, vert_gap_width, &offset); + dot_line(cent + position(-dim.x/2.0, dim.y/2.0 - rad), + cent + position(-dim.x/2.0, -dim.y/2.0 + rad), + slt, vert_gap_width, &offset); + dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, + M_PI, 5.0*M_PI/4.0 - epsilon, slt, vert_gap_width, &offset); + + offset = 0.0; + dot_arc(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, + 5*M_PI/4.0, 3*M_PI/2.0, slt, hor_gap_width, &offset); + dot_line(cent + position(-dim.x/2.0 + rad, -dim.y/2.0), + cent + position(dim.x/2.0 - rad, -dim.y/2.0), + slt, hor_gap_width, &offset); + dot_arc(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, + 3*M_PI/2, 7*M_PI/4 - epsilon, slt, hor_gap_width, &offset); +} + +// Used by dotted_rounded_box. + +void common_output::dot_arc(const position ¢, double rad, + double start_angle, double end_angle, + const line_type <, double gap_width, + double *offsetp) +{ + double length = (end_angle - start_angle)*rad; + double pos = 0.0; + for (;;) { + if (*offsetp == 0.0) { + double ang = start_angle + pos/rad; + dot(cent + position(cos(ang), sin(ang))*rad, lt); + } + double rem = gap_width - *offsetp; + if (pos + rem > length) { + *offsetp += length - pos; + break; + } + else { + pos += rem; + *offsetp = 0.0; + } + } +} + +// Used by dotted_rounded_box. + +void common_output::dot_line(const position &start, const position &end, + const line_type <, double gap_width, + double *offsetp) +{ + distance dist = end - start; + double length = hypot(dist); + if (length == 0.0) + return; + double pos = 0.0; + for (;;) { + if (*offsetp == 0.0) + dot(start + dist*(pos/length), lt); + double rem = gap_width - *offsetp; + if (pos + rem > length) { + *offsetp += length - pos; + break; + } + else { + pos += rem; + *offsetp = 0.0; + } + } +} + + +void common_output::solid_rounded_box(const position ¢, + const distance &dim, double rad, + const line_type <) +{ + position tem = cent - dim/2.0; + arc(tem + position(0.0, rad), + tem + position(rad, rad), + tem + position(rad, 0.0), + lt); + tem = cent + position(-dim.x/2.0, dim.y/2.0); + arc(tem + position(rad, 0.0), + tem + position(rad, -rad), + tem + position(0.0, -rad), + lt); + tem = cent + dim/2.0; + arc(tem + position(0.0, -rad), + tem + position(-rad, -rad), + tem + position(-rad, 0.0), + lt); + tem = cent + position(dim.x/2.0, -dim.y/2.0); + arc(tem + position(-rad, 0.0), + tem + position(-rad, rad), + tem + position(0.0, rad), + lt); + position end; + end = cent + position(-dim.x/2.0, dim.y/2.0 - rad); + line(cent - dim/2.0 + position(0.0, rad), &end, 1, lt); + end = cent + position(dim.x/2.0 - rad, dim.y/2.0); + line(cent + position(-dim.x/2.0 + rad, dim.y/2.0), &end, 1, lt); + end = cent + position(dim.x/2.0, -dim.y/2.0 + rad); + line(cent + position(dim.x/2.0, dim.y/2.0 - rad), &end, 1, lt); + end = cent + position(-dim.x/2.0 + rad, -dim.y/2.0); + line(cent + position(dim.x/2.0 - rad, -dim.y/2.0), &end, 1, lt); +} + +void common_output::filled_rounded_box(const position ¢, + const distance &dim, double rad, + double fill) +{ + line_type ilt; + ilt.type = line_type::invisible; + circle(cent + position(dim.x/2.0 - rad, dim.y/2.0 - rad), rad, ilt, fill); + circle(cent + position(-dim.x/2.0 + rad, dim.y/2.0 - rad), rad, ilt, fill); + circle(cent + position(-dim.x/2.0 + rad, -dim.y/2.0 + rad), rad, ilt, fill); + circle(cent + position(dim.x/2.0 - rad, -dim.y/2.0 + rad), rad, ilt, fill); + position vec[4]; + vec[0] = cent + position(dim.x/2.0, dim.y/2.0 - rad); + vec[1] = cent + position(-dim.x/2.0, dim.y/2.0 - rad); + vec[2] = cent + position(-dim.x/2.0, -dim.y/2.0 + rad); + vec[3] = cent + position(dim.x/2.0, -dim.y/2.0 + rad); + polygon(vec, 4, ilt, fill); + vec[0] = cent + position(dim.x/2.0 - rad, dim.y/2.0); + vec[1] = cent + position(-dim.x/2.0 + rad, dim.y/2.0); + vec[2] = cent + position(-dim.x/2.0 + rad, -dim.y/2.0); + vec[3] = cent + position(dim.x/2.0 - rad, -dim.y/2.0); + polygon(vec, 4, ilt, fill); +} diff --git a/contrib/groff/pic/common.h b/contrib/groff/pic/common.h new file mode 100644 index 000000000000..25a6e10c689c --- /dev/null +++ b/contrib/groff/pic/common.h @@ -0,0 +1,70 @@ +// -*- C++ -*- +/* 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. */ + +class common_output : public output { +private: + void dash_line(const position &start, const position &end, + const line_type <, double dash_width, double gap_width, + double *offsetp); + void dash_arc(const position ¢, double rad, + double start_angle, double end_angle, const line_type <, + double dash_width, double gap_width, double *offsetp); + void dot_line(const position &start, const position &end, + const line_type <, double gap_width, double *offsetp); + void dot_arc(const position ¢, double rad, + double start_angle, double end_angle, const line_type <, + double gap_width, double *offsetp); +protected: + virtual void dot(const position &, const line_type &) = 0; + void dashed_circle(const position &, double rad, const line_type &); + void dotted_circle(const position &, double rad, const line_type &); + void dashed_arc(const position &, const position &, const position &, + const line_type &); + void dotted_arc(const position &, const position &, const position &, + const line_type &); + virtual void solid_arc(const position ¢, double rad, double start_angle, + double end_angle, const line_type <); + void dashed_rounded_box(const position &, const distance &, double, + const line_type &); + void dotted_rounded_box(const position &, const distance &, double, + const line_type &); + void solid_rounded_box(const position &, const distance &, double, + const line_type &); + void filled_rounded_box(const position &, const distance &, double, double); +public: + void start_picture(double sc, const position &ll, const position &ur) = 0; + void finish_picture() = 0; + void circle(const position &, double rad, const line_type &, double) = 0; + void text(const position &, text_piece *, int, double) = 0; + void line(const position &, const position *, int n, const line_type &) = 0; + void polygon(const position *, int n, const line_type &, double) = 0; + void spline(const position &, const position *, int n, + const line_type &) = 0; + void arc(const position &, const position &, const position &, + const line_type &) = 0; + void ellipse(const position &, const distance &, + const line_type &, double) = 0; + void rounded_box(const position &, const distance &, double, + const line_type &, double); +}; + +int compute_arc_center(const position &start, const position ¢, + const position &end, position *result); + diff --git a/contrib/groff/pic/depend b/contrib/groff/pic/depend new file mode 100644 index 000000000000..73ac3ab9093c --- /dev/null +++ b/contrib/groff/pic/depend @@ -0,0 +1,21 @@ +pic.tab.o : pic.tab.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \ + ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \ + output.h ../lib/ptable.h object.h +lex.o : lex.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \ + ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \ + output.h ../lib/ptable.h object.h pic.tab.h +main.o : main.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \ + ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \ + output.h +object.o : object.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \ + ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \ + output.h ../lib/ptable.h object.h +common.o : common.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \ + ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \ + output.h common.h +troff.o : troff.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \ + ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \ + output.h common.h +tex.o : tex.cc pic.h ../lib/assert.h ../lib/cset.h ../lib/lib.h \ + ../lib/stringclass.h ../lib/errarg.h ../lib/error.h position.h text.h \ + output.h common.h diff --git a/contrib/groff/pic/lex.cc b/contrib/groff/pic/lex.cc new file mode 100644 index 000000000000..920938d538e1 --- /dev/null +++ b/contrib/groff/pic/lex.cc @@ -0,0 +1,1939 @@ +// -*- C++ -*- +/* 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" +#include "pic.tab.h" + +declare_ptable(char) +implement_ptable(char) + +PTABLE(char) macro_table; + +class macro_input : public input { + char *s; + char *p; +public: + macro_input(const char *); + ~macro_input(); + int get(); + int peek(); +}; + +class argument_macro_input : public input { + char *s; + char *p; + char *ap; + int argc; + char *argv[9]; +public: + argument_macro_input(const char *, int, char **); + ~argument_macro_input(); + int get(); + int peek(); +}; + +input::input() : next(0) +{ +} + +input::~input() +{ +} + +int input::get_location(const char **, int *) +{ + return 0; +} + +file_input::file_input(FILE *f, const char *fn) +: lineno(0), ptr(""), filename(fn) +{ + fp = f; +} + +file_input::~file_input() +{ + fclose(fp); +} + +int file_input::read_line() +{ + for (;;) { + line.clear(); + lineno++; + for (;;) { + int c = getc(fp); + if (c == EOF) + break; + else if (illegal_input_char(c)) + lex_error("illegal input character code %1", c); + else { + line += char(c); + if (c == '\n') + break; + } + } + if (line.length() == 0) + return 0; + if (!(line.length() >= 3 && line[0] == '.' && line[1] == 'P' + && (line[2] == 'S' || line[2] == 'E' || line[2] == 'F') + && (line.length() == 3 || line[3] == ' ' || line[3] == '\n' + || compatible_flag))) { + line += '\0'; + ptr = line.contents(); + return 1; + } + } +} + +int file_input::get() +{ + if (*ptr != '\0' || read_line()) + return (unsigned char)*ptr++; + else + return EOF; +} + +int file_input::peek() +{ + if (*ptr != '\0' || read_line()) + return (unsigned char)*ptr; + else + return EOF; +} + +int file_input::get_location(const char **fnp, int *lnp) +{ + *fnp = filename; + *lnp = lineno; + return 1; +} + +macro_input::macro_input(const char *str) +{ + p = s = strsave(str); +} + +macro_input::~macro_input() +{ + a_delete s; +} + +int macro_input::get() +{ + if (p == 0 || *p == '\0') + return EOF; + else + return (unsigned char)*p++; +} + +int macro_input::peek() +{ + if (p == 0 || *p == '\0') + return EOF; + else + return (unsigned char)*p; +} + +// Character representing $1. Must be illegal input character. +#define ARG1 14 + +char *process_body(const char *body) +{ + char *s = strsave(body); + int j = 0; + for (int i = 0; s[i] != '\0'; i++) + if (s[i] == '$' && s[i+1] >= '0' && s[i+1] <= '9') { + if (s[i+1] != '0') + s[j++] = ARG1 + s[++i] - '1'; + } + else + s[j++] = s[i]; + s[j] = '\0'; + return s; +} + + +argument_macro_input::argument_macro_input(const char *body, int ac, char **av) +: argc(ac), ap(0) +{ + for (int i = 0; i < argc; i++) + argv[i] = av[i]; + p = s = process_body(body); +} + + +argument_macro_input::~argument_macro_input() +{ + for (int i = 0; i < argc; i++) + a_delete argv[i]; + a_delete s; +} + +int argument_macro_input::get() +{ + if (ap) { + if (*ap != '\0') + return (unsigned char)*ap++; + ap = 0; + } + if (p == 0) + return EOF; + while (*p >= ARG1 && *p <= ARG1 + 8) { + int i = *p++ - ARG1; + if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { + ap = argv[i]; + return (unsigned char)*ap++; + } + } + if (*p == '\0') + return EOF; + return (unsigned char)*p++; +} + +int argument_macro_input::peek() +{ + if (ap) { + if (*ap != '\0') + return (unsigned char)*ap; + ap = 0; + } + if (p == 0) + return EOF; + while (*p >= ARG1 && *p <= ARG1 + 8) { + int i = *p++ - ARG1; + if (i < argc && argv[i] != 0 && argv[i][0] != '\0') { + ap = argv[i]; + return (unsigned char)*ap; + } + } + if (*p == '\0') + return EOF; + return (unsigned char)*p; +} + +class input_stack { + static input *current_input; + static int bol_flag; +public: + static void push(input *); + static void clear(); + static int get_char(); + static int peek_char(); + static int get_location(const char **fnp, int *lnp); + static void push_back(unsigned char c, int was_bol = 0); + static int bol(); +}; + +input *input_stack::current_input = 0; +int input_stack::bol_flag = 0; + +inline int input_stack::bol() +{ + return bol_flag; +} + +void input_stack::clear() +{ + while (current_input != 0) { + input *tem = current_input; + current_input = current_input->next; + delete tem; + } + bol_flag = 1; +} + +void input_stack::push(input *in) +{ + in->next = current_input; + current_input = in; +} + +void lex_init(input *top) +{ + input_stack::clear(); + input_stack::push(top); +} + +void lex_cleanup() +{ + while (input_stack::get_char() != EOF) + ; +} + +int input_stack::get_char() +{ + while (current_input != 0) { + int c = current_input->get(); + if (c != EOF) { + bol_flag = c == '\n'; + return c; + } + // don't pop the top-level input off the stack + if (current_input->next == 0) + return EOF; + input *tem = current_input; + current_input = current_input->next; + delete tem; + } + return EOF; +} + +int input_stack::peek_char() +{ + while (current_input != 0) { + int c = current_input->peek(); + if (c != EOF) + return c; + if (current_input->next == 0) + return EOF; + input *tem = current_input; + current_input = current_input->next; + delete tem; + } + return EOF; +} + +class char_input : public input { + int c; +public: + char_input(int); + int get(); + int peek(); +}; + +char_input::char_input(int n) : c((unsigned char)n) +{ +} + +int char_input::get() +{ + int n = c; + c = EOF; + return n; +} + +int char_input::peek() +{ + return c; +} + +void input_stack::push_back(unsigned char c, int was_bol) +{ + push(new char_input(c)); + bol_flag = was_bol; +} + +int input_stack::get_location(const char **fnp, int *lnp) +{ + for (input *p = current_input; p; p = p->next) + if (p->get_location(fnp, lnp)) + return 1; + return 0; +} + +string context_buffer; + +string token_buffer; +double token_double; +int token_int; + +void interpolate_macro_with_args(const char *body) +{ + char *argv[9]; + int argc = 0; + int i; + for (i = 0; i < 9; i++) + argv[i] = 0; + int level = 0; + int c; + enum { NORMAL, IN_STRING, IN_STRING_QUOTED } state = NORMAL; + do { + token_buffer.clear(); + for (;;) { + c = input_stack::get_char(); + if (c == EOF) { + lex_error("end of input while scanning macro arguments"); + break; + } + if (state == NORMAL && level == 0 && (c == ',' || c == ')')) { + if (token_buffer.length() > 0) { + token_buffer += '\0'; + argv[argc] = strsave(token_buffer.contents()); + } + // for `foo()', argc = 0 + if (argc > 0 || c != ')' || i > 0) + argc++; + break; + } + token_buffer += char(c); + switch (state) { + case NORMAL: + if (c == '"') + state = IN_STRING; + else if (c == '(') + level++; + else if (c == ')') + level--; + break; + case IN_STRING: + if (c == '"') + state = NORMAL; + else if (c == '\\') + state = IN_STRING_QUOTED; + break; + case IN_STRING_QUOTED: + state = IN_STRING; + break; + } + } + } while (c != ')' && c != EOF); + input_stack::push(new argument_macro_input(body, argc, argv)); +} + +static int docmp(const char *s1, int n1, const char *s2, int n2) +{ + if (n1 < n2) { + int r = memcmp(s1, s2, n1); + return r ? r : -1; + } + else if (n1 > n2) { + int r = memcmp(s1, s2, n2); + return r ? r : 1; + } + else + return memcmp(s1, s2, n1); +} + +int lookup_keyword(const char *str, int len) +{ + static struct keyword { + const char *name; + int token; + } table[] = { + { "Here", HERE }, + { "above", ABOVE }, + { "aligned", ALIGNED }, + { "and", AND }, + { "arc", ARC }, + { "arrow", ARROW }, + { "at", AT }, + { "atan2", ATAN2 }, + { "below", BELOW }, + { "between", BETWEEN }, + { "bottom", BOTTOM }, + { "box", BOX }, + { "by", BY }, + { "ccw", CCW }, + { "center", CENTER }, + { "chop", CHOP }, + { "circle", CIRCLE }, + { "command", COMMAND }, + { "copy", COPY }, + { "cos", COS }, + { "cw", CW }, + { "dashed", DASHED }, + { "define", DEFINE }, + { "diam", DIAMETER }, + { "diameter", DIAMETER }, + { "do", DO }, + { "dotted", DOTTED }, + { "down", DOWN }, + { "ellipse", ELLIPSE }, + { "else", ELSE }, + { "end", END }, + { "exp", EXP }, + { "fill", FILL }, + { "filled", FILL }, + { "for", FOR }, + { "from", FROM }, + { "height", HEIGHT }, + { "ht", HEIGHT }, + { "if", IF }, + { "int", INT }, + { "invis", INVISIBLE }, + { "invisible", INVISIBLE }, + { "last", LAST }, + { "left", LEFT }, + { "line", LINE }, + { "ljust", LJUST }, + { "log", LOG }, + { "lower", LOWER }, + { "max", K_MAX }, + { "min", K_MIN }, + { "move", MOVE }, + { "of", OF }, + { "plot", PLOT }, + { "print", PRINT }, + { "rad", RADIUS }, + { "radius", RADIUS }, + { "rand", RAND }, + { "reset", RESET }, + { "right", RIGHT }, + { "rjust", RJUST }, + { "same", SAME }, + { "sh", SH }, + { "sin", SIN }, + { "spline", SPLINE }, + { "sprintf", SPRINTF }, + { "sqrt", SQRT }, + { "start", START }, + { "the", THE }, + { "then", THEN }, + { "thick", THICKNESS }, + { "thickness", THICKNESS }, + { "thru", THRU }, + { "to", TO }, + { "top", TOP }, + { "undef", UNDEF }, + { "until", UNTIL }, + { "up", UP }, + { "upper", UPPER }, + { "way", WAY }, + { "wid", WIDTH }, + { "width", WIDTH }, + { "with", WITH }, + }; + + const keyword *start = table; + const keyword *end = table + sizeof(table)/sizeof(table[0]); + while (start < end) { + // start <= target < end + const keyword *mid = start + (end - start)/2; + + int cmp = docmp(str, len, mid->name, strlen(mid->name)); + if (cmp == 0) + return mid->token; + if (cmp < 0) + end = mid; + else + start = mid + 1; + } + return 0; +} + +int get_token_after_dot(int c) +{ + // get_token deals with the case where c is a digit + switch (c) { + case 'h': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + context_buffer = ".ht"; + return DOT_HT; + } + else if (c == 'e') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'i') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'g') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'h') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + context_buffer = ".height"; + return DOT_HT; + } + input_stack::push_back('h'); + } + input_stack::push_back('g'); + } + input_stack::push_back('i'); + } + input_stack::push_back('e'); + } + input_stack::push_back('h'); + return '.'; + case 'x': + input_stack::get_char(); + context_buffer = ".x"; + return DOT_X; + case 'y': + input_stack::get_char(); + context_buffer = ".y"; + return DOT_Y; + case 'c': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'e') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'n') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'e') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'r') { + input_stack::get_char(); + context_buffer = ".center"; + return DOT_C; + } + input_stack::push_back('e'); + } + input_stack::push_back('t'); + } + input_stack::push_back('n'); + } + input_stack::push_back('e'); + } + context_buffer = ".c"; + return DOT_C; + case 'n': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'e') { + input_stack::get_char(); + context_buffer = ".ne"; + return DOT_NE; + } + else if (c == 'w') { + input_stack::get_char(); + context_buffer = ".nw"; + return DOT_NW; + } + else { + context_buffer = ".n"; + return DOT_N; + } + break; + case 'e': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'n') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'd') { + input_stack::get_char(); + context_buffer = ".end"; + return DOT_END; + } + input_stack::push_back('n'); + context_buffer = ".e"; + return DOT_E; + } + context_buffer = ".e"; + return DOT_E; + case 'w': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'i') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'd') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'h') { + input_stack::get_char(); + context_buffer = ".width"; + return DOT_WID; + } + input_stack::push_back('t'); + } + context_buffer = ".wid"; + return DOT_WID; + } + input_stack::push_back('i'); + } + context_buffer = ".w"; + return DOT_W; + case 's': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'e') { + input_stack::get_char(); + context_buffer = ".se"; + return DOT_SE; + } + else if (c == 'w') { + input_stack::get_char(); + context_buffer = ".sw"; + return DOT_SW; + } + else { + if (c == 't') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'a') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'r') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + context_buffer = ".start"; + return DOT_START; + } + input_stack::push_back('r'); + } + input_stack::push_back('a'); + } + input_stack::push_back('t'); + } + context_buffer = ".s"; + return DOT_S; + } + break; + case 't': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'o') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'p') { + input_stack::get_char(); + context_buffer = ".top"; + return DOT_N; + } + input_stack::push_back('o'); + } + context_buffer = ".t"; + return DOT_N; + case 'l': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'e') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'f') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + context_buffer = ".left"; + return DOT_W; + } + input_stack::push_back('f'); + } + input_stack::push_back('e'); + } + context_buffer = ".l"; + return DOT_W; + case 'r': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'a') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'd') { + input_stack::get_char(); + context_buffer = ".rad"; + return DOT_RAD; + } + input_stack::push_back('a'); + } + else if (c == 'i') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'g') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'h') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + context_buffer = ".right"; + return DOT_E; + } + input_stack::push_back('h'); + } + input_stack::push_back('g'); + } + input_stack::push_back('i'); + } + context_buffer = ".r"; + return DOT_E; + case 'b': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'o') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'o') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'm') { + input_stack::get_char(); + context_buffer = ".bottom"; + return DOT_S; + } + input_stack::push_back('o'); + } + input_stack::push_back('t'); + } + context_buffer = ".bot"; + return DOT_S; + } + input_stack::push_back('o'); + } + context_buffer = ".b"; + return DOT_S; + default: + context_buffer = '.'; + return '.'; + } +} + +int get_token(int lookup_flag) +{ + context_buffer.clear(); + for (;;) { + int n = 0; + int bol = input_stack::bol(); + int c = input_stack::get_char(); + if (bol && c == command_char) { + token_buffer.clear(); + token_buffer += c; + // the newline is not part of the token + for (;;) { + c = input_stack::peek_char(); + if (c == EOF || c == '\n') + break; + input_stack::get_char(); + token_buffer += char(c); + } + context_buffer = token_buffer; + return COMMAND_LINE; + } + switch (c) { + case EOF: + return EOF; + case ' ': + case '\t': + break; + case '\\': + { + int d = input_stack::peek_char(); + if (d != '\n') { + context_buffer = '\\'; + return '\\'; + } + input_stack::get_char(); + break; + } + case '#': + do { + c = input_stack::get_char(); + } while (c != '\n' && c != EOF); + if (c == '\n') + context_buffer = '\n'; + return c; + case '"': + context_buffer = '"'; + token_buffer.clear(); + for (;;) { + c = input_stack::get_char(); + if (c == '\\') { + context_buffer += '\\'; + c = input_stack::peek_char(); + if (c == '"') { + input_stack::get_char(); + token_buffer += '"'; + context_buffer += '"'; + } + else + token_buffer += '\\'; + } + else if (c == '\n') { + error("newline in string"); + break; + } + else if (c == EOF) { + error("missing `\"'"); + break; + } + else if (c == '"') { + context_buffer += '"'; + break; + } + else { + context_buffer += char(c); + token_buffer += char(c); + } + } + return TEXT; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + int overflow = 0; + n = 0; + for (;;) { + if (n > (INT_MAX - 9)/10) { + overflow = 1; + break; + } + n *= 10; + n += c - '0'; + context_buffer += char(c); + c = input_stack::peek_char(); + if (c == EOF || !csdigit(c)) + break; + c = input_stack::get_char(); + } + token_double = n; + if (overflow) { + for (;;) { + token_double *= 10.0; + token_double += c - '0'; + context_buffer += char(c); + c = input_stack::peek_char(); + if (c == EOF || !csdigit(c)) + break; + c = input_stack::get_char(); + } + // if somebody asks for 1000000000000th, we will silently + // give them INT_MAXth + double temp = token_double; // work around gas 1.34/sparc bug + if (token_double > INT_MAX) + n = INT_MAX; + else + n = int(temp); + } + } + switch (c) { + case 'i': + case 'I': + context_buffer += char(c); + input_stack::get_char(); + return NUMBER; + case '.': + { + context_buffer += '.'; + input_stack::get_char(); + got_dot: + double factor = 1.0; + for (;;) { + c = input_stack::peek_char(); + if (!c == EOF || !csdigit(c)) + break; + input_stack::get_char(); + context_buffer += char(c); + factor /= 10.0; + if (c != '0') + token_double += factor*(c - '0'); + } + if (c != 'e' && c != 'E') { + if (c == 'i' || c == 'I') { + context_buffer += char(c); + input_stack::get_char(); + } + return NUMBER; + } + } + // fall through + case 'e': + case 'E': + { + int echar = c; + input_stack::get_char(); + c = input_stack::peek_char(); + int sign = '+'; + if (c == '+' || c == '-') { + sign = c; + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == EOF || !csdigit(c)) { + input_stack::push_back(sign); + input_stack::push_back(echar); + return NUMBER; + } + context_buffer += char(echar); + context_buffer += char(sign); + } + else { + if (c == EOF || !csdigit(c)) { + input_stack::push_back(echar); + return NUMBER; + } + context_buffer += char(echar); + } + input_stack::get_char(); + context_buffer += char(c); + n = c - '0'; + for (;;) { + c = input_stack::peek_char(); + if (c == EOF || !csdigit(c)) + break; + input_stack::get_char(); + context_buffer += char(c); + n = n*10 + (c - '0'); + } + if (sign == '-') + n = -n; + if (c == 'i' || c == 'I') { + context_buffer += char(c); + input_stack::get_char(); + } + token_double *= pow(10.0, n); + return NUMBER; + } + case 'n': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'd') { + input_stack::get_char(); + token_int = n; + context_buffer += "nd"; + return ORDINAL; + } + input_stack::push_back('n'); + return NUMBER; + case 'r': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'd') { + input_stack::get_char(); + token_int = n; + context_buffer += "rd"; + return ORDINAL; + } + input_stack::push_back('r'); + return NUMBER; + case 't': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'h') { + input_stack::get_char(); + token_int = n; + context_buffer += "th"; + return ORDINAL; + } + input_stack::push_back('t'); + return NUMBER; + case 's': + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + token_int = n; + context_buffer += "st"; + return ORDINAL; + } + input_stack::push_back('s'); + return NUMBER; + default: + return NUMBER; + } + break; + case '\'': + { + c = input_stack::peek_char(); + if (c == 't') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == 'h') { + input_stack::get_char(); + context_buffer = "'th"; + return TH; + } + else + input_stack::push_back('t'); + } + context_buffer = "'"; + return '\''; + } + case '.': + { + c = input_stack::peek_char(); + if (c != EOF && csdigit(c)) { + n = 0; + token_double = 0.0; + context_buffer = '.'; + goto got_dot; + } + return get_token_after_dot(c); + } + case '<': + c = input_stack::peek_char(); + if (c == '-') { + input_stack::get_char(); + c = input_stack::peek_char(); + if (c == '>') { + input_stack::get_char(); + context_buffer = "<->"; + return DOUBLE_ARROW_HEAD; + } + context_buffer = "<-"; + return LEFT_ARROW_HEAD; + } + else if (c == '=') { + input_stack::get_char(); + context_buffer = "<="; + return LESSEQUAL; + } + context_buffer = "<"; + return '<'; + case '-': + c = input_stack::peek_char(); + if (c == '>') { + input_stack::get_char(); + context_buffer = "->"; + return RIGHT_ARROW_HEAD; + } + context_buffer = "-"; + return '-'; + case '!': + c = input_stack::peek_char(); + if (c == '=') { + input_stack::get_char(); + context_buffer = "!="; + return NOTEQUAL; + } + context_buffer = "!"; + return '!'; + case '>': + c = input_stack::peek_char(); + if (c == '=') { + input_stack::get_char(); + context_buffer = ">="; + return GREATEREQUAL; + } + context_buffer = ">"; + return '>'; + case '=': + c = input_stack::peek_char(); + if (c == '=') { + input_stack::get_char(); + context_buffer = "=="; + return EQUALEQUAL; + } + context_buffer = "="; + return '='; + case '&': + c = input_stack::peek_char(); + if (c == '&') { + input_stack::get_char(); + context_buffer = "&&"; + return ANDAND; + } + context_buffer = "&"; + return '&'; + case '|': + c = input_stack::peek_char(); + if (c == '|') { + input_stack::get_char(); + context_buffer = "||"; + return OROR; + } + context_buffer = "|"; + return '|'; + default: + if (c != EOF && csalpha(c)) { + token_buffer.clear(); + token_buffer = c; + for (;;) { + c = input_stack::peek_char(); + if (c == EOF || (!csalnum(c) && c != '_')) + break; + input_stack::get_char(); + token_buffer += char(c); + } + int tok = lookup_keyword(token_buffer.contents(), + token_buffer.length()); + if (tok != 0) { + context_buffer = token_buffer; + return tok; + } + char *def = 0; + if (lookup_flag) { + token_buffer += '\0'; + def = macro_table.lookup(token_buffer.contents()); + token_buffer.set_length(token_buffer.length() - 1); + if (def) { + if (c == '(') { + input_stack::get_char(); + interpolate_macro_with_args(def); + } + else + input_stack::push(new macro_input(def)); + } + } + if (!def) { + context_buffer = token_buffer; + if (csupper(token_buffer[0])) + return LABEL; + else + return VARIABLE; + } + } + else { + context_buffer = char(c); + return (unsigned char)c; + } + break; + } + } +} + +int get_delimited() +{ + token_buffer.clear(); + int c = input_stack::get_char(); + while (c == ' ' || c == '\t' || c == '\n') + c = input_stack::get_char(); + if (c == EOF) { + lex_error("missing delimiter"); + return 0; + } + context_buffer = char(c); + int had_newline = 0; + int start = c; + int level = 0; + enum { NORMAL, IN_STRING, IN_STRING_QUOTED, DELIM_END } state = NORMAL; + for (;;) { + c = input_stack::get_char(); + if (c == EOF) { + lex_error("missing closing delimiter"); + return 0; + } + if (c == '\n') + had_newline = 1; + else if (!had_newline) + context_buffer += char(c); + switch (state) { + case NORMAL: + if (start == '{') { + if (c == '{') { + level++; + break; + } + if (c == '}') { + if (--level < 0) + state = DELIM_END; + break; + } + } + else { + if (c == start) { + state = DELIM_END; + break; + } + } + if (c == '"') + state = IN_STRING; + break; + case IN_STRING_QUOTED: + if (c == '\n') + state = NORMAL; + else + state = IN_STRING; + break; + case IN_STRING: + if (c == '"' || c == '\n') + state = NORMAL; + else if (c == '\\') + state = IN_STRING_QUOTED; + break; + case DELIM_END: + // This case it just to shut cfront 2.0 up. + default: + assert(0); + } + if (state == DELIM_END) + break; + token_buffer += c; + } + return 1; +} + +void do_define() +{ + int t = get_token(0); // do not expand what we are defining + if (t != VARIABLE && t != LABEL) { + lex_error("can only define variable or placename"); + return; + } + token_buffer += '\0'; + string nm = token_buffer; + const char *name = nm.contents(); + if (!get_delimited()) + return; + token_buffer += '\0'; + macro_table.define(name, strsave(token_buffer.contents())); +} + +void do_undef() +{ + int t = get_token(0); // do not expand what we are undefining + if (t != VARIABLE && t != LABEL) { + lex_error("can only define variable or placename"); + return; + } + token_buffer += '\0'; + macro_table.define(token_buffer.contents(), 0); +} + + +class for_input : public input { + char *var; + char *body; + double to; + int by_is_multiplicative; + double by; + const char *p; + int done_newline; +public: + for_input(char *, double, int, double, char *); + ~for_input(); + int get(); + int peek(); +}; + +for_input::for_input(char *vr, double t, int bim, double b, char *bd) +: var(vr), to(t), by_is_multiplicative(bim), by(b), body(bd), p(body), + done_newline(0) +{ +} + +for_input::~for_input() +{ + a_delete var; + a_delete body; +} + +int for_input::get() +{ + if (p == 0) + return EOF; + for (;;) { + if (*p != '\0') + return (unsigned char)*p++; + if (!done_newline) { + done_newline = 1; + return '\n'; + } + double val; + if (!lookup_variable(var, &val)) { + lex_error("body of `for' terminated enclosing block"); + return EOF; + } + if (by_is_multiplicative) + val *= by; + else + val += by; + define_variable(var, val); + if (val > to) { + p = 0; + return EOF; + } + p = body; + done_newline = 0; + } +} + +int for_input::peek() +{ + if (p == 0) + return EOF; + if (*p != '\0') + return (unsigned char)*p; + if (!done_newline) + return '\n'; + double val; + if (!lookup_variable(var, &val)) + return EOF; + if (by_is_multiplicative) { + if (val * by > to) + return EOF; + } + else { + if (val + by > to) + return EOF; + } + if (*body == '\0') + return EOF; + return (unsigned char)*body; +} + +void do_for(char *var, double from, double to, int by_is_multiplicative, + double by, char *body) +{ + define_variable(var, from); + if (from <= to) + input_stack::push(new for_input(var, to, by_is_multiplicative, by, body)); +} + + +void do_copy(const char *filename) +{ + errno = 0; + FILE *fp = fopen(filename, "r"); + if (fp == 0) { + lex_error("can't open `%1': %2", filename, strerror(errno)); + return; + } + input_stack::push(new file_input(fp, filename)); +} + +class copy_thru_input : public input { + int done; + char *body; + char *until; + const char *p; + const char *ap; + int argv[9]; + int argc; + string line; + int get_line(); + virtual int inget() = 0; +public: + copy_thru_input(const char *b, const char *u); + ~copy_thru_input(); + int get(); + int peek(); +}; + +class copy_file_thru_input : public copy_thru_input { + input *in; +public: + copy_file_thru_input(input *, const char *b, const char *u); + ~copy_file_thru_input(); + int inget(); +}; + +copy_file_thru_input::copy_file_thru_input(input *i, const char *b, + const char *u) +: in(i), copy_thru_input(b, u) +{ +} + +copy_file_thru_input::~copy_file_thru_input() +{ + delete in; +} + +int copy_file_thru_input::inget() +{ + if (!in) + return EOF; + else + return in->get(); +} + +class copy_rest_thru_input : public copy_thru_input { +public: + copy_rest_thru_input(const char *, const char *u); + int inget(); +}; + +copy_rest_thru_input::copy_rest_thru_input(const char *b, const char *u) +: copy_thru_input(b, u) +{ +} + +int copy_rest_thru_input::inget() +{ + while (next != 0) { + int c = next->get(); + if (c != EOF) + return c; + if (next->next == 0) + return EOF; + input *tem = next; + next = next->next; + delete tem; + } + return EOF; + +} + +copy_thru_input::copy_thru_input(const char *b, const char *u) +: done(0) +{ + ap = 0; + body = process_body(b); + p = 0; + until = strsave(u); +} + + +copy_thru_input::~copy_thru_input() +{ + a_delete body; + a_delete until; +} + +int copy_thru_input::get() +{ + if (ap) { + if (*ap != '\0') + return (unsigned char)*ap++; + ap = 0; + } + for (;;) { + if (p == 0) { + if (!get_line()) + break; + p = body; + } + if (*p == '\0') { + p = 0; + return '\n'; + } + while (*p >= ARG1 && *p <= ARG1 + 8) { + int i = *p++ - ARG1; + if (i < argc && line[argv[i]] != '\0') { + ap = line.contents() + argv[i]; + return (unsigned char)*ap++; + } + } + if (*p != '\0') + return (unsigned char)*p++; + } + return EOF; +} + +int copy_thru_input::peek() +{ + if (ap) { + if (*ap != '\0') + return (unsigned char)*ap; + ap = 0; + } + for (;;) { + if (p == 0) { + if (!get_line()) + break; + p = body; + } + if (*p == '\0') + return '\n'; + while (*p >= ARG1 && *p <= ARG1 + 8) { + int i = *p++ - ARG1; + if (i < argc && line[argv[i]] != '\0') { + ap = line.contents() + argv[i]; + return (unsigned char)*ap; + } + } + if (*p != '\0') + return (unsigned char)*p; + } + return EOF; +} + +int copy_thru_input::get_line() +{ + if (done) + return 0; + line.clear(); + argc = 0; + int c = inget(); + for (;;) { + while (c == ' ') + c = inget(); + if (c == EOF || c == '\n') + break; + if (argc == 9) { + do { + c = inget(); + } while (c != '\n' && c != EOF); + break; + } + argv[argc++] = line.length(); + do { + line += char(c); + c = inget(); + } while (c != ' ' && c != '\n'); + line += '\0'; + } + if (until != 0 && argc > 0 && strcmp(&line[argv[0]], until) == 0) { + done = 1; + return 0; + } + return argc > 0 || c == '\n'; +} + +class simple_file_input : public input { + const char *filename; + int lineno; + FILE *fp; +public: + simple_file_input(FILE *, const char *); + ~simple_file_input(); + int get(); + int peek(); + int get_location(const char **, int *); +}; + +simple_file_input::simple_file_input(FILE *p, const char *s) +: filename(s), fp(p), lineno(1) +{ +} + +simple_file_input::~simple_file_input() +{ + // don't delete the filename + fclose(fp); +} + +int simple_file_input::get() +{ + int c = getc(fp); + while (illegal_input_char(c)) { + error("illegal input character code %1", c); + c = getc(fp); + } + if (c == '\n') + lineno++; + return c; +} + +int simple_file_input::peek() +{ + int c = getc(fp); + while (illegal_input_char(c)) { + error("illegal input character code %1", c); + c = getc(fp); + } + if (c != EOF) + ungetc(c, fp); + return c; +} + +int simple_file_input::get_location(const char **fnp, int *lnp) +{ + *fnp = filename; + *lnp = lineno; + return 1; +} + + +void copy_file_thru(const char *filename, const char *body, const char *until) +{ + errno = 0; + FILE *fp = fopen(filename, "r"); + if (fp == 0) { + lex_error("can't open `%1': %2", filename, strerror(errno)); + return; + } + input *in = new copy_file_thru_input(new simple_file_input(fp, filename), + body, until); + input_stack::push(in); +} + +void copy_rest_thru(const char *body, const char *until) +{ + input_stack::push(new copy_rest_thru_input(body, until)); +} + +void push_body(const char *s) +{ + input_stack::push(new char_input('\n')); + input_stack::push(new macro_input(s)); +} + +int delim_flag = 0; + +char *get_thru_arg() +{ + int c = input_stack::peek_char(); + while (c == ' ') { + input_stack::get_char(); + c = input_stack::peek_char(); + } + if (c != EOF && csalpha(c)) { + // looks like a macro + input_stack::get_char(); + token_buffer = c; + for (;;) { + c = input_stack::peek_char(); + if (c == EOF || (!csalnum(c) && c != '_')) + break; + input_stack::get_char(); + token_buffer += char(c); + } + context_buffer = token_buffer; + token_buffer += '\0'; + char *def = macro_table.lookup(token_buffer.contents()); + if (def) + return strsave(def); + // I guess it wasn't a macro after all; so push the macro name back. + // -2 because we added a '\0' + for (int i = token_buffer.length() - 2; i >= 0; i--) + input_stack::push_back(token_buffer[i]); + } + if (get_delimited()) { + token_buffer += '\0'; + return strsave(token_buffer.contents()); + } + else + return 0; +} + +int lookahead_token = -1; +string old_context_buffer; + +void do_lookahead() +{ + if (lookahead_token == -1) { + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + } +} + +int yylex() +{ + if (delim_flag) { + assert(lookahead_token == -1); + if (delim_flag == 2) { + if ((yylval.str = get_thru_arg()) != 0) + return DELIMITED; + else + return 0; + } + else { + if (get_delimited()) { + token_buffer += '\0'; + yylval.str = strsave(token_buffer.contents()); + return DELIMITED; + } + else + return 0; + } + } + for (;;) { + int t; + if (lookahead_token >= 0) { + t = lookahead_token; + lookahead_token = -1; + } + else + t = get_token(1); + switch (t) { + case '\n': + return ';'; + case EOF: + return 0; + case DEFINE: + do_define(); + break; + case UNDEF: + do_undef(); + break; + case ORDINAL: + yylval.n = token_int; + return t; + case NUMBER: + yylval.x = token_double; + return t; + case COMMAND_LINE: + case TEXT: + token_buffer += '\0'; + if (!input_stack::get_location(&yylval.lstr.filename, + &yylval.lstr.lineno)) { + yylval.lstr.filename = 0; + yylval.lstr.lineno = -1; + } + yylval.lstr.str = strsave(token_buffer.contents()); + return t; + case LABEL: + case VARIABLE: + token_buffer += '\0'; + yylval.str = strsave(token_buffer.contents()); + return t; + case LEFT: + // change LEFT to LEFT_CORNER when followed by OF + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + if (lookahead_token == OF) + return LEFT_CORNER; + else + return t; + case RIGHT: + // change RIGHT to RIGHT_CORNER when followed by OF + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + if (lookahead_token == OF) + return RIGHT_CORNER; + else + return t; + case UPPER: + // recognise UPPER only before LEFT or RIGHT + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + if (lookahead_token != LEFT && lookahead_token != RIGHT) { + yylval.str = strsave("upper"); + return VARIABLE; + } + else + return t; + case LOWER: + // recognise LOWER only before LEFT or RIGHT + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + if (lookahead_token != LEFT && lookahead_token != RIGHT) { + yylval.str = strsave("lower"); + return VARIABLE; + } + else + return t; + case TOP: + // recognise TOP only before OF + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + if (lookahead_token != OF) { + yylval.str = strsave("top"); + return VARIABLE; + } + else + return t; + case BOTTOM: + // recognise BOTTOM only before OF + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + if (lookahead_token != OF) { + yylval.str = strsave("bottom"); + return VARIABLE; + } + else + return t; + case CENTER: + // recognise CENTER only before OF + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + if (lookahead_token != OF) { + yylval.str = strsave("center"); + return VARIABLE; + } + else + return t; + case START: + // recognise START only before OF + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + if (lookahead_token != OF) { + yylval.str = strsave("start"); + return VARIABLE; + } + else + return t; + case END: + // recognise END only before OF + old_context_buffer = context_buffer; + lookahead_token = get_token(1); + if (lookahead_token != OF) { + yylval.str = strsave("end"); + return VARIABLE; + } + else + return t; + default: + return t; + } + } +} + +void lex_error(const char *message, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + const char *filename; + int lineno; + if (!input_stack::get_location(&filename, &lineno)) + error(message, arg1, arg2, arg3); + else + error_with_file_and_line(filename, lineno, message, arg1, arg2, arg3); +} + +void lex_warning(const char *message, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + const char *filename; + int lineno; + if (!input_stack::get_location(&filename, &lineno)) + warning(message, arg1, arg2, arg3); + else + warning_with_file_and_line(filename, lineno, message, arg1, arg2, arg3); +} + +void yyerror(const char *s) +{ + const char *filename; + int lineno; + const char *context = 0; + if (lookahead_token == -1) { + if (context_buffer.length() > 0) { + context_buffer += '\0'; + context = context_buffer.contents(); + } + } + else { + if (old_context_buffer.length() > 0) { + old_context_buffer += '\0'; + context = old_context_buffer.contents(); + } + } + if (!input_stack::get_location(&filename, &lineno)) { + if (context) { + if (context[0] == '\n' && context[1] == '\0') + error("%1 before newline", s); + else + error("%1 before `%2'", s, context); + } + else + error("%1 at end of picture", s); + } + else { + if (context) { + if (context[0] == '\n' && context[1] == '\0') + error_with_file_and_line(filename, lineno, "%1 before newline", s); + else + error_with_file_and_line(filename, lineno, "%1 before `%2'", + s, context); + } + else + error_with_file_and_line(filename, lineno, "%1 at end of picture", s); + } +} + diff --git a/contrib/groff/pic/main.cc b/contrib/groff/pic/main.cc new file mode 100644 index 000000000000..87beb5dc285f --- /dev/null +++ b/contrib/groff/pic/main.cc @@ -0,0 +1,621 @@ +// -*- C++ -*- +/* 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" + +extern int yyparse(); + +output *out; + +int flyback_flag; +int zero_length_line_flag = 0; +// Non-zero means we're using a groff driver. +int driver_extension_flag = 1; +int compatible_flag = 0; +int safer_flag = 0; +int command_char = '.'; // the character that introduces lines + // that should be passed through tranparently +static int lf_flag = 1; // non-zero if we should attempt to understand + // lines beginning with `.lf' + +// Non-zero means a parse error was encountered. +static int had_parse_error = 0; + +void do_file(const char *filename); + +class top_input : public input { + FILE *fp; + int bol; + int eof; + int push_back[3]; + int start_lineno; +public: + top_input(FILE *); + int get(); + int peek(); + int get_location(const char **, int *); +}; + +top_input::top_input(FILE *p) : fp(p), bol(1), eof(0) +{ + push_back[0] = push_back[1] = push_back[2] = EOF; + start_lineno = current_lineno; +} + +int top_input::get() +{ + if (eof) + return EOF; + if (push_back[2] != EOF) { + int c = push_back[2]; + push_back[2] = EOF; + return c; + } + else if (push_back[1] != EOF) { + int c = push_back[1]; + push_back[1] = EOF; + return c; + } + else if (push_back[0] != EOF) { + int c = push_back[0]; + push_back[0] = EOF; + return c; + } + int c = getc(fp); + while (illegal_input_char(c)) { + error("illegal input character code %1", int(c)); + c = getc(fp); + bol = 0; + } + if (bol && c == '.') { + c = getc(fp); + if (c == 'P') { + c = getc(fp); + if (c == 'F' || c == 'E') { + int d = getc(fp); + if (d != EOF) + ungetc(d, fp); + if (d == EOF || d == ' ' || d == '\n' || compatible_flag) { + eof = 1; + flyback_flag = c == 'F'; + return EOF; + } + push_back[0] = c; + push_back[1] = 'P'; + return '.'; + } + if (c == 'S') { + c = getc(fp); + if (c != EOF) + ungetc(c, fp); + if (c == EOF || c == ' ' || c == '\n' || compatible_flag) { + error("nested .PS"); + eof = 1; + return EOF; + } + push_back[0] = 'S'; + push_back[1] = 'P'; + return '.'; + } + if (c != EOF) + ungetc(c, fp); + push_back[0] = 'P'; + return '.'; + } + else { + if (c != EOF) + ungetc(c, fp); + return '.'; + } + } + if (c == '\n') { + bol = 1; + current_lineno++; + return '\n'; + } + bol = 0; + if (c == EOF) { + eof = 1; + error("end of file before .PE or .PF"); + error_with_file_and_line(current_filename, start_lineno - 1, + ".PS was here"); + } + return c; +} + +int top_input::peek() +{ + if (eof) + return EOF; + if (push_back[2] != EOF) + return push_back[2]; + if (push_back[1] != EOF) + return push_back[1]; + if (push_back[0] != EOF) + return push_back[0]; + int c = getc(fp); + while (illegal_input_char(c)) { + error("illegal input character code %1", int(c)); + c = getc(fp); + bol = 0; + } + if (bol && c == '.') { + c = getc(fp); + if (c == 'P') { + c = getc(fp); + if (c == 'F' || c == 'E') { + int d = getc(fp); + if (d != EOF) + ungetc(d, fp); + if (d == EOF || d == ' ' || d == '\n' || compatible_flag) { + eof = 1; + flyback_flag = c == 'F'; + return EOF; + } + push_back[0] = c; + push_back[1] = 'P'; + push_back[2] = '.'; + return '.'; + } + if (c == 'S') { + c = getc(fp); + if (c != EOF) + ungetc(c, fp); + if (c == EOF || c == ' ' || c == '\n' || compatible_flag) { + error("nested .PS"); + eof = 1; + return EOF; + } + push_back[0] = 'S'; + push_back[1] = 'P'; + push_back[2] = '.'; + return '.'; + } + if (c != EOF) + ungetc(c, fp); + push_back[0] = 'P'; + push_back[1] = '.'; + return '.'; + } + else { + if (c != EOF) + ungetc(c, fp); + push_back[0] = '.'; + return '.'; + } + } + if (c != EOF) + ungetc(c, fp); + if (c == '\n') + return '\n'; + return c; +} + +int top_input::get_location(const char **filenamep, int *linenop) +{ + *filenamep = current_filename; + *linenop = current_lineno; + return 1; +} + +void do_picture(FILE *fp) +{ + flyback_flag = 0; + int c; + while ((c = getc(fp)) == ' ') + ; + if (c == '<') { + string filename; + while ((c = getc(fp)) == ' ') + ; + while (c != EOF && c != ' ' && c != '\n') { + filename += char(c); + c = getc(fp); + } + if (c == ' ') { + do { + c = getc(fp); + } while (c != EOF && c != '\n'); + } + if (c == '\n') + current_lineno++; + if (filename.length() == 0) + error("missing filename after `<'"); + else { + filename += '\0'; + const char *old_filename = current_filename; + int old_lineno = current_lineno; + // filenames must be permanent + do_file(strsave(filename.contents())); + current_filename = old_filename; + current_lineno = old_lineno; + } + out->set_location(current_filename, current_lineno); + } + else { + out->set_location(current_filename, current_lineno); + string start_line; + while (c != EOF) { + if (c == '\n') { + current_lineno++; + break; + } + start_line += c; + c = getc(fp); + } + if (c == EOF) + return; + start_line += '\0'; + double wid, ht; + switch (sscanf(&start_line[0], "%lf %lf", &wid, &ht)) { + case 1: + ht = 0.0; + break; + case 2: + break; + default: + ht = wid = 0.0; + break; + } + out->set_desired_width_height(wid, ht); + out->set_args(start_line.contents()); + lex_init(new top_input(fp)); + if (yyparse()) { + had_parse_error = 1; + lex_error("giving up on this picture"); + } + parse_cleanup(); + lex_cleanup(); + + // skip the rest of the .PF/.PE line + while ((c = getc(fp)) != EOF && c != '\n') + ; + if (c == '\n') + current_lineno++; + out->set_location(current_filename, current_lineno); + } +} + +void do_file(const char *filename) +{ + FILE *fp; + if (strcmp(filename, "-") == 0) + fp = stdin; + else { + errno = 0; + fp = fopen(filename, "r"); + if (fp == 0) + fatal("can't open `%1': %2", filename, strerror(errno)); + } + out->set_location(filename, 1); + current_filename = filename; + current_lineno = 1; + enum { START, MIDDLE, HAD_DOT, HAD_P, HAD_PS, HAD_l, HAD_lf } state = START; + for (;;) { + int c = getc(fp); + if (c == EOF) + break; + switch (state) { + case START: + if (c == '.') + state = HAD_DOT; + else { + putchar(c); + if (c == '\n') { + current_lineno++; + state = START; + } + else + state = MIDDLE; + } + break; + case MIDDLE: + putchar(c); + if (c == '\n') { + current_lineno++; + state = START; + } + break; + case HAD_DOT: + if (c == 'P') + state = HAD_P; + else if (lf_flag && c == 'l') + state = HAD_l; + else { + putchar('.'); + putchar(c); + if (c == '\n') { + current_lineno++; + state = START; + } + else + state = MIDDLE; + } + break; + case HAD_P: + if (c == 'S') + state = HAD_PS; + else { + putchar('.'); + putchar('P'); + putchar(c); + if (c == '\n') { + current_lineno++; + state = START; + } + else + state = MIDDLE; + } + break; + case HAD_PS: + if (c == ' ' || c == '\n' || compatible_flag) { + ungetc(c, fp); + do_picture(fp); + state = START; + } + else { + fputs(".PS", stdout); + putchar(c); + state = MIDDLE; + } + break; + case HAD_l: + if (c == 'f') + state = HAD_lf; + else { + putchar('.'); + putchar('l'); + putchar(c); + if (c == '\n') { + current_lineno++; + state = START; + } + else + state = MIDDLE; + } + break; + case HAD_lf: + if (c == ' ' || c == '\n' || compatible_flag) { + string line; + while (c != EOF) { + line += c; + if (c == '\n') { + current_lineno++; + break; + } + c = getc(fp); + } + line += '\0'; + interpret_lf_args(line.contents()); + printf(".lf%s", line.contents()); + state = START; + } + else { + fputs(".lf", stdout); + putchar(c); + state = MIDDLE; + } + break; + default: + assert(0); + } + } + switch (state) { + case START: + break; + case MIDDLE: + putchar('\n'); + break; + case HAD_DOT: + fputs(".\n", stdout); + break; + case HAD_P: + fputs(".P\n", stdout); + break; + case HAD_PS: + fputs(".PS\n", stdout); + break; + case HAD_l: + fputs(".l\n", stdout); + break; + case HAD_lf: + fputs(".lf\n", stdout); + break; + } + if (fp != stdin) + fclose(fp); +} + +#ifdef FIG_SUPPORT +void do_whole_file(const char *filename) +{ + // Do not set current_filename. + FILE *fp; + if (strcmp(filename, "-") == 0) + fp = stdin; + else { + errno = 0; + fp = fopen(filename, "r"); + if (fp == 0) + fatal("can't open `%1': %2", filename, strerror(errno)); + } + lex_init(new file_input(fp, filename)); + if (yyparse()) + had_parse_error = 1; + parse_cleanup(); + lex_cleanup(); +} +#endif + +void usage() +{ + fprintf(stderr, "usage: %s [ -nvC ] [ filename ... ]\n", program_name); +#ifdef TEX_SUPPORT + fprintf(stderr, " %s -t [ -cvzC ] [ filename ... ]\n", program_name); +#endif +#ifdef FIG_SUPPORT + fprintf(stderr, " %s -f [ -v ] [ filename ]\n", program_name); +#endif + exit(1); +} + +#ifdef __MSDOS__ +static char *fix_program_name(char *arg, char *dflt) +{ + if (!arg) + return dflt; + char *prog = strchr(arg, '\0'); + for (;;) { + if (prog == arg) + break; + --prog; + if (strchr("\\/:", *prog)) { + prog++; + break; + } + } + char *ext = strchr(prog, '.'); + if (ext) + *ext = '\0'; + for (char *p = prog; *p; p++) + if ('A' <= *p && *p <= 'Z') + *p = 'a' + (*p - 'A'); + return prog; +} +#endif /* __MSDOS__ */ + +int main(int argc, char **argv) +{ +#ifdef __MSDOS__ + argv[0] = fix_program_name(argv[0], "pic"); +#endif /* __MSDOS__ */ + program_name = argv[0]; + static char stderr_buf[BUFSIZ]; + setbuf(stderr, stderr_buf); + int opt; +#ifdef TEX_SUPPORT + int tex_flag = 0; + int tpic_flag = 0; +#endif +#ifdef FIG_SUPPORT + int whole_file_flag = 0; + int fig_flag = 0; +#endif + while ((opt = getopt(argc, argv, "T:CDStcvnxzpf")) != EOF) + switch (opt) { + case 'C': + compatible_flag = 1; + break; + case 'D': + case 'T': + break; + case 'S': + safer_flag = 1; + break; + case 'f': +#ifdef FIG_SUPPORT + whole_file_flag++; + fig_flag++; +#else + fatal("fig support not included"); +#endif + break; + case 'n': + driver_extension_flag = 0; + break; + case 'p': + case 'x': + warning("-%1 option is obsolete", char(opt)); + break; + case 't': +#ifdef TEX_SUPPORT + tex_flag++; +#else + fatal("TeX support not included"); +#endif + break; + case 'c': +#ifdef TEX_SUPPORT + tpic_flag++; +#else + fatal("TeX support not included"); +#endif + break; + case 'v': + { + extern const char *version_string; + fprintf(stderr, "GNU pic version %s\n", version_string); + fflush(stderr); + break; + } + case 'z': + // zero length lines will be printed as dots + zero_length_line_flag++; + break; + case '?': + usage(); + break; + default: + assert(0); + } + parse_init(); +#ifdef TEX_SUPPORT + if (tpic_flag) { + out = make_tpic_output(); + lf_flag = 0; + } + else if (tex_flag) { + out = make_tex_output(); + command_char = '\\'; + lf_flag = 0; + } + else +#endif +#ifdef FIG_SUPPORT + if (fig_flag) + out = make_fig_output(); + else +#endif + out = make_troff_output(); +#ifdef FIG_SUPPORT + if (whole_file_flag) { + if (optind >= argc) + do_whole_file("-"); + else if (argc - optind > 1) + usage(); + else + do_whole_file(argv[optind]); + } + else { +#endif + if (optind >= argc) + do_file("-"); + else + for (int i = optind; i < argc; i++) + do_file(argv[i]); +#ifdef FIG_SUPPORT + } +#endif + delete out; + if (ferror(stdout) || fflush(stdout) < 0) + fatal("output error"); + return had_parse_error; +} + diff --git a/contrib/groff/pic/object.cc b/contrib/groff/pic/object.cc new file mode 100644 index 000000000000..860e1bc64531 --- /dev/null +++ b/contrib/groff/pic/object.cc @@ -0,0 +1,1833 @@ +// -*- C++ -*- +/* 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" + +void print_object_list(object *); + +line_type::line_type() +: type(solid), thickness(1.0) +{ +} + +output::output() : desired_height(0.0), desired_width(0.0), args(0) +{ +} + +output::~output() +{ + a_delete args; +} + +void output::set_desired_width_height(double wid, double ht) +{ + desired_width = wid; + desired_height = ht; +} + +void output::set_args(const char *s) +{ + a_delete args; + if (s == 0 || *s == '\0') + args = 0; + else + args = strsave(s); +} + +void output::command(const char *, const char *, int) +{ +} + +void output::set_location(const char *, int) +{ +} + +int output::supports_filled_polygons() +{ + return 0; +} + +void output::begin_block(const position &, const position &) +{ +} + +void output::end_block() +{ +} + +double output::compute_scale(double sc, const position &ll, const position &ur) +{ + distance dim = ur - ll; + if (desired_width != 0.0 || desired_height != 0.0) { + sc = 0.0; + if (desired_width != 0.0) { + if (dim.x == 0.0) + error("width specified for picture with zero width"); + else + sc = dim.x/desired_width; + } + if (desired_height != 0.0) { + if (dim.y == 0.0) + error("height specified for picture with zero height"); + else { + double tem = dim.y/desired_height; + if (tem > sc) + sc = tem; + } + } + return sc == 0.0 ? 1.0 : sc; + } + else { + if (sc <= 0.0) + sc = 1.0; + distance sdim = dim/sc; + double max_width = 0.0; + lookup_variable("maxpswid", &max_width); + double max_height = 0.0; + lookup_variable("maxpsht", &max_height); + if ((max_width > 0.0 && sdim.x > max_width) + || (max_height > 0.0 && sdim.y > max_height)) { + double xscale = dim.x/max_width; + double yscale = dim.y/max_height; + return xscale > yscale ? xscale : yscale; + } + else + return sc; + } +} + +position::position(const place &pl) +{ + if (pl.obj != 0) { + // Use two statements to work around bug in SGI C++. + object *tem = pl.obj; + *this = tem->origin(); + } + else { + x = pl.x; + y = pl.y; + } +} + +position::position() : x(0.0), y(0.0) +{ +} + +position::position(double a, double b) : x(a), y(b) +{ +} + + +int operator==(const position &a, const position &b) +{ + return a.x == b.x && a.y == b.y; +} + +int operator!=(const position &a, const position &b) +{ + return a.x != b.x || a.y != b.y; +} + +position &position::operator+=(const position &a) +{ + x += a.x; + y += a.y; + return *this; +} + +position &position::operator-=(const position &a) +{ + x -= a.x; + y -= a.y; + return *this; +} + +position &position::operator*=(double a) +{ + x *= a; + y *= a; + return *this; +} + +position &position::operator/=(double a) +{ + x /= a; + y /= a; + return *this; +} + +position operator-(const position &a) +{ + return position(-a.x, -a.y); +} + +position operator+(const position &a, const position &b) +{ + return position(a.x + b.x, a.y + b.y); +} + +position operator-(const position &a, const position &b) +{ + return position(a.x - b.x, a.y - b.y); +} + +position operator/(const position &a, double n) +{ + return position(a.x/n, a.y/n); +} + +position operator*(const position &a, double n) +{ + return position(a.x*n, a.y*n); +} + +// dot product + +double operator*(const position &a, const position &b) +{ + return a.x*b.x + a.y*b.y; +} + +double hypot(const position &a) +{ + return hypot(a.x, a.y); +} + +struct arrow_head_type { + double height; + double width; + int solid; +}; + +void draw_arrow(const position &pos, const distance &dir, + const arrow_head_type &aht, const line_type <) +{ + double hyp = hypot(dir); + if (hyp == 0.0) { + error("cannot draw arrow on object with zero length"); + return; + } + position base = -dir; + base *= aht.height/hyp; + position n(dir.y, -dir.x); + n *= aht.width/(hyp*2.0); + line_type slt = lt; + slt.type = line_type::solid; + if (aht.solid && out->supports_filled_polygons()) { + position v[3]; + v[0] = pos; + v[1] = pos + base + n; + v[2] = pos + base - n; + // A value > 1 means fill with the current color. + out->polygon(v, 3, slt, 2.0); + } + else { + position v[2]; + v[0] = pos; + v[1] = pos + base + n; + out->line(pos + base - n, v, 2, slt); + } +} + +object::object() : prev(0), next(0) +{ +} + +object::~object() +{ +} + +void object::move_by(const position &) +{ +} + +void object::print() +{ +} + +void object::print_text() +{ +} + +int object::blank() +{ + return 0; +} + +struct bounding_box { + int blank; + position ll; + position ur; + + bounding_box(); + void encompass(const position &); +}; + +bounding_box::bounding_box() +: blank(1) +{ +} + +void bounding_box::encompass(const position &pos) +{ + if (blank) { + ll = pos; + ur = pos; + blank = 0; + } + else { + if (pos.x < ll.x) + ll.x = pos.x; + if (pos.y < ll.y) + ll.y = pos.y; + if (pos.x > ur.x) + ur.x = pos.x; + if (pos.y > ur.y) + ur.y = pos.y; + } +} + +void object::update_bounding_box(bounding_box *) +{ +} + +position object::origin() +{ + return position(0.0,0.0); +} + +position object::north() +{ + return origin(); +} + +position object::south() +{ + return origin(); +} + +position object::east() +{ + return origin(); +} + +position object::west() +{ + return origin(); +} + +position object::north_east() +{ + return origin(); +} + +position object::north_west() +{ + return origin(); +} + +position object::south_east() +{ + return origin(); +} + +position object::south_west() +{ + return origin(); +} + +position object::start() +{ + return origin(); +} + +position object::end() +{ + return origin(); +} + +position object::center() +{ + return origin(); +} + +double object::width() +{ + return 0.0; +} + +double object::radius() +{ + return 0.0; +} + +double object::height() +{ + return 0.0; +} + +place *object::find_label(const char *) +{ + return 0; +} + +segment::segment(const position &a, int n, segment *p) +: pos(a), is_absolute(n), next(p) +{ +} + +text_item::text_item(char *t, const char *fn, int ln) +: filename(fn), lineno(ln), text(t), next(0) +{ + adj.h = CENTER_ADJUST; + adj.v = NONE_ADJUST; +} + +text_item::~text_item() +{ + a_delete text; +} + +object_spec::object_spec(object_type t) : type(t) +{ + flags = 0; + tbl = 0; + segment_list = 0; + segment_width = segment_height = 0.0; + segment_is_absolute = 0; + text = 0; + with = 0; + dir = RIGHT_DIRECTION; +} + +object_spec::~object_spec() +{ + delete tbl; + while (segment_list != 0) { + segment *tem = segment_list; + segment_list = segment_list->next; + delete tem; + } + object *p = oblist.head; + while (p != 0) { + object *tem = p; + p = p->next; + delete tem; + } + while (text != 0) { + text_item *tem = text; + text = text->next; + delete tem; + } + delete with; +} + +class command_object : public object { + char *s; + const char *filename; + int lineno; +public: + command_object(char *, const char *, int); + ~command_object(); + object_type type() { return OTHER_OBJECT; } + void print(); +}; + +command_object::command_object(char *p, const char *fn, int ln) +: s(p), filename(fn), lineno(ln) +{ +} + +command_object::~command_object() +{ + a_delete s; +} + +void command_object::print() +{ + out->command(s, filename, lineno); +} + +object *make_command_object(char *s, const char *fn, int ln) +{ + return new command_object(s, fn, ln); +} + +class mark_object : public object { +public: + mark_object(); + object_type type(); +}; + +object *make_mark_object() +{ + return new mark_object(); +} + +mark_object::mark_object() +{ +} + +object_type mark_object::type() +{ + return MARK_OBJECT; +} + +object_list::object_list() : head(0), tail(0) +{ +} + +void object_list::append(object *obj) +{ + if (tail == 0) { + obj->next = obj->prev = 0; + head = tail = obj; + } + else { + obj->prev = tail; + obj->next = 0; + tail->next = obj; + tail = obj; + } +} + +void object_list::wrap_up_block(object_list *ol) +{ + object *p; + for (p = tail; p && p->type() != MARK_OBJECT; p = p->prev) + ; + assert(p != 0); + ol->head = p->next; + if (ol->head) { + ol->tail = tail; + ol->head->prev = 0; + } + else + ol->tail = 0; + tail = p->prev; + if (tail) + tail->next = 0; + else + head = 0; + delete p; +} + +text_piece::text_piece() +: text(0), filename(0), lineno(-1) +{ + adj.h = CENTER_ADJUST; + adj.v = NONE_ADJUST; +} + +text_piece::~text_piece() +{ + a_delete text; +} + +class graphic_object : public object { + int ntext; + text_piece *text; + int aligned; +protected: + line_type lt; +public: + graphic_object(); + ~graphic_object(); + object_type type() = 0; + void print_text(); + void add_text(text_item *, int); + void set_dotted(double); + void set_dashed(double); + void set_thickness(double); + void set_invisible(); + virtual void set_fill(double); +}; + +graphic_object::graphic_object() : ntext(0), text(0), aligned(0) +{ +} + +void graphic_object::set_dotted(double wid) +{ + lt.type = line_type::dotted; + lt.dash_width = wid; +} + +void graphic_object::set_dashed(double wid) +{ + lt.type = line_type::dashed; + lt.dash_width = wid; +} + +void graphic_object::set_thickness(double th) +{ + lt.thickness = th; +} + +void graphic_object::set_fill(double) +{ +} + +void graphic_object::set_invisible() +{ + lt.type = line_type::invisible; +} + +void graphic_object::add_text(text_item *t, int a) +{ + aligned = a; + int len = 0; + text_item *p; + for (p = t; p; p = p->next) + len++; + if (len == 0) + text = 0; + else { + text = new text_piece[len]; + for (p = t, len = 0; p; p = p->next, len++) { + text[len].text = p->text; + p->text = 0; + text[len].adj = p->adj; + text[len].filename = p->filename; + text[len].lineno = p->lineno; + } + } + ntext = len; +} + +void graphic_object::print_text() +{ + double angle = 0.0; + if (aligned) { + position d(end() - start()); + if (d.x != 0.0 || d.y != 0.0) + angle = atan2(d.y, d.x); + } + if (text != 0) + out->text(center(), text, ntext, angle); +} + +graphic_object::~graphic_object() +{ + if (text) + ad_delete(ntext) text; +} + +class rectangle_object : public graphic_object { +protected: + position cent; + position dim; +public: + rectangle_object(const position &); + double width() { return dim.x; } + double height() { return dim.y; } + position origin() { return cent; } + position center() { return cent; } + position north() { return position(cent.x, cent.y + dim.y/2.0); } + position south() { return position(cent.x, cent.y - dim.y/2.0); } + position east() { return position(cent.x + dim.x/2.0, cent.y); } + position west() { return position(cent.x - dim.x/2.0, cent.y); } + position north_east() { return position(cent.x + dim.x/2.0, cent.y + dim.y/2.0); } + position north_west() { return position(cent.x - dim.x/2.0, cent.y + dim.y/2.0); } + position south_east() { return position(cent.x + dim.x/2.0, cent.y - dim.y/2.0); } + position south_west() { return position(cent.x - dim.x/2.0, cent.y - dim.y/2.0); } + object_type type() = 0; + void update_bounding_box(bounding_box *); + void move_by(const position &); +}; + +rectangle_object::rectangle_object(const position &d) +: dim(d) +{ +} + +void rectangle_object::update_bounding_box(bounding_box *p) +{ + p->encompass(cent - dim/2.0); + p->encompass(cent + dim/2.0); +} + +void rectangle_object::move_by(const position &a) +{ + cent += a; +} + +class closed_object : public rectangle_object { +public: + closed_object(const position &); + object_type type() = 0; + void set_fill(double); +protected: + double fill; // < 0 if not filled +}; + +closed_object::closed_object(const position &pos) +: rectangle_object(pos), fill(-1.0) +{ +} + +void closed_object::set_fill(double f) +{ + assert(f >= 0.0); + fill = f; +} + + +class box_object : public closed_object { + double xrad; + double yrad; +public: + box_object(const position &, double); + object_type type() { return BOX_OBJECT; } + void print(); + position north_east(); + position north_west(); + position south_east(); + position south_west(); +}; + +box_object::box_object(const position &pos, double r) +: closed_object(pos), xrad(dim.x > 0 ? r : -r), yrad(dim.y > 0 ? r : -r) +{ +} + +const double CHOP_FACTOR = 1.0 - 1.0/M_SQRT2; + +position box_object::north_east() +{ + return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad, + cent.y + dim.y/2.0 - CHOP_FACTOR*yrad); +} + +position box_object::north_west() +{ + return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad, + cent.y + dim.y/2.0 - CHOP_FACTOR*yrad); +} + +position box_object::south_east() +{ + return position(cent.x + dim.x/2.0 - CHOP_FACTOR*xrad, + cent.y - dim.y/2.0 + CHOP_FACTOR*yrad); +} + +position box_object::south_west() +{ + return position(cent.x - dim.x/2.0 + CHOP_FACTOR*xrad, + cent.y - dim.y/2.0 + CHOP_FACTOR*yrad); +} + +void box_object::print() +{ + if (lt.type == line_type::invisible && fill < 0.0) + return; + if (xrad == 0.0) { + distance dim2 = dim/2.0; + position vec[4]; + vec[0] = cent + position(dim2.x, -dim2.y); + vec[1] = cent + position(dim2.x, dim2.y); + vec[2] = cent + position(-dim2.x, dim2.y); + vec[3] = cent + position(-dim2.x, -dim2.y); + out->polygon(vec, 4, lt, fill); + } + else { + distance abs_dim(fabs(dim.x), fabs(dim.y)); + out->rounded_box(cent, abs_dim, fabs(xrad), lt, fill); + } +} + +graphic_object *object_spec::make_box(position *curpos, direction *dirp) +{ + static double last_box_height; + static double last_box_width; + static double last_box_radius; + static int have_last_box = 0; + if (!(flags & HAS_HEIGHT)) { + if ((flags & IS_SAME) && have_last_box) + height = last_box_height; + else + lookup_variable("boxht", &height); + } + if (!(flags & HAS_WIDTH)) { + if ((flags & IS_SAME) && have_last_box) + width = last_box_width; + else + lookup_variable("boxwid", &width); + } + if (!(flags & HAS_RADIUS)) { + if ((flags & IS_SAME) && have_last_box) + radius = last_box_radius; + else + lookup_variable("boxrad", &radius); + } + last_box_width = width; + last_box_height = height; + last_box_radius = radius; + have_last_box = 1; + radius = fabs(radius); + if (radius*2.0 > fabs(width)) + radius = fabs(width/2.0); + if (radius*2.0 > fabs(height)) + radius = fabs(height/2.0); + box_object *p = new box_object(position(width, height), radius); + if (!position_rectangle(p, curpos, dirp)) { + delete p; + p = 0; + } + return p; +} + +// return non-zero for success + +int object_spec::position_rectangle(rectangle_object *p, + position *curpos, direction *dirp) +{ + position pos; + dir = *dirp; // ignore any direction in attribute list + position motion; + switch (dir) { + case UP_DIRECTION: + motion.y = p->height()/2.0; + break; + case DOWN_DIRECTION: + motion.y = -p->height()/2.0; + break; + case LEFT_DIRECTION: + motion.x = -p->width()/2.0; + break; + case RIGHT_DIRECTION: + motion.x = p->width()/2.0; + break; + default: + assert(0); + } + if (flags & HAS_AT) { + pos = at; + if (flags & HAS_WITH) { + place offset; + place here; + here.obj = p; + if (!with->follow(here, &offset)) + return 0; + pos -= offset; + } + } + else { + pos = *curpos; + pos += motion; + } + p->move_by(pos); + pos += motion; + *curpos = pos; + return 1; +} + +class block_object : public rectangle_object { + object_list oblist; + PTABLE(place) *tbl; +public: + block_object(const position &, const object_list &ol, PTABLE(place) *t); + ~block_object(); + place *find_label(const char *); + object_type type(); + void move_by(const position &); + void print(); +}; + +block_object::block_object(const position &d, const object_list &ol, + PTABLE(place) *t) +: oblist(ol), tbl(t), rectangle_object(d) +{ +} + +block_object::~block_object() +{ + delete tbl; + object *p = oblist.head; + while (p != 0) { + object *tem = p; + p = p->next; + delete tem; + } +} + +void block_object::print() +{ + out->begin_block(south_west(), north_east()); + print_object_list(oblist.head); + out->end_block(); +} + +static void adjust_objectless_places(PTABLE(place) *tbl, const position &a) +{ + // Adjust all the labels that aren't attached to objects. + PTABLE_ITERATOR(place) iter(tbl); + const char *key; + place *pl; + while (iter.next(&key, &pl)) + if (key && csupper(key[0]) && pl->obj == 0) { + pl->x += a.x; + pl->y += a.y; + } +} + +void block_object::move_by(const position &a) +{ + cent += a; + for (object *p = oblist.head; p; p = p->next) + p->move_by(a); + adjust_objectless_places(tbl, a); +} + + +place *block_object::find_label(const char *name) +{ + return tbl->lookup(name); +} + +object_type block_object::type() +{ + return BLOCK_OBJECT; +} + +graphic_object *object_spec::make_block(position *curpos, direction *dirp) +{ + bounding_box bb; + for (object *p = oblist.head; p; p = p->next) + p->update_bounding_box(&bb); + position dim; + if (!bb.blank) { + position m = -(bb.ll + bb.ur)/2.0; + for (object *p = oblist.head; p; p = p->next) + p->move_by(m); + adjust_objectless_places(tbl, m); + dim = bb.ur - bb.ll; + } + if (flags & HAS_WIDTH) + dim.x = width; + if (flags & HAS_HEIGHT) + dim.y = height; + block_object *block = new block_object(dim, oblist, tbl); + if (!position_rectangle(block, curpos, dirp)) { + delete block; + block = 0; + } + tbl = 0; + oblist.head = oblist.tail = 0; + return block; +} + +class text_object : public rectangle_object { +public: + text_object(const position &); + object_type type() { return TEXT_OBJECT; } +}; + +text_object::text_object(const position &d) +: rectangle_object(d) +{ +} + +graphic_object *object_spec::make_text(position *curpos, direction *dirp) +{ + if (!(flags & HAS_HEIGHT)) { + lookup_variable("textht", &height); + int nitems = 0; + for (text_item *t = text; t; t = t->next) + nitems++; + height *= nitems; + } + if (!(flags & HAS_WIDTH)) + lookup_variable("textwid", &width); + text_object *p = new text_object(position(width, height)); + if (!position_rectangle(p, curpos, dirp)) { + delete p; + p = 0; + } + return p; +} + + +class ellipse_object : public closed_object { +public: + ellipse_object(const position &); + position north_east() { return position(cent.x + dim.x/(M_SQRT2*2.0), + cent.y + dim.y/(M_SQRT2*2.0)); } + position north_west() { return position(cent.x - dim.x/(M_SQRT2*2.0), + cent.y + dim.y/(M_SQRT2*2.0)); } + position south_east() { return position(cent.x + dim.x/(M_SQRT2*2.0), + cent.y - dim.y/(M_SQRT2*2.0)); } + position south_west() { return position(cent.x - dim.x/(M_SQRT2*2.0), + cent.y - dim.y/(M_SQRT2*2.0)); } + double radius() { return dim.x/2.0; } + object_type type() { return ELLIPSE_OBJECT; } + void print(); +}; + +ellipse_object::ellipse_object(const position &d) +: closed_object(d) +{ +} + +void ellipse_object::print() +{ + if (lt.type == line_type::invisible && fill < 0.0) + return; + out->ellipse(cent, dim, lt, fill); +} + +graphic_object *object_spec::make_ellipse(position *curpos, direction *dirp) +{ + static double last_ellipse_height; + static double last_ellipse_width; + static int have_last_ellipse = 0; + if (!(flags & HAS_HEIGHT)) { + if ((flags & IS_SAME) && have_last_ellipse) + height = last_ellipse_height; + else + lookup_variable("ellipseht", &height); + } + if (!(flags & HAS_WIDTH)) { + if ((flags & IS_SAME) && have_last_ellipse) + width = last_ellipse_width; + else + lookup_variable("ellipsewid", &width); + } + last_ellipse_width = width; + last_ellipse_height = height; + have_last_ellipse = 1; + ellipse_object *p = new ellipse_object(position(width, height)); + if (!position_rectangle(p, curpos, dirp)) { + delete p; + return 0; + } + return p; +} + +class circle_object : public ellipse_object { +public: + circle_object(double); + object_type type() { return CIRCLE_OBJECT; } + void print(); +}; + +circle_object::circle_object(double diam) +: ellipse_object(position(diam, diam)) +{ +} + +void circle_object::print() +{ + if (lt.type == line_type::invisible && fill < 0.0) + return; + out->circle(cent, dim.x/2.0, lt, fill); +} + +graphic_object *object_spec::make_circle(position *curpos, direction *dirp) +{ + static double last_circle_radius; + static int have_last_circle = 0; + if (!(flags & HAS_RADIUS)) { + if ((flags & IS_SAME) && have_last_circle) + radius = last_circle_radius; + else + lookup_variable("circlerad", &radius); + } + last_circle_radius = radius; + have_last_circle = 1; + circle_object *p = new circle_object(radius*2.0); + if (!position_rectangle(p, curpos, dirp)) { + delete p; + return 0; + } + return p; +} + +class move_object : public graphic_object { + position strt; + position en; +public: + move_object(const position &s, const position &e); + position origin() { return en; } + object_type type() { return MOVE_OBJECT; } + void update_bounding_box(bounding_box *); + void move_by(const position &); +}; + +move_object::move_object(const position &s, const position &e) +: strt(s), en(e) +{ +} + +void move_object::update_bounding_box(bounding_box *p) +{ + p->encompass(strt); + p->encompass(en); +} + +void move_object::move_by(const position &a) +{ + strt += a; + en += a; +} + +graphic_object *object_spec::make_move(position *curpos, direction *dirp) +{ + static position last_move; + static int have_last_move = 0; + *dirp = dir; + // No need to look at at since `at' attribute sets `from' attribute. + position startpos = (flags & HAS_FROM) ? from : *curpos; + if (!(flags & HAS_SEGMENT)) { + if ((flags && IS_SAME) && have_last_move) + segment_pos = last_move; + else { + switch (dir) { + case UP_DIRECTION: + segment_pos.y = segment_height; + break; + case DOWN_DIRECTION: + segment_pos.y = -segment_height; + break; + case LEFT_DIRECTION: + segment_pos.x = -segment_width; + break; + case RIGHT_DIRECTION: + segment_pos.x = segment_width; + break; + default: + assert(0); + } + } + } + segment_list = new segment(segment_pos, segment_is_absolute, segment_list); + // Reverse the segment_list so that it's in forward order. + segment *old = segment_list; + segment_list = 0; + while (old != 0) { + segment *tem = old->next; + old->next = segment_list; + segment_list = old; + old = tem; + } + // Compute the end position. + position endpos = startpos; + for (segment *s = segment_list; s; s = s->next) + if (s->is_absolute) + endpos = s->pos; + else + endpos += s->pos; + have_last_move = 1; + last_move = endpos - startpos; + move_object *p = new move_object(startpos, endpos); + *curpos = endpos; + return p; +} + +class linear_object : public graphic_object { +protected: + char arrow_at_start; + char arrow_at_end; + arrow_head_type aht; + position strt; + position en; +public: + linear_object(const position &s, const position &e); + position start() { return strt; } + position end() { return en; } + void move_by(const position &); + void update_bounding_box(bounding_box *) = 0; + object_type type() = 0; + void add_arrows(int at_start, int at_end, const arrow_head_type &); +}; + +class line_object : public linear_object { +protected: + position *v; + int n; +public: + line_object(const position &s, const position &e, position *, int); + ~line_object(); + position origin() { return strt; } + position center() { return (strt + en)/2.0; } + position north() { return (en.y - strt.y) > 0 ? en : strt; } + position south() { return (en.y - strt.y) < 0 ? en : strt; } + position east() { return (en.x - strt.x) > 0 ? en : strt; } + position west() { return (en.x - strt.x) < 0 ? en : strt; } + object_type type() { return LINE_OBJECT; } + void update_bounding_box(bounding_box *); + void print(); + void move_by(const position &); +}; + +class arrow_object : public line_object { +public: + arrow_object(const position &, const position &, position *, int); + object_type type() { return ARROW_OBJECT; } +}; + +class spline_object : public line_object { +public: + spline_object(const position &, const position &, position *, int); + object_type type() { return SPLINE_OBJECT; } + void print(); + void update_bounding_box(bounding_box *); +}; + +linear_object::linear_object(const position &s, const position &e) +: strt(s), en(e), arrow_at_start(0), arrow_at_end(0) +{ +} + +void linear_object::move_by(const position &a) +{ + strt += a; + en += a; +} + +void linear_object::add_arrows(int at_start, int at_end, + const arrow_head_type &a) +{ + arrow_at_start = at_start; + arrow_at_end = at_end; + aht = a; +} + +line_object::line_object(const position &s, const position &e, + position *p, int i) +: v(p), n(i), linear_object(s, e) +{ +} + +void line_object::print() +{ + if (lt.type == line_type::invisible) + return; + out->line(strt, v, n, lt); + if (arrow_at_start) + draw_arrow(strt, strt-v[0], aht, lt); + if (arrow_at_end) + draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt); +} + +void line_object::update_bounding_box(bounding_box *p) +{ + p->encompass(strt); + for (int i = 0; i < n; i++) + p->encompass(v[i]); +} + +void line_object::move_by(const position &pos) +{ + linear_object::move_by(pos); + for (int i = 0; i < n; i++) + v[i] += pos; +} + +void spline_object::update_bounding_box(bounding_box *p) +{ + p->encompass(strt); + p->encompass(en); + /* + + If + + p1 = q1/2 + q2/2 + p2 = q1/6 + q2*5/6 + p3 = q2*5/6 + q3/6 + p4 = q2/2 + q3/2 + [ the points for the Bezier cubic ] + + and + + t = .5 + + then + + (1-t)^3*p1 + 3*t*(t - 1)^2*p2 + 3*t^2*(1-t)*p3 + t^3*p4 + [ the equation for the Bezier cubic ] + + = .125*q1 + .75*q2 + .125*q3 + + */ + for (int i = 1; i < n; i++) + p->encompass((i == 1 ? strt : v[i-2])*.125 + v[i-1]*.75 + v[i]*.125); +} + +arrow_object::arrow_object(const position &s, const position &e, + position *p, int i) +: line_object(s, e, p, i) +{ +} + +spline_object::spline_object(const position &s, const position &e, + position *p, int i) +: line_object(s, e, p, i) +{ +} + +void spline_object::print() +{ + if (lt.type == line_type::invisible) + return; + out->spline(strt, v, n, lt); + if (arrow_at_start) + draw_arrow(strt, strt-v[0], aht, lt); + if (arrow_at_end) + draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt); +} + +line_object::~line_object() +{ + a_delete v; +} + +linear_object *object_spec::make_line(position *curpos, direction *dirp) +{ + static position last_line; + static int have_last_line = 0; + *dirp = dir; + // No need to look at at since `at' attribute sets `from' attribute. + position startpos = (flags & HAS_FROM) ? from : *curpos; + if (!(flags & HAS_SEGMENT)) { + if ((flags & IS_SAME) && (type == LINE_OBJECT || type == ARROW_OBJECT) + && have_last_line) + segment_pos = last_line; + else + switch (dir) { + case UP_DIRECTION: + segment_pos.y = segment_height; + break; + case DOWN_DIRECTION: + segment_pos.y = -segment_height; + break; + case LEFT_DIRECTION: + segment_pos.x = -segment_width; + break; + case RIGHT_DIRECTION: + segment_pos.x = segment_width; + break; + default: + assert(0); + } + } + segment_list = new segment(segment_pos, segment_is_absolute, segment_list); + // reverse the segment_list so that it's in forward order + segment *old = segment_list; + segment_list = 0; + while (old != 0) { + segment *tem = old->next; + old->next = segment_list; + segment_list = old; + old = tem; + } + // Absolutise all movements + position endpos = startpos; + int nsegments = 0; + segment *s; + for (s = segment_list; s; s = s->next, nsegments++) + if (s->is_absolute) + endpos = s->pos; + else { + endpos += s->pos; + s->pos = endpos; + s->is_absolute = 1; // to avoid confusion + } + // handle chop + line_object *p = 0; + position *v = new position[nsegments]; + int i = 0; + for (s = segment_list; s; s = s->next, i++) + v[i] = s->pos; + if (flags & IS_DEFAULT_CHOPPED) { + lookup_variable("circlerad", &start_chop); + end_chop = start_chop; + flags |= IS_CHOPPED; + } + if (flags & IS_CHOPPED) { + position start_chop_vec, end_chop_vec; + if (start_chop != 0.0) { + start_chop_vec = v[0] - startpos; + start_chop_vec *= start_chop / hypot(start_chop_vec); + } + if (end_chop != 0.0) { + end_chop_vec = (v[nsegments - 1] + - (nsegments > 1 ? v[nsegments - 2] : startpos)); + end_chop_vec *= end_chop / hypot(end_chop_vec); + } + startpos += start_chop_vec; + v[nsegments - 1] -= end_chop_vec; + endpos -= end_chop_vec; + } + switch (type) { + case SPLINE_OBJECT: + p = new spline_object(startpos, endpos, v, nsegments); + break; + case ARROW_OBJECT: + p = new arrow_object(startpos, endpos, v, nsegments); + break; + case LINE_OBJECT: + p = new line_object(startpos, endpos, v, nsegments); + break; + default: + assert(0); + } + have_last_line = 1; + last_line = endpos - startpos; + *curpos = endpos; + return p; +} + +class arc_object : public linear_object { + int clockwise; + position cent; + double rad; +public: + arc_object(int, const position &, const position &, const position &); + position origin() { return cent; } + position center() { return cent; } + double radius() { return rad; } + position north(); + position south(); + position east(); + position west(); + position north_east(); + position north_west(); + position south_east(); + position south_west(); + void update_bounding_box(bounding_box *); + object_type type() { return ARC_OBJECT; } + void print(); + void move_by(const position &pos); +}; + +arc_object::arc_object(int cw, const position &s, const position &e, + const position &c) +: linear_object(s, e), clockwise(cw), cent(c) +{ + rad = hypot(c - s); +} + +void arc_object::move_by(const position &pos) +{ + linear_object::move_by(pos); + cent += pos; +} + +// we get arc corners from the corresponding circle + +position arc_object::north() +{ + position result(cent); + result.y += rad; + return result; +} + +position arc_object::south() +{ + position result(cent); + result.y -= rad; + return result; +} + +position arc_object::east() +{ + position result(cent); + result.x += rad; + return result; +} + +position arc_object::west() +{ + position result(cent); + result.x -= rad; + return result; +} + +position arc_object::north_east() +{ + position result(cent); + result.x += rad/M_SQRT2; + result.y += rad/M_SQRT2; + return result; +} + +position arc_object::north_west() +{ + position result(cent); + result.x -= rad/M_SQRT2; + result.y += rad/M_SQRT2; + return result; +} + +position arc_object::south_east() +{ + position result(cent); + result.x += rad/M_SQRT2; + result.y -= rad/M_SQRT2; + return result; +} + +position arc_object::south_west() +{ + position result(cent); + result.x -= rad/M_SQRT2; + result.y -= rad/M_SQRT2; + return result; +} + + +void arc_object::print() +{ + if (lt.type == line_type::invisible) + return; + if (clockwise) + out->arc(en, cent, strt, lt); + else + out->arc(strt, cent, en, lt); + if (arrow_at_start) { + position c = cent - strt; + draw_arrow(strt, + (clockwise ? position(c.y, -c.x) : position(-c.y, c.x)), + aht, lt); + } + if (arrow_at_end) { + position e = en - cent; + draw_arrow(en, + (clockwise ? position(e.y, -e.x) : position(-e.y, e.x)), + aht, lt); + } +} + +inline double max(double a, double b) +{ + return a > b ? a : b; +} + +void arc_object::update_bounding_box(bounding_box *p) +{ + p->encompass(strt); + p->encompass(en); + position start_offset = strt - cent; + if (start_offset.x == 0.0 && start_offset.y == 0.0) + return; + position end_offset = en - cent; + if (end_offset.x == 0.0 && end_offset.y == 0.0) + return; + double start_quad = atan2(start_offset.y, start_offset.x)/(M_PI/2.0); + double end_quad = atan2(end_offset.y, end_offset.x)/(M_PI/2.0); + if (clockwise) { + double temp = start_quad; + start_quad = end_quad; + end_quad = temp; + } + if (start_quad < 0.0) + start_quad += 4.0; + while (end_quad <= start_quad) + end_quad += 4.0; + double radius = max(hypot(start_offset), hypot(end_offset)); + for (int q = int(start_quad) + 1; q < end_quad; q++) { + position offset; + switch (q % 4) { + case 0: + offset.x = radius; + break; + case 1: + offset.y = radius; + break; + case 2: + offset.x = -radius; + break; + case 3: + offset.y = -radius; + break; + } + p->encompass(cent + offset); + } +} + +// We ignore the with attribute. The at attribute always refers to the center. + +linear_object *object_spec::make_arc(position *curpos, direction *dirp) +{ + *dirp = dir; + int cw = (flags & IS_CLOCKWISE) != 0; + // compute the start + position startpos; + if (flags & HAS_FROM) + startpos = from; + else + startpos = *curpos; + if (!(flags & HAS_RADIUS)) + lookup_variable("arcrad", &radius); + // compute the end + position endpos; + if (flags & HAS_TO) + endpos = to; + else { + position m(radius, radius); + // Adjust the signs. + if (cw) { + if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION) + m.x = -m.x; + if (dir == DOWN_DIRECTION || dir == RIGHT_DIRECTION) + m.y = -m.y; + *dirp = direction((dir + 3) % 4); + } + else { + if (dir == UP_DIRECTION || dir == LEFT_DIRECTION) + m.x = -m.x; + if (dir == DOWN_DIRECTION || dir == LEFT_DIRECTION) + m.y = -m.y; + *dirp = direction((dir + 1) % 4); + } + endpos = startpos + m; + } + // compute the center + position centerpos; + if (flags & HAS_AT) + centerpos = at; + else if (startpos == endpos) + centerpos = startpos; + else { + position h = (endpos - startpos)/2.0; + double d = hypot(h); + if (radius <= 0) + radius = .25; + // make the radius big enough + while (radius < d) + radius *= 2.0; + double alpha = acos(d/radius); + double theta = atan2(h.y, h.x); + if (cw) + theta -= alpha; + else + theta += alpha; + centerpos = position(cos(theta), sin(theta))*radius + startpos; + } + arc_object *p = new arc_object(cw, startpos, endpos, centerpos); + *curpos = endpos; + return p; +} + +graphic_object *object_spec::make_linear(position *curpos, direction *dirp) +{ + linear_object *obj; + if (type == ARC_OBJECT) + obj = make_arc(curpos, dirp); + else + obj = make_line(curpos, dirp); + if (type == ARROW_OBJECT + && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD)) == 0) + flags |= HAS_RIGHT_ARROW_HEAD; + if (obj && (flags & (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD))) { + arrow_head_type a; + int at_start = (flags & HAS_LEFT_ARROW_HEAD) != 0; + int at_end = (flags & HAS_RIGHT_ARROW_HEAD) != 0; + if (flags & HAS_HEIGHT) + a.height = height; + else + lookup_variable("arrowht", &a.height); + if (flags & HAS_WIDTH) + a.width = width; + else + lookup_variable("arrowwid", &a.width); + double solid; + lookup_variable("arrowhead", &solid); + a.solid = solid != 0.0; + obj->add_arrows(at_start, at_end, a); + } + return obj; +} + +object *object_spec::make_object(position *curpos, direction *dirp) +{ + graphic_object *obj = 0; + switch (type) { + case BLOCK_OBJECT: + obj = make_block(curpos, dirp); + break; + case BOX_OBJECT: + obj = make_box(curpos, dirp); + break; + case TEXT_OBJECT: + obj = make_text(curpos, dirp); + break; + case ELLIPSE_OBJECT: + obj = make_ellipse(curpos, dirp); + break; + case CIRCLE_OBJECT: + obj = make_circle(curpos, dirp); + break; + case MOVE_OBJECT: + obj = make_move(curpos, dirp); + break; + case ARC_OBJECT: + case LINE_OBJECT: + case SPLINE_OBJECT: + case ARROW_OBJECT: + obj = make_linear(curpos, dirp); + break; + case MARK_OBJECT: + case OTHER_OBJECT: + default: + assert(0); + break; + } + if (obj) { + if (flags & IS_INVISIBLE) + obj->set_invisible(); + if (text != 0) + obj->add_text(text, (flags & IS_ALIGNED) != 0); + if (flags & IS_DOTTED) + obj->set_dotted(dash_width); + else if (flags & IS_DASHED) + obj->set_dashed(dash_width); + double th; + if (flags & HAS_THICKNESS) + th = thickness; + else + lookup_variable("linethick", &th); + obj->set_thickness(th); + if (flags & (IS_DEFAULT_FILLED|IS_FILLED)) { + if (flags & IS_DEFAULT_FILLED) + lookup_variable("fillval", &fill); + if (fill < 0.0) + error("bad fill value %1", fill); + else + obj->set_fill(fill); + } + } + return obj; +} + +struct string_list { + string_list *next; + char *str; + string_list(char *); + ~string_list(); +}; + +string_list::string_list(char *s) +: next(0), str(s) +{ +} + +string_list::~string_list() +{ + a_delete str; +} + +/* A path is used to hold the argument to the with attribute. For example, +`.nw' or `.A.s' or `.A'. The major operation on a path is to take a +place and follow the path through the place to place within the place. +Note that `.A.B.C.sw' will work. */ + +path::path(corner c) +: label_list(0), crn(c), ypath(0) +{ +} + +path::path(char *l, corner c) +: crn(c), ypath(0) +{ + label_list = new string_list(l); +} + +path::~path() +{ + while (label_list) { + string_list *tem = label_list; + label_list = label_list->next; + delete tem; + } + delete ypath; +} + +void path::append(corner c) +{ + assert(crn == 0); + crn = c; +} + +void path::append(char *s) +{ + string_list **p; + for (p = &label_list; *p; p = &(*p)->next) + ; + *p = new string_list(s); +} + +void path::set_ypath(path *p) +{ + ypath = p; +} + +// return non-zero for success + +int path::follow(const place &pl, place *result) const +{ + const place *p = &pl; + for (string_list *lb = label_list; lb; lb = lb->next) + if (p->obj == 0 || (p = p->obj->find_label(lb->str)) == 0) { + lex_error("object does not contain a place `%1'", lb->str); + return 0; + } + if (crn == 0 || p->obj == 0) + *result = *p; + else { + position pos = ((p->obj)->*(crn))(); + result->x = pos.x; + result->y = pos.y; + result->obj = 0; + } + if (ypath) { + place tem; + if (!ypath->follow(pl, &tem)) + return 0; + result->y = tem.y; + if (result->obj != tem.obj) + result->obj = 0; + } + return 1; +} + +void print_object_list(object *p) +{ + for (; p; p = p->next) { + p->print(); + p->print_text(); + } +} + +void print_picture(object *obj) +{ + bounding_box bb; + for (object *p = obj; p; p = p->next) + p->update_bounding_box(&bb); + double scale; + lookup_variable("scale", &scale); + out->start_picture(scale, bb.ll, bb.ur); + print_object_list(obj); + out->finish_picture(); +} + diff --git a/contrib/groff/pic/object.h b/contrib/groff/pic/object.h new file mode 100644 index 000000000000..2748e81e8465 --- /dev/null +++ b/contrib/groff/pic/object.h @@ -0,0 +1,217 @@ +// -*- C++ -*- +/* 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. */ + +struct place; + +enum object_type { + OTHER_OBJECT, + BOX_OBJECT, + CIRCLE_OBJECT, + ELLIPSE_OBJECT, + ARC_OBJECT, + SPLINE_OBJECT, + LINE_OBJECT, + ARROW_OBJECT, + MOVE_OBJECT, + TEXT_OBJECT, + BLOCK_OBJECT, + MARK_OBJECT + }; + +struct bounding_box; + +struct object { + object *prev; + object *next; + object(); + virtual ~object(); + virtual position origin(); + virtual double width(); + virtual double radius(); + virtual double height(); + virtual position north(); + virtual position south(); + virtual position east(); + virtual position west(); + virtual position north_east(); + virtual position north_west(); + virtual position south_east(); + virtual position south_west(); + virtual position start(); + virtual position end(); + virtual position center(); + virtual place *find_label(const char *); + virtual void move_by(const position &); + virtual int blank(); + virtual void update_bounding_box(bounding_box *); + virtual object_type type() = 0; + virtual void print(); + virtual void print_text(); +}; + +typedef position (object::*corner)(); + +struct place { + object *obj; + double x, y; +}; + +struct string_list; + +class path { + corner crn; + string_list *label_list; + path *ypath; +public: + path(corner = 0); + path(char *, corner = 0); + ~path(); + void append(corner); + void append(char *); + void set_ypath(path *); + int follow(const place &, place *) const; +}; + +struct object_list { + object *head; + object *tail; + object_list(); + void append(object *); + void wrap_up_block(object_list *); +}; + +declare_ptable(place) + +// these go counterclockwise +enum direction { + RIGHT_DIRECTION, + UP_DIRECTION, + LEFT_DIRECTION, + DOWN_DIRECTION + }; + +struct graphics_state { + double x, y; + direction dir; +}; + +struct saved_state : public graphics_state { + saved_state *prev; + PTABLE(place) *tbl; +}; + + +struct text_item { + text_item *next; + char *text; + adjustment adj; + const char *filename; + int lineno; + + text_item(char *, const char *, int); + ~text_item(); +}; + +const unsigned long IS_DOTTED = 01; +const unsigned long IS_DASHED = 02; +const unsigned long IS_CLOCKWISE = 04; +const unsigned long IS_INVISIBLE = 020; +const unsigned long HAS_LEFT_ARROW_HEAD = 040; +const unsigned long HAS_RIGHT_ARROW_HEAD = 0100; +const unsigned long HAS_SEGMENT = 0200; +const unsigned long IS_SAME = 0400; +const unsigned long HAS_FROM = 01000; +const unsigned long HAS_AT = 02000; +const unsigned long HAS_WITH = 04000; +const unsigned long HAS_HEIGHT = 010000; +const unsigned long HAS_WIDTH = 020000; +const unsigned long HAS_RADIUS = 040000; +const unsigned long HAS_TO = 0100000; +const unsigned long IS_CHOPPED = 0200000; +const unsigned long IS_DEFAULT_CHOPPED = 0400000; +const unsigned long HAS_THICKNESS = 01000000; +const unsigned long IS_FILLED = 02000000; +const unsigned long IS_DEFAULT_FILLED = 04000000; +const unsigned long IS_ALIGNED = 010000000; + +struct segment { + int is_absolute; + position pos; + segment *next; + segment(const position &, int, segment *); +}; + +struct rectangle_object; +struct graphic_object; +struct linear_object; + +struct object_spec { + unsigned long flags; + object_type type; + object_list oblist; + PTABLE(place) *tbl; + double dash_width; + position from; + position to; + position at; + position by; + path *with; + text_item *text; + double height; + double radius; + double width; + double segment_width; + double segment_height; + double start_chop; + double end_chop; + double thickness; + double fill; + direction dir; + segment *segment_list; + position segment_pos; + int segment_is_absolute; + + object_spec(object_type); + ~object_spec(); + object *make_object(position *, direction *); + graphic_object *make_box(position *, direction *); + graphic_object *make_block(position *, direction *); + graphic_object *make_text(position *, direction *); + graphic_object *make_ellipse(position *, direction *); + graphic_object *make_circle(position *, direction *); + linear_object *make_line(position *, direction *); + linear_object *make_arc(position *, direction *); + graphic_object *make_linear(position *, direction *); + graphic_object *make_move(position *, direction *); + int position_rectangle(rectangle_object *p, position *curpos, + direction *dirp); +}; + + +object *make_object(object_spec *, position *, direction *); + +object *make_mark_object(); +object *make_command_object(char *, const char *, int); + +int lookup_variable(const char *name, double *val); +void define_variable(const char *name, double val); + +void print_picture(object *); + diff --git a/contrib/groff/pic/output.h b/contrib/groff/pic/output.h new file mode 100644 index 000000000000..ac490db463e3 --- /dev/null +++ b/contrib/groff/pic/output.h @@ -0,0 +1,79 @@ +// -*- C++ -*- +/* 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. */ + +struct line_type { + enum { invisible, solid, dotted, dashed } type; + double dash_width; + double thickness; // the thickness is in points + + line_type(); +}; + + +class output { +protected: + char *args; + double desired_height; // zero if no height specified + double desired_width; // zero if no depth specified + double compute_scale(double, const position &, const position &); +public: + output(); + virtual ~output(); + void set_desired_width_height(double wid, double ht); + void set_args(const char *); + virtual void start_picture(double sc, const position &ll, const position &ur) = 0; + virtual void finish_picture() = 0; + virtual void circle(const position &, double rad, + const line_type &, double) = 0; + virtual void text(const position &, text_piece *, int, double) = 0; + virtual void line(const position &, const position *, int n, + const line_type &) = 0; + virtual void polygon(const position *, int n, + const line_type &, double) = 0; + virtual void spline(const position &, const position *, int n, + const line_type &) = 0; + virtual void arc(const position &, const position &, const position &, + const line_type &) = 0; + virtual void ellipse(const position &, const distance &, + const line_type &, double) = 0; + virtual void rounded_box(const position &, const distance &, double, + const line_type &, double) = 0; + virtual void command(const char *, const char *, int); + virtual void set_location(const char *, int); + virtual int supports_filled_polygons(); + virtual void begin_block(const position &ll, const position &ur); + virtual void end_block(); +}; + +extern output *out; + +/* #define FIG_SUPPORT 1 */ +#define TEX_SUPPORT 1 + +output *make_troff_output(); + +#ifdef TEX_SUPPORT +output *make_tex_output(); +output *make_tpic_output(); +#endif /* TEX_SUPPORT */ + +#ifdef FIG_SUPPORT +output *make_fig_output(); +#endif /* FIG_SUPPORT */ diff --git a/contrib/groff/pic/pic.cc b/contrib/groff/pic/pic.cc new file mode 100644 index 000000000000..9e9e9f1ecf5f --- /dev/null +++ b/contrib/groff/pic/pic.cc @@ -0,0 +1,5283 @@ +#if defined(__STDC__) || defined(__cplusplus) +#define YYCONST const +#define YYPARAMS(x) x +#define YYDEFUN(name, arglist, args) name(args) +#define YYAND , +#define YYPTR void * +#else +#define YYCONST +#define YYPARAMS(x) () +#define YYDEFUN(name, arglist, args) name arglist args; +#define YYAND ; +#define YYPTR char * +#endif +#ifndef lint +YYCONST static char yysccsid[] = "@(#)yaccpar 1.8 (Berkeley +Cygnus.28) 01/20/91"; +#endif +#define YYBYACC 1 +#ifndef YYDONT_INCLUDE_STDIO +#include <stdio.h> +#endif +#ifdef __cplusplus +#include <stdlib.h> /* for malloc/realloc/free */ +#endif +#line 20 "pic.y" +#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(); + +#undef fmod +#undef rand + +extern "C" { + double fmod(double, double); + 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); + +#line 73 "pic.y" +typedef 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; +} YYSTYPE; +#line 95 "y.tab.c" +#define LABEL 257 +#define VARIABLE 258 +#define NUMBER 259 +#define TEXT 260 +#define COMMAND_LINE 261 +#define DELIMITED 262 +#define ORDINAL 263 +#define TH 264 +#define LEFT_ARROW_HEAD 265 +#define RIGHT_ARROW_HEAD 266 +#define DOUBLE_ARROW_HEAD 267 +#define LAST 268 +#define UP 269 +#define DOWN 270 +#define LEFT 271 +#define RIGHT 272 +#define BOX 273 +#define CIRCLE 274 +#define ELLIPSE 275 +#define ARC 276 +#define LINE 277 +#define ARROW 278 +#define MOVE 279 +#define SPLINE 280 +#define HEIGHT 281 +#define RADIUS 282 +#define WIDTH 283 +#define DIAMETER 284 +#define FROM 285 +#define TO 286 +#define AT 287 +#define WITH 288 +#define BY 289 +#define THEN 290 +#define DOTTED 291 +#define DASHED 292 +#define CHOP 293 +#define SAME 294 +#define INVISIBLE 295 +#define LJUST 296 +#define RJUST 297 +#define ABOVE 298 +#define BELOW 299 +#define OF 300 +#define THE 301 +#define WAY 302 +#define BETWEEN 303 +#define AND 304 +#define HERE 305 +#define DOT_N 306 +#define DOT_E 307 +#define DOT_W 308 +#define DOT_S 309 +#define DOT_NE 310 +#define DOT_SE 311 +#define DOT_NW 312 +#define DOT_SW 313 +#define DOT_C 314 +#define DOT_START 315 +#define DOT_END 316 +#define DOT_X 317 +#define DOT_Y 318 +#define DOT_HT 319 +#define DOT_WID 320 +#define DOT_RAD 321 +#define SIN 322 +#define COS 323 +#define ATAN2 324 +#define LOG 325 +#define EXP 326 +#define SQRT 327 +#define K_MAX 328 +#define K_MIN 329 +#define INT 330 +#define RAND 331 +#define COPY 332 +#define THRU 333 +#define TOP 334 +#define BOTTOM 335 +#define UPPER 336 +#define LOWER 337 +#define SH 338 +#define PRINT 339 +#define CW 340 +#define CCW 341 +#define FOR 342 +#define DO 343 +#define IF 344 +#define ELSE 345 +#define ANDAND 346 +#define OROR 347 +#define NOTEQUAL 348 +#define EQUALEQUAL 349 +#define LESSEQUAL 350 +#define GREATEREQUAL 351 +#define LEFT_CORNER 352 +#define RIGHT_CORNER 353 +#define CENTER 354 +#define END 355 +#define START 356 +#define RESET 357 +#define UNTIL 358 +#define PLOT 359 +#define THICKNESS 360 +#define FILL 361 +#define ALIGNED 362 +#define SPRINTF 363 +#define COMMAND 364 +#define DEFINE 365 +#define UNDEF 366 +#define YYERRCODE 256 +static YYCONST short yylhs[] = { -1, + 0, 0, 16, 17, 17, 28, 28, 29, 29, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 31, 30, + 30, 32, 33, 30, 34, 35, 30, 36, 30, 30, + 37, 30, 30, 30, 38, 38, 38, 26, 26, 27, + 27, 27, 39, 7, 23, 23, 2, 2, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, + 15, 15, 15, 15, 40, 42, 15, 15, 41, 41, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 43, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 18, 18, 25, 25, 24, 24, 19, 19, + 6, 6, 6, 6, 6, 6, 44, 44, 5, 5, + 13, 13, 13, 13, 13, 14, 14, 14, 22, 22, + 21, 21, 8, 8, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 11, 11, 12, 12, 12, 10, 10, + 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, +}; +static YYCONST short yylen[] = { 2, + 1, 1, 3, 1, 3, 0, 1, 1, 2, 3, + 4, 1, 1, 1, 1, 1, 2, 2, 0, 3, + 2, 0, 0, 7, 0, 0, 6, 0, 10, 1, + 0, 4, 1, 1, 2, 2, 3, 1, 2, 1, + 1, 1, 0, 5, 0, 2, 1, 1, 3, 3, + 3, 3, 3, 3, 3, 3, 2, 0, 2, 3, + 1, 4, 4, 4, 0, 0, 6, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 3, 0, 4, 3, 3, 3, 3, 2, 2, 3, + 2, 3, 2, 3, 2, 3, 3, 3, 3, 3, + 3, 2, 2, 3, 2, 3, 2, 3, 2, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 3, 2, 1, 5, 0, 3, 1, 1, + 1, 3, 3, 5, 5, 6, 1, 4, 3, 3, + 1, 2, 2, 3, 1, 1, 1, 3, 1, 3, + 1, 2, 2, 2, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 2, 3, 1, 1, 2, 1, 5, + 4, 3, 3, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 1, 1, 2, 2, 2, 2, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, + 3, 3, 3, 3, 3, 2, 3, 4, 4, 6, + 4, 4, 4, 6, 6, 4, 4, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 2, +}; +static YYCONST short yydefred[] = { 0, + 8, 0, 2, 0, 0, 0, 0, 125, 16, 12, + 13, 14, 15, 71, 72, 73, 74, 75, 76, 77, + 78, 0, 19, 0, 0, 0, 0, 0, 0, 0, + 65, 82, 0, 4, 0, 0, 79, 68, 0, 9, + 0, 0, 0, 0, 25, 0, 146, 203, 204, 149, + 151, 188, 189, 145, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 186, 187, 0, 0, 194, + 195, 200, 202, 201, 0, 0, 0, 0, 0, 131, + 129, 147, 0, 0, 0, 0, 0, 0, 41, 0, + 38, 0, 0, 0, 0, 0, 0, 0, 0, 35, + 0, 0, 0, 0, 0, 31, 3, 0, 113, 114, + 115, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 102, 0, 0, 0, 111, 112, + 119, 120, 121, 122, 116, 117, 0, 0, 124, 0, + 118, 36, 0, 0, 10, 0, 22, 0, 20, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 190, + 192, 196, 198, 191, 193, 197, 199, 0, 0, 0, + 0, 0, 0, 0, 0, 137, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 205, 206, 207, 208, 209, 0, + 142, 0, 0, 163, 155, 156, 157, 158, 159, 160, + 161, 0, 154, 152, 153, 39, 0, 0, 57, 0, + 0, 0, 43, 0, 0, 0, 0, 81, 127, 0, + 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 166, 100, 0, 169, 0, 0, 101, 0, 0, + 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, + 62, 0, 11, 0, 26, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 228, 0, 217, 140, 0, 150, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 148, + 132, 133, 162, 0, 0, 53, 0, 0, 0, 0, + 0, 51, 0, 0, 50, 49, 0, 66, 83, 32, + 174, 0, 0, 0, 0, 164, 0, 168, 0, 0, + 23, 0, 218, 219, 0, 221, 222, 223, 0, 0, + 226, 227, 0, 0, 0, 0, 0, 44, 0, 126, + 0, 0, 173, 172, 0, 165, 0, 0, 27, 0, + 0, 0, 134, 138, 0, 0, 0, 0, 70, 67, + 171, 0, 24, 46, 220, 224, 225, 136, 0, 0, + 170, 0, 0, 28, 0, 0, 29, +}; +static YYCONST short yydgoto[] = { 2, + 105, 179, 107, 400, 90, 91, 33, 92, 93, 263, + 264, 265, 108, 95, 34, 3, 35, 36, 96, 223, + 97, 98, 379, 337, 109, 100, 101, 241, 5, 38, + 46, 284, 377, 158, 352, 406, 243, 39, 330, 114, + 390, 371, 115, 202, +}; +static YYCONST short yysindex[] = { -52, + 0, 0, 0, 5205, -46, 7, -12, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -249, 0,10894, -198,11035, -186,11441, 51,10894, + 0, 0, -251, 0, -52,10595, 0, 0, -42, 0, + -52,11035, 35, -236, 0, -145, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 79, 80, 85, 87, 91, + 94, 98, 101, 102, 107, 0, 0, -126, -67, 0, + 0, 0, 0, 0,11136,11035,11441,11441, 1187, 0, + 0, 0, -71, -250, 2230, -10, 575, 426, 0,10894, + 0, 71,11035,11035, 1220, -141, -305, -250, -291, 0, + -28, -101,10894, -52, -52, 0, 0, 9974, 0, 0, + 0,11746,11746,11746,11746,11441,11441,11441,11441,11542, +11542,11542, 4851,11645, 0,11746,11746,11746, 0, 0, + 0, 0, 0, 0, 0, 0,11441,11746, 0, 1647, + 0, 0, -98,10233, 0,11035, 0, -100, 0,11035, +11035,11035,11035,11035,11035,11035,11035,11035,10736, 0, + 0, 0, 0, 0, 0, 0, 0, 1626, 141, 146, + 42, -73, 99, 99, -105, 0,11441,11441,11441,11441, +11441,11441,11441,11542,11441,11441,11441,11441,11441,11441, +11441,11542, -18, 152, 0, 0, 0, 0, 0, -56, + 0,11645,11645, 0, 0, 0, 0, 0, 0, 0, + 0, 120, 0, 0, 0, 0,11441, 99, 0,11035, +11035,11441, 0,11035,11035, -242, -242, 0, 0, 89, + 5205, 125, -41, 0, 1647, 1647, 1647, 1647, 1647, 1647, + 1647, 1647, 1187, -10, -10, -10, 2121, 455, 575, 2121, + -33, 0, 0, 2134, 0,11237, 781, 0, 1647, 1647, + 1647, 1647, 1647, 0, 7, -12, 0, 0, 0, -250, + 0, -10, 0, -32, 0, 202, 203, 189, 207, 208, + 210, 209, 217, 235, 0, 243, 0, 0,11542, 0, + -1, 1117, 1180, 739, 739, 357, 357, 1647, -21, 192, + 357, 46, 46, 99, 99, 99, 99, -35, 152, 0, + 0, 0, 0, 1076, 1117, 0, 1659, -44, 357, 47, + 1117, 0, 1659, -44, 0, 0, 10, 0, 0, 0, + 0, 575, 2121, 2121, 264, 0, 67, 0, 1208, 146, + 0, -27, 0, 0,11035, 0, 0, 0,11035,11035, + 0, 0, 2, 13,11542,11542,11441, 0,11441, 0, + 5205, 2121, 0, 0, 2121, 0, -27, 65, 0, 285, + 292, 293, 0, 0, -14, -10, 1619, 1647, 0, 0, + 0, 299, 0, 0, 0, 0, 0, 0,11340, 1, + 0,11441, 1647, 0, 1647, 86, 0, +}; +static YYCONST short yyrindex[] = { 20, + 0, 0, 0, 347, 150, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 23, 0, 0, 0, + 0, 0, 59, 0, 109, 212, 0, 0, 268, 0, +10487, 0, 0, 287, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8932, 0, + 0, 0, 0, 4221, 8476, 9124, 0, 0, 0, 589, + 0, 0, 0, 0, 181, 0, 721, 0, 0, 0, +10102, 0, 615, 5629, 5629, 0, 0, 122, 0, 0, + 0, 9441, 9481, 9223, 9331, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 9580, 9690, 9789, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 9829, 0, 4977, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 308, 0, 213, + 0, 0, 270, 602, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2904, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8437, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 5084, 5401, 5508, 5825, 5932, 6249, + 6356, 6673, 0, 6780, 7097, 7204, 0, 0, 0, 0, + 0, 0, 0, 8782, 0, 0, 0, 0, 7521, 7628, + 7945, 8052, 8369, 0,10163, 2065, 135, 1861, 36, 591, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 3782, 4114, 3236, 3343, 2026, 2358, 4660, 8825, 0, + 2465, 1587, 1919, 709, 1041, 1148, 1480, 0, 3675, 0, + 0, 0, 0, 0, 390, 0, 8929, 179, 2797, 0, + 92, 0, 614, 720, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 308, 0, + 0, 652, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 679, 0, 0, 0, 0, 0, 652, 0, 0, 0, + 0, 0, 0, 0, 0, 4553, 8, 11, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 12, 0, 14, 0, 0, +}; +static YYCONST short yygindex[] = { 0, + -24, 627, -77, 0, -57, 196, 0, 0, -5, 0, + 0, 265, 1084, -88, -117, -40, 0, 0, 134, -59, + 0, 0, -23, 0, 26, 323, -60, 3, 325, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, +}; +#define YYTABLESIZE 12102 +static YYCONST short yytable[] = { 89, + 244, 153, 4, 111, 204, 89, 1, 212, 200, 213, + 44, 150, 40, 198, 196, 200, 197, 8, 199, 6, + 198, 196, 34, 197, 86, 199, 229, 180, 212, 37, + 213, 232, 212, 195, 213, 63, 281, 117, 225, 226, + 234, 235, 383, 154, 212, 43, 213, 398, 42, 99, + 370, 128, 226, 369, 128, 99, 236, 237, 30, 102, + 178, 151, 183, 184, 41, 201, 205, 206, 207, 208, + 209, 110, 201, 240, 242, 89, 268, 86, 129, 228, + 129, 34, 200, 45, 212, 299, 213, 198, 89, 211, + 112, 52, 199, 116, 63, 156, 157, 245, 246, 247, + 248, 249, 250, 251, 252, 253, 253, 253, 6, 267, + 6, 269, 270, 271, 319, 34, 159, 30, 160, 161, + 29, 7, 272, 273, 162, 99, 163, 262, 63, 253, + 164, 227, 52, 165, 14, 52, 238, 166, 99, 201, + 167, 168, 6, 37, 170, 171, 169, 34, 233, 7, + 52, 30, 326, 328, 321, 322, 332, 334, 239, 274, + 63, 285, 302, 303, 304, 305, 306, 307, 308, 309, + 311, 312, 313, 314, 315, 316, 317, 253, 56, 37, + 47, 297, 7, 30, 52, 47, 298, 267, 267, 7, + 300, 50, 201, 14, 7, 301, 51, 210, 343, 344, + 320, 6, 324, 174, 175, 325, 327, 329, 350, 331, + 333, 61, 323, 338, 7, 152, 52, 339, 181, 56, + 340, 47, 56, 346, 47, 172, 173, 14, 203, 351, + 188, 8, 355, 6, 212, 365, 213, 56, 47, 47, + 7, 349, 353, 354, 50, 7, 7, 356, 357, 51, + 358, 262, 359, 389, 262, 131, 131, 131, 348, 14, + 360, 335, 336, 254, 255, 256, 37, 33, 366, 216, + 61, 56, 7, 47, 253, 361, 6, 6, 185, 6, + 6, 186, 372, 362, 176, 177, 21, 282, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 364, 234, 216, 56, 61, 47, 216, 375, 368, 216, + 216, 216, 216, 216, 216, 384, 216, 187, 188, 189, + 190, 191, 192, 376, 394, 395, 33, 310, 216, 216, + 378, 216, 396, 397, 29, 318, 61, 262, 262, 401, + 253, 253, 387, 404, 388, 21, 1, 407, 47, 279, + 58, 6, 113, 393, 59, 52, 60, 6, 6, 118, + 33, 6, 216, 6, 0, 216, 262, 0, 0, 262, + 0, 0, 0, 0, 403, 0, 6, 405, 6, 21, + 0, 52, 6, 6, 0, 0, 0, 0, 0, 235, + 0, 188, 33, 200, 216, 0, 37, 188, 198, 196, + 0, 197, 188, 199, 0, 0, 7, 7, 7, 7, + 7, 21, 7, 0, 0, 0, 0, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 235, 0, 363, 235, 188, 0, 0, 52, 52, 0, + 0, 0, 56, 0, 47, 0, 0, 0, 235, 0, + 201, 0, 0, 0, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 0, 0, 56, 0, + 47, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 235, 7, 7, 7, 7, 7, 7, 0, + 0, 7, 0, 7, 0, 0, 0, 0, 385, 386, + 0, 7, 7, 7, 7, 7, 7, 0, 7, 0, + 0, 0, 7, 7, 235, 0, 222, 0, 0, 0, + 0, 341, 0, 0, 345, 56, 216, 216, 216, 216, + 0, 0, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 0, 0, 0, 222, 0, 0, 0, 0, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 0, 0, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 0, 0, 18, 0, + 64, 216, 216, 216, 216, 216, 216, 216, 216, 216, + 216, 237, 0, 216, 216, 216, 216, 373, 374, 216, + 216, 0, 216, 55, 17, 216, 216, 216, 216, 216, + 216, 216, 216, 216, 216, 216, 0, 0, 0, 216, + 216, 216, 216, 130, 237, 130, 391, 0, 237, 392, + 0, 237, 237, 237, 237, 237, 237, 18, 237, 64, + 0, 45, 106, 235, 55, 0, 0, 55, 0, 0, + 237, 237, 0, 237, 0, 222, 0, 0, 155, 0, + 0, 0, 55, 17, 0, 0, 0, 0, 69, 235, + 0, 18, 0, 64, 0, 214, 0, 0, 0, 235, + 0, 0, 235, 224, 237, 0, 0, 237, 215, 216, + 217, 218, 219, 220, 0, 221, 55, 17, 212, 0, + 45, 0, 182, 18, 214, 64, 0, 0, 0, 54, + 48, 0, 342, 0, 0, 0, 237, 215, 216, 217, + 218, 219, 220, 0, 221, 235, 235, 69, 55, 17, + 0, 212, 0, 0, 45, 212, 0, 0, 212, 212, + 212, 212, 212, 212, 0, 212, 0, 0, 0, 0, + 54, 48, 0, 54, 48, 0, 0, 212, 212, 0, + 212, 69, 0, 0, 0, 200, 45, 0, 54, 48, + 198, 196, 283, 197, 0, 199, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 296, 0, 0, 232, 0, + 195, 212, 0, 69, 212, 0, 0, 0, 0, 0, + 0, 0, 54, 48, 0, 0, 0, 200, 0, 0, + 0, 0, 198, 196, 193, 197, 0, 199, 0, 0, + 0, 0, 201, 212, 214, 0, 0, 0, 0, 0, + 232, 0, 195, 0, 54, 48, 0, 215, 216, 217, + 218, 219, 220, 0, 221, 0, 0, 0, 237, 237, + 237, 237, 0, 0, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 201, 0, 0, 55, 0, 0, + 0, 0, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 0, 55, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 237, 0, 0, + 0, 0, 0, 237, 237, 237, 237, 237, 237, 237, + 237, 237, 237, 0, 0, 237, 237, 237, 237, 0, + 0, 237, 237, 0, 237, 0, 0, 237, 237, 237, + 237, 237, 237, 237, 237, 237, 237, 237, 0, 0, + 55, 237, 237, 237, 237, 212, 212, 212, 212, 0, + 0, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 380, 0, 54, 48, 381, 382, 0, 0, 212, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 54, + 48, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 0, 0, 0, 0, 0, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 213, 0, 212, 212, 212, 212, 0, 0, 212, 212, + 0, 212, 0, 0, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 0, 54, 0, 212, 212, + 212, 212, 0, 213, 0, 0, 0, 213, 0, 0, + 213, 213, 213, 213, 213, 213, 0, 213, 191, 192, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 213, + 213, 0, 213, 0, 0, 0, 0, 94, 0, 0, + 0, 0, 200, 94, 0, 0, 0, 198, 196, 0, + 197, 0, 199, 0, 0, 0, 187, 188, 189, 190, + 191, 192, 0, 213, 0, 232, 213, 195, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 214, 0, 0, + 0, 0, 0, 200, 0, 0, 0, 0, 198, 196, + 0, 197, 0, 199, 0, 213, 0, 0, 94, 201, + 0, 0, 0, 0, 0, 0, 232, 0, 195, 0, + 214, 0, 0, 94, 214, 0, 0, 214, 214, 214, + 214, 214, 214, 0, 214, 0, 94, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 214, 214, 0, 214, + 201, 0, 0, 94, 94, 94, 200, 0, 0, 0, + 0, 198, 196, 200, 197, 0, 199, 0, 198, 196, + 193, 197, 0, 199, 0, 0, 0, 280, 0, 232, + 214, 195, 0, 214, 200, 0, 194, 0, 195, 198, + 196, 193, 197, 0, 199, 0, 200, 0, 0, 0, + 0, 198, 196, 0, 197, 0, 199, 232, 0, 195, + 0, 0, 214, 201, 0, 0, 0, 94, 0, 232, + 201, 195, 0, 0, 0, 94, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 213, 213, 213, + 213, 201, 0, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 201, 0, 0, 0, 0, 0, 0, + 0, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 0, 0, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 0, 0, 0, + 0, 367, 213, 213, 213, 213, 213, 213, 213, 213, + 213, 213, 0, 0, 213, 213, 213, 213, 0, 0, + 213, 213, 94, 213, 0, 0, 213, 213, 213, 213, + 213, 213, 213, 213, 213, 213, 213, 0, 0, 0, + 213, 213, 213, 213, 214, 214, 214, 214, 0, 0, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 0, 187, 188, 189, 190, 191, 192, 0, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 94, 94, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 189, 190, 191, 192, 0, 214, + 214, 214, 214, 214, 214, 214, 214, 214, 214, 215, + 0, 214, 214, 214, 214, 0, 185, 214, 214, 186, + 214, 0, 0, 214, 214, 214, 214, 214, 214, 214, + 214, 214, 214, 214, 0, 0, 0, 214, 214, 214, + 214, 0, 215, 0, 0, 0, 215, 0, 0, 215, + 215, 215, 215, 215, 215, 187, 215, 189, 190, 191, + 192, 0, 187, 188, 189, 190, 191, 192, 215, 215, + 0, 215, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 230, 231, 189, 190, 191, 192, 0, + 0, 0, 0, 0, 0, 230, 231, 189, 190, 191, + 192, 0, 215, 0, 0, 215, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 210, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 215, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 210, + 0, 0, 0, 0, 0, 0, 210, 210, 0, 210, + 210, 210, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 210, 210, 0, 210, 0, + 0, 0, 0, 0, 0, 200, 0, 0, 0, 0, + 198, 196, 200, 197, 0, 199, 0, 198, 196, 193, + 197, 0, 199, 0, 0, 0, 0, 0, 232, 210, + 195, 0, 210, 200, 0, 194, 0, 195, 198, 196, + 0, 197, 0, 199, 0, 200, 0, 0, 0, 0, + 198, 196, 0, 197, 0, 199, 232, 0, 195, 0, + 0, 210, 201, 0, 0, 0, 0, 0, 232, 201, + 195, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 215, 215, 215, 215, + 201, 0, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 201, 0, 0, 0, 0, 0, 0, 0, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 0, 0, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 0, 0, 0, 0, + 0, 215, 215, 215, 215, 215, 215, 215, 215, 215, + 215, 0, 0, 215, 215, 215, 215, 0, 0, 215, + 215, 0, 215, 0, 0, 215, 215, 215, 215, 215, + 215, 215, 215, 215, 215, 215, 0, 0, 0, 215, + 215, 215, 215, 210, 210, 210, 210, 0, 0, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 0, + 15, 0, 0, 0, 0, 0, 0, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 0, 0, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 0, 0, 0, 0, 399, 210, 210, + 210, 210, 210, 210, 210, 210, 210, 210, 211, 15, + 210, 210, 210, 210, 0, 185, 210, 210, 186, 210, + 0, 0, 210, 210, 210, 210, 210, 210, 210, 210, + 210, 210, 210, 0, 0, 0, 210, 210, 210, 210, + 0, 211, 0, 15, 0, 0, 189, 0, 211, 211, + 0, 211, 211, 211, 187, 188, 189, 190, 191, 192, + 0, 230, 231, 189, 190, 191, 192, 211, 211, 0, + 211, 0, 0, 0, 0, 15, 0, 0, 0, 0, + 0, 0, 187, 188, 189, 190, 191, 192, 0, 0, + 0, 0, 0, 0, 230, 0, 189, 190, 191, 192, + 0, 211, 0, 0, 211, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 230, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 211, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 230, 0, + 0, 0, 0, 0, 0, 230, 230, 0, 0, 230, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 230, 230, 0, 230, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 203, 0, 0, 0, 0, 203, 203, 203, 203, + 0, 203, 0, 0, 0, 0, 0, 189, 230, 0, + 0, 230, 0, 189, 203, 0, 203, 0, 189, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 230, 0, 0, 0, 0, 0, 0, 0, 203, 0, + 189, 0, 0, 0, 0, 0, 261, 0, 0, 0, + 0, 0, 0, 0, 0, 211, 211, 211, 211, 347, + 0, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 211, 0, 0, 0, 0, 0, 0, 0, 0, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 0, + 0, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 0, 0, 0, 0, 0, + 211, 211, 211, 211, 211, 211, 211, 211, 211, 211, + 0, 0, 211, 211, 211, 211, 0, 0, 211, 211, + 0, 211, 0, 0, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 210, 0, 0, 211, 211, + 211, 211, 230, 230, 230, 230, 0, 0, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 0, 0, + 0, 0, 0, 0, 0, 0, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 0, 0, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 0, 0, 0, 0, 0, 230, 230, 230, + 230, 230, 230, 230, 230, 230, 230, 232, 0, 230, + 230, 230, 230, 0, 203, 230, 230, 203, 230, 0, + 0, 230, 230, 230, 230, 230, 230, 230, 230, 230, + 230, 230, 0, 0, 0, 230, 230, 230, 230, 0, + 232, 52, 53, 0, 0, 0, 0, 232, 232, 0, + 0, 232, 0, 0, 52, 53, 0, 0, 0, 0, + 203, 203, 203, 203, 203, 203, 232, 232, 0, 232, + 0, 0, 0, 0, 0, 0, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 0, 0, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 232, 0, 0, 232, 76, 77, 78, 79, 0, 0, + 0, 0, 0, 0, 231, 0, 0, 76, 77, 78, + 79, 0, 80, 81, 82, 83, 84, 0, 0, 0, + 0, 0, 232, 0, 0, 80, 81, 82, 83, 84, + 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, + 0, 0, 0, 0, 231, 231, 0, 0, 231, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 231, 231, 0, 231, 0, 0, 0, + 0, 0, 0, 0, 0, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, + 231, 0, 0, 76, 77, 78, 79, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 80, 81, 82, 83, 84, 0, 0, 0, 231, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 232, 232, 232, 232, 0, 0, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 0, 0, 0, 0, 0, 0, 0, 0, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 0, 0, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 0, 0, 0, 0, 0, 232, + 232, 232, 232, 232, 232, 232, 232, 232, 232, 0, + 0, 232, 232, 232, 232, 0, 0, 232, 232, 0, + 232, 0, 0, 232, 232, 232, 232, 232, 232, 232, + 232, 232, 232, 232, 0, 0, 0, 232, 232, 232, + 232, 231, 231, 231, 231, 0, 0, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 0, 0, 0, + 0, 0, 0, 0, 0, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 0, 0, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 231, 0, 0, 0, 0, 0, 231, 231, 231, 231, + 231, 231, 231, 231, 231, 231, 229, 0, 231, 231, + 231, 231, 0, 0, 231, 231, 0, 231, 0, 0, + 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, + 231, 0, 0, 0, 231, 231, 231, 231, 0, 229, + 0, 0, 0, 0, 0, 0, 229, 229, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 229, 229, 0, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, + 0, 0, 229, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 143, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 229, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 143, 0, 0, 0, + 0, 0, 0, 143, 143, 0, 143, 143, 143, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 143, 0, 0, 143, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 143, 0, 0, 143, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 143, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 229, 229, 229, 229, 0, 0, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 0, + 0, 0, 0, 0, 0, 0, 0, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 0, 0, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 0, 0, 0, 0, 0, 229, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 0, 0, + 229, 229, 229, 229, 0, 0, 229, 229, 0, 229, + 0, 0, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 229, 229, 0, 0, 0, 229, 229, 229, 229, + 143, 143, 143, 143, 0, 0, 143, 0, 143, 143, + 143, 143, 143, 143, 143, 143, 0, 0, 0, 0, + 0, 0, 0, 0, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 0, 0, 0, 0, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, + 143, 143, 143, 143, 143, 234, 0, 143, 143, 143, + 143, 0, 0, 143, 143, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 143, 143, 143, 143, 143, + 0, 0, 0, 143, 143, 143, 143, 0, 234, 0, + 0, 0, 0, 0, 0, 234, 234, 0, 0, 234, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 234, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 234, 0, + 0, 234, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 233, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 234, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, + 0, 0, 233, 233, 0, 0, 233, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 233, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 233, 0, 0, 233, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 234, 234, 234, 234, 0, 0, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 0, 0, + 0, 0, 0, 0, 0, 0, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 0, 0, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, + 234, 234, 0, 0, 0, 0, 0, 234, 234, 234, + 234, 234, 234, 234, 234, 234, 234, 0, 0, 234, + 234, 234, 234, 0, 0, 234, 234, 0, 234, 0, + 0, 234, 234, 234, 234, 0, 0, 234, 234, 234, + 234, 234, 0, 0, 0, 234, 234, 234, 234, 233, + 233, 233, 233, 0, 0, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 0, 0, 0, 0, 0, + 0, 0, 0, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 0, 0, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 233, 233, 233, 233, 233, 0, + 0, 0, 0, 0, 233, 233, 233, 233, 233, 233, + 233, 233, 233, 233, 144, 0, 233, 233, 233, 233, + 0, 0, 233, 233, 0, 233, 0, 0, 233, 233, + 233, 233, 0, 0, 233, 233, 233, 233, 233, 0, + 0, 0, 233, 233, 233, 233, 0, 144, 0, 0, + 0, 0, 0, 0, 144, 144, 0, 144, 144, 144, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 144, 0, 0, 144, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 144, 0, 0, + 144, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 235, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 144, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 235, 0, 0, 0, 0, 0, + 0, 235, 235, 0, 0, 235, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 235, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 235, 0, 0, 235, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 235, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 144, 144, 144, 144, 0, 0, 144, 0, 144, + 144, 144, 144, 144, 144, 144, 144, 0, 0, 0, + 0, 0, 0, 0, 0, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 0, 0, 0, 0, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, + 144, 144, 144, 144, 144, 144, 0, 0, 144, 144, + 144, 144, 0, 0, 144, 144, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 144, 144, 144, 144, + 144, 0, 0, 0, 144, 144, 144, 144, 235, 235, + 235, 235, 0, 0, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 0, 0, 0, 0, 0, 0, + 0, 0, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 0, 0, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 235, 0, 0, + 0, 0, 0, 235, 235, 235, 235, 235, 235, 235, + 235, 235, 235, 236, 0, 235, 235, 235, 235, 0, + 0, 235, 235, 0, 235, 0, 0, 235, 235, 0, + 0, 0, 0, 235, 235, 235, 235, 235, 0, 0, + 0, 235, 235, 235, 235, 0, 236, 0, 0, 0, + 0, 0, 0, 236, 236, 0, 0, 236, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 236, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 236, 0, 0, 236, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 236, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 0, 0, 0, 0, 0, 0, + 130, 130, 0, 130, 130, 130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 130, + 0, 0, 130, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 130, 0, 0, 130, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 130, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 236, 236, 236, 236, 0, 0, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 0, 0, 0, 0, + 0, 0, 0, 0, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 0, 0, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, + 0, 0, 0, 0, 0, 236, 236, 236, 236, 236, + 236, 236, 236, 236, 236, 0, 0, 236, 236, 236, + 236, 0, 0, 236, 236, 0, 236, 0, 0, 0, + 236, 0, 0, 0, 0, 236, 236, 236, 236, 236, + 0, 0, 0, 236, 236, 236, 236, 130, 130, 130, + 130, 0, 0, 130, 0, 130, 130, 130, 130, 130, + 130, 130, 130, 0, 0, 0, 0, 0, 0, 0, + 0, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, + 0, 0, 0, 0, 130, 130, 130, 130, 130, 130, + 130, 130, 130, 130, 130, 130, 130, 0, 0, 0, + 0, 0, 130, 130, 130, 130, 130, 130, 130, 130, + 130, 130, 135, 0, 130, 130, 130, 130, 0, 0, + 130, 130, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 130, 130, 130, 130, 130, 0, 0, 0, + 130, 130, 130, 130, 0, 135, 0, 0, 0, 0, + 0, 0, 135, 135, 0, 0, 135, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 135, 0, 0, 135, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 135, 0, 0, 135, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 139, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 135, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 139, 0, 0, 0, 0, 0, 0, 139, + 139, 0, 0, 139, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 139, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 139, 0, 0, 139, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 139, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 135, + 135, 135, 135, 0, 0, 135, 0, 135, 135, 135, + 135, 135, 135, 135, 135, 0, 0, 0, 0, 0, + 0, 0, 0, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 0, 0, 0, 0, 135, 135, 135, 135, + 135, 135, 135, 135, 135, 135, 135, 135, 135, 0, + 0, 0, 0, 0, 135, 135, 135, 135, 135, 135, + 135, 135, 135, 135, 0, 0, 135, 135, 135, 135, + 260, 0, 135, 135, 0, 0, 261, 0, 0, 0, + 0, 0, 0, 0, 135, 135, 135, 135, 135, 0, + 0, 0, 135, 135, 135, 135, 139, 139, 139, 139, + 0, 0, 139, 0, 139, 139, 139, 139, 139, 139, + 139, 139, 0, 0, 0, 0, 0, 0, 0, 0, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 139, 139, 139, 0, + 0, 0, 0, 139, 139, 139, 139, 139, 139, 139, + 139, 139, 139, 139, 139, 139, 88, 0, 0, 0, + 0, 139, 139, 139, 139, 139, 139, 139, 139, 139, + 139, 0, 0, 139, 139, 139, 139, 0, 0, 139, + 139, 0, 0, 0, 0, 0, 0, 0, 0, 88, + 0, 139, 139, 139, 139, 139, 88, 0, 0, 139, + 139, 139, 139, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 88, + 0, 0, 88, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 90, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 88, 0, 0, 0, 0, 0, 257, 0, 0, + 0, 0, 0, 258, 0, 0, 90, 0, 259, 0, + 0, 52, 53, 90, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 90, 0, 0, 90, + 0, 0, 0, 0, 76, 77, 78, 79, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 80, 81, 82, 83, 84, 0, 90, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 88, 88, 88, 88, 0, 0, 88, + 0, 88, 88, 88, 88, 88, 88, 88, 88, 0, + 0, 0, 0, 0, 0, 0, 0, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 88, 88, 88, 0, 0, 0, 0, + 0, 88, 88, 88, 88, 88, 88, 88, 88, 88, + 88, 88, 88, 0, 0, 32, 0, 0, 88, 88, + 88, 88, 88, 88, 88, 88, 88, 88, 0, 0, + 88, 88, 88, 88, 0, 0, 88, 88, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 88, 88, + 88, 88, 88, 0, 0, 0, 88, 88, 88, 88, + 90, 90, 90, 90, 0, 0, 90, 0, 90, 90, + 90, 90, 90, 90, 90, 90, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 0, 0, 0, 0, 0, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 92, 0, 0, 0, 0, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 0, 0, 90, 90, 90, + 90, 0, 0, 90, 90, 0, 0, 0, 0, 0, + 0, 0, 0, 92, 0, 90, 90, 90, 90, 90, + 92, 0, 0, 90, 90, 90, 90, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 92, + 0, 6, 7, 0, 8, 9, 0, 0, 0, 0, + 0, 0, 0, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 0, 0, 0, 0, 0, + 0, 0, 0, 92, 0, 0, 92, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 92, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, + 96, 0, 23, 24, 0, 0, 25, 96, 26, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 27, 0, 28, 0, 0, 96, 29, 30, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 96, 0, 0, 96, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 92, 92, 92, + 92, 0, 0, 92, 0, 92, 92, 92, 92, 92, + 92, 92, 92, 0, 0, 0, 0, 0, 0, 0, + 0, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, + 0, 0, 0, 0, 0, 92, 92, 92, 92, 92, + 92, 92, 92, 92, 92, 92, 92, 0, 0, 6, + 0, 0, 92, 92, 92, 92, 92, 92, 92, 92, + 92, 92, 0, 0, 92, 92, 92, 92, 0, 0, + 92, 92, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 92, 92, 92, 92, 92, 0, 0, 0, + 92, 92, 92, 92, 96, 96, 96, 96, 0, 0, + 96, 0, 96, 96, 96, 96, 96, 96, 96, 96, + 0, 0, 0, 0, 0, 0, 0, 0, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 96, 96, 96, 0, 0, 0, + 0, 0, 96, 96, 96, 96, 96, 96, 96, 96, + 96, 96, 96, 96, 94, 0, 0, 0, 0, 96, + 96, 96, 96, 96, 96, 96, 96, 96, 96, 0, + 0, 96, 96, 96, 96, 0, 0, 96, 96, 0, + 0, 0, 0, 0, 0, 0, 0, 94, 0, 96, + 96, 96, 96, 96, 94, 0, 0, 96, 96, 96, + 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 94, 0, 6, 6, 0, 6, 6, + 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, + 0, 0, 0, 0, 0, 0, 0, 94, 0, 0, + 94, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 84, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 84, 0, 6, 6, 0, 0, + 6, 84, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 6, 0, 6, 0, 0, + 84, 6, 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 84, 0, 0, 84, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 84, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 94, 94, 94, 94, 0, 0, 94, 0, 94, + 94, 94, 94, 94, 94, 94, 94, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 0, 0, 0, 0, 0, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 0, 0, 0, 0, 0, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 0, 0, 94, 94, + 94, 94, 0, 0, 94, 94, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 94, 94, 94, 94, + 94, 0, 0, 0, 94, 94, 94, 94, 84, 84, + 84, 84, 0, 0, 84, 0, 84, 84, 84, 84, + 84, 84, 84, 84, 0, 0, 0, 0, 0, 0, + 0, 0, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 84, 84, + 84, 0, 0, 0, 0, 0, 84, 84, 84, 84, + 84, 84, 84, 84, 84, 84, 84, 84, 85, 0, + 0, 0, 0, 84, 84, 84, 84, 84, 84, 84, + 84, 84, 84, 0, 0, 84, 84, 84, 84, 0, + 0, 84, 84, 0, 0, 0, 0, 0, 0, 0, + 0, 85, 0, 84, 84, 84, 84, 84, 85, 0, + 0, 84, 84, 84, 84, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 85, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 85, 0, 0, 85, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 85, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, + 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 86, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 86, 0, + 0, 86, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 85, 85, 85, 85, 0, + 0, 85, 0, 85, 85, 85, 85, 85, 85, 85, + 85, 0, 0, 0, 0, 0, 0, 0, 0, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 0, 0, + 0, 0, 0, 85, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 0, 0, 0, 0, 0, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 0, 0, 85, 85, 85, 85, 0, 0, 85, 85, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 85, 85, 85, 85, 85, 0, 0, 0, 85, 85, + 85, 85, 86, 86, 86, 86, 0, 0, 86, 0, + 86, 86, 86, 86, 86, 86, 86, 86, 0, 0, + 0, 0, 0, 0, 0, 0, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 86, 86, 86, 0, 0, 0, 0, 0, + 86, 86, 86, 86, 86, 86, 86, 86, 86, 86, + 86, 86, 87, 0, 0, 0, 0, 86, 86, 86, + 86, 86, 86, 86, 86, 86, 86, 0, 0, 86, + 86, 86, 86, 0, 0, 86, 86, 0, 0, 0, + 0, 0, 0, 0, 0, 87, 0, 86, 86, 86, + 86, 86, 87, 0, 0, 86, 86, 86, 86, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 87, 0, 0, 87, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 97, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 97, 0, 0, 0, 0, 0, 0, 97, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 97, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 97, 0, 0, 97, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 97, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 87, + 87, 87, 87, 0, 0, 87, 0, 87, 87, 87, + 87, 87, 87, 87, 87, 0, 0, 0, 0, 0, + 0, 0, 0, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, + 87, 87, 0, 0, 0, 0, 0, 87, 87, 87, + 87, 87, 87, 87, 87, 87, 87, 87, 87, 0, + 0, 0, 0, 0, 87, 87, 87, 87, 87, 87, + 87, 87, 87, 87, 0, 0, 87, 87, 87, 87, + 0, 0, 87, 87, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 87, 87, 87, 87, 87, 0, + 0, 0, 87, 87, 87, 87, 97, 97, 97, 97, + 0, 0, 97, 0, 97, 97, 97, 97, 97, 97, + 97, 97, 0, 0, 0, 0, 0, 0, 0, 0, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 97, 97, 97, 0, + 0, 0, 0, 0, 97, 97, 97, 97, 97, 97, + 97, 97, 97, 97, 97, 97, 98, 0, 0, 0, + 0, 97, 97, 97, 97, 97, 97, 97, 97, 97, + 97, 0, 0, 97, 97, 97, 97, 0, 0, 97, + 97, 0, 0, 0, 0, 0, 0, 0, 0, 98, + 0, 97, 97, 97, 97, 97, 98, 0, 0, 97, + 97, 97, 97, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 98, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, + 0, 0, 98, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 98, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 99, 0, 0, 0, + 0, 0, 0, 99, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 99, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 99, 0, 0, 99, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 99, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 98, 98, 98, 98, 0, 0, 98, + 0, 98, 98, 98, 98, 98, 98, 98, 98, 0, + 0, 0, 0, 0, 0, 0, 0, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 98, 98, 98, 0, 0, 0, 0, + 0, 98, 98, 98, 98, 98, 98, 98, 98, 98, + 98, 98, 98, 0, 0, 0, 0, 0, 98, 98, + 98, 98, 98, 98, 98, 98, 98, 98, 0, 0, + 98, 98, 98, 98, 0, 0, 98, 98, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 98, 98, + 98, 98, 98, 0, 0, 0, 98, 98, 98, 98, + 99, 99, 99, 99, 0, 0, 99, 0, 99, 99, + 99, 99, 99, 99, 99, 99, 0, 0, 0, 0, + 0, 0, 0, 0, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 0, 0, 0, 0, 0, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, + 104, 0, 0, 0, 0, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 0, 0, 99, 99, 99, + 99, 0, 0, 99, 99, 0, 0, 0, 0, 0, + 0, 0, 0, 104, 0, 99, 99, 99, 99, 99, + 104, 0, 0, 99, 99, 99, 99, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 104, 0, 0, 104, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 106, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 104, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 0, 0, 0, 0, 0, 0, 106, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 106, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 0, 0, 106, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 104, 104, 104, + 104, 0, 0, 104, 0, 104, 104, 104, 104, 104, + 104, 104, 104, 0, 0, 0, 0, 0, 0, 0, + 0, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, + 0, 0, 0, 0, 0, 104, 104, 104, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 0, 0, 0, + 0, 0, 104, 104, 104, 104, 104, 104, 104, 104, + 104, 104, 0, 0, 104, 104, 104, 104, 0, 0, + 104, 104, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 104, 104, 104, 104, 104, 0, 0, 0, + 104, 104, 104, 104, 106, 106, 106, 106, 0, 0, + 106, 0, 106, 106, 106, 106, 106, 106, 106, 106, + 0, 0, 0, 0, 0, 0, 0, 0, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 106, 106, 106, 0, 0, 0, + 0, 0, 106, 106, 106, 106, 106, 106, 106, 106, + 106, 106, 106, 106, 110, 0, 0, 0, 0, 106, + 106, 106, 106, 106, 106, 106, 106, 106, 106, 0, + 0, 106, 106, 106, 106, 0, 0, 106, 106, 0, + 0, 0, 0, 0, 0, 0, 0, 110, 0, 106, + 106, 106, 106, 106, 110, 0, 0, 106, 106, 106, + 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 110, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 110, 0, 0, + 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 110, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, + 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 123, 0, 0, 123, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 110, 110, 110, 110, 0, 0, 110, 0, 110, + 110, 110, 110, 110, 110, 110, 110, 0, 0, 0, + 0, 0, 0, 0, 0, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 0, 0, 0, 0, 0, 110, + 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, + 110, 0, 0, 0, 0, 0, 110, 110, 110, 110, + 110, 110, 110, 110, 110, 110, 0, 0, 110, 110, + 110, 110, 0, 0, 110, 110, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 110, 110, 110, 110, + 110, 0, 0, 0, 110, 110, 110, 110, 123, 123, + 123, 123, 0, 0, 123, 0, 123, 123, 123, 123, + 123, 123, 123, 123, 0, 0, 0, 0, 0, 0, + 0, 0, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 0, 0, 0, 0, 0, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 123, 108, 0, + 0, 0, 0, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 0, 0, 123, 123, 123, 123, 0, + 0, 123, 123, 0, 0, 0, 0, 0, 0, 0, + 0, 108, 0, 123, 123, 123, 123, 123, 108, 0, + 0, 123, 123, 123, 123, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 108, 0, 0, + 0, 0, 0, 0, 0, 0, 237, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 108, 0, 0, 108, 0, 0, 0, 0, 0, + 0, 0, 0, 237, 0, 141, 0, 237, 237, 237, + 237, 237, 0, 237, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 108, 0, 237, 237, 0, 237, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 141, 0, + 0, 0, 0, 0, 0, 141, 141, 0, 141, 141, + 141, 0, 0, 0, 0, 0, 0, 0, 0, 237, + 0, 0, 0, 0, 141, 0, 0, 141, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 237, 0, 0, 0, 0, 0, 0, 141, 0, + 0, 141, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 141, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 108, 108, 108, 108, 0, + 0, 108, 0, 108, 108, 108, 108, 108, 108, 108, + 108, 0, 0, 0, 0, 0, 0, 0, 0, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 108, 108, 108, 0, 0, + 0, 0, 0, 108, 108, 108, 108, 108, 108, 108, + 108, 108, 108, 108, 108, 0, 0, 0, 0, 0, + 108, 108, 108, 108, 108, 108, 108, 108, 108, 108, + 237, 0, 108, 108, 108, 108, 0, 0, 108, 108, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 108, 108, 108, 108, 108, 0, 237, 0, 108, 108, + 108, 108, 141, 141, 141, 141, 237, 0, 141, 237, + 141, 141, 141, 141, 141, 141, 141, 141, 0, 0, + 0, 0, 0, 0, 0, 0, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 0, 0, 0, 0, 141, + 141, 167, 237, 237, 237, 237, 237, 237, 0, 0, + 0, 0, 141, 141, 141, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 141, 141, 141, 0, 0, 0, + 0, 0, 0, 0, 167, 141, 141, 0, 0, 0, + 0, 167, 167, 0, 229, 167, 167, 0, 0, 0, + 0, 0, 0, 0, 0, 141, 141, 141, 141, 0, + 167, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, + 0, 0, 0, 0, 229, 229, 0, 0, 229, 0, + 0, 0, 0, 0, 167, 0, 0, 167, 0, 0, + 0, 0, 0, 229, 229, 0, 229, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 167, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 229, 0, 0, + 229, 0, 0, 0, 0, 0, 0, 0, 236, 0, + 0, 40, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 229, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 40, 0, 0, 0, 0, 236, + 0, 40, 236, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 236, 0, 0, + 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 236, 0, 0, 40, 0, 0, 40, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 167, 167, + 167, 167, 0, 0, 167, 0, 167, 167, 167, 167, + 167, 167, 0, 236, 0, 0, 40, 0, 0, 0, + 0, 0, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, + 167, 229, 229, 229, 229, 0, 167, 229, 0, 0, + 0, 0, 229, 0, 0, 229, 229, 0, 0, 0, + 0, 0, 0, 167, 167, 167, 167, 167, 167, 167, + 167, 167, 167, 0, 0, 0, 0, 0, 0, 0, + 0, 167, 167, 42, 0, 0, 0, 0, 0, 229, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 167, 167, 167, 167, 0, 229, 229, 229, 229, + 229, 229, 229, 229, 229, 229, 42, 0, 229, 229, + 229, 229, 0, 42, 0, 0, 0, 0, 0, 0, + 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, + 229, 0, 42, 0, 0, 0, 0, 229, 40, 40, + 40, 40, 236, 0, 40, 0, 0, 0, 0, 40, + 0, 0, 40, 40, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 42, 0, 236, 42, + 0, 0, 95, 0, 0, 0, 0, 0, 236, 0, + 0, 236, 0, 0, 0, 0, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 42, 0, + 0, 0, 0, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 0, 0, 40, 40, 40, 40, 0, + 0, 0, 0, 0, 0, 236, 0, 0, 0, 0, + 0, 95, 0, 40, 40, 40, 40, 40, 0, 0, + 0, 0, 0, 0, 40, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 42, 42, 42, 42, 0, 0, 42, 0, 0, 93, + 0, 42, 0, 0, 42, 42, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 93, 0, 0, 0, 0, 42, 42, + 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 89, 0, 0, 0, 0, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 42, 93, 0, 42, 42, 42, + 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 42, 42, 42, 42, 42, + 91, 0, 95, 0, 0, 0, 42, 95, 95, 95, + 0, 95, 95, 95, 95, 0, 0, 0, 0, 89, + 0, 0, 0, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, + 95, 95, 188, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 89, 0, 0, 0, 0, 0, 91, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 95, 95, 0, 89, 0, 0, 0, 0, + 0, 0, 0, 91, 0, 0, 0, 0, 0, 103, + 0, 0, 95, 95, 95, 95, 0, 0, 0, 0, + 93, 0, 0, 0, 0, 93, 93, 93, 0, 93, + 93, 93, 93, 0, 0, 91, 0, 0, 0, 0, + 0, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 93, 93, 93, 93, 93, 93, 93, 93, 93, 93, + 189, 0, 0, 0, 0, 0, 0, 0, 103, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 93, 93, 103, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, + 93, 93, 93, 93, 0, 0, 0, 0, 0, 0, + 89, 0, 0, 0, 103, 89, 89, 89, 0, 89, + 89, 89, 89, 0, 0, 0, 0, 0, 0, 0, + 0, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, + 91, 0, 0, 0, 0, 91, 91, 91, 105, 91, + 91, 91, 91, 0, 0, 0, 0, 0, 0, 0, + 0, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, + 89, 89, 105, 0, 0, 0, 0, 0, 109, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 89, 89, 89, 89, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 105, 0, 0, 0, 0, 0, + 91, 91, 0, 0, 0, 0, 0, 0, 107, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, + 91, 91, 91, 91, 103, 103, 103, 109, 103, 103, + 103, 103, 0, 0, 0, 0, 0, 0, 0, 0, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 103, + 103, 103, 103, 103, 103, 103, 103, 103, 103, 0, + 0, 109, 0, 0, 0, 0, 0, 107, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 109, 0, 0, 0, 0, 0, 103, + 103, 107, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 103, + 103, 103, 103, 0, 0, 0, 0, 0, 0, 105, + 0, 0, 0, 107, 105, 105, 105, 0, 105, 105, + 105, 105, 0, 0, 0, 0, 0, 0, 0, 0, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 105, + 105, 0, 40, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 109, 105, + 105, 105, 105, 109, 109, 109, 0, 109, 109, 109, + 109, 0, 0, 0, 32, 0, 0, 0, 0, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 109, 109, + 109, 109, 109, 109, 109, 109, 109, 109, 107, 0, + 0, 0, 0, 107, 107, 107, 31, 107, 107, 107, + 107, 80, 0, 0, 0, 0, 0, 0, 0, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 109, 109, + 0, 0, 0, 0, 80, 0, 0, 0, 0, 0, + 0, 80, 0, 0, 0, 0, 0, 0, 109, 109, + 109, 109, 0, 0, 0, 0, 0, 0, 0, 0, + 80, 0, 146, 0, 0, 0, 0, 0, 107, 107, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 107, 107, + 107, 107, 0, 0, 80, 0, 0, 80, 0, 0, + 0, 0, 0, 0, 0, 146, 0, 146, 146, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 146, 0, 0, 0, 0, 80, 0, 0, 0, + 6, 7, 0, 8, 9, 0, 0, 0, 0, 0, + 0, 0, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 0, 146, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 88, 0, 0, 0, 0, + 0, 0, 85, 0, 0, 0, 0, 87, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 146, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, + 0, 23, 24, 0, 0, 25, 0, 26, 0, 0, + 0, 0, 0, 32, 0, 0, 0, 0, 86, 0, + 27, 0, 28, 0, 0, 0, 29, 30, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 31, 0, 0, 80, 80, + 80, 0, 0, 0, 80, 0, 80, 80, 80, 80, + 80, 80, 80, 80, 0, 0, 0, 0, 0, 0, + 0, 0, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, + 80, 0, 0, 0, 0, 0, 80, 80, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 0, 0, + 0, 0, 0, 80, 80, 80, 80, 80, 80, 80, + 80, 80, 80, 146, 146, 80, 80, 80, 80, 0, + 0, 80, 80, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 80, 80, 80, 80, 80, 0, 0, + 0, 80, 80, 80, 0, 0, 0, 0, 146, 146, + 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, + 146, 146, 146, 146, 0, 0, 0, 0, 0, 275, + 276, 49, 8, 9, 0, 50, 146, 146, 146, 146, + 51, 10, 11, 277, 278, 14, 15, 16, 17, 18, + 19, 20, 21, 0, 146, 146, 146, 146, 146, 6, + 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, + 0, 6, 0, 0, 0, 0, 0, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 0, + 0, 0, 0, 0, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 22, 0, 76, 77, 78, 79, + 23, 24, 0, 0, 25, 0, 26, 6, 0, 0, + 0, 0, 6, 0, 80, 81, 82, 83, 84, 27, + 0, 28, 0, 0, 0, 29, 30, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 88, 0, 0, + 0, 0, 0, 0, 103, 0, 0, 0, 0, 87, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 6, 6, 6, 6, 6, 0, 6, + 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 0, 104, 0, + 0, 0, 0, 0, 0, 103, 295, 0, 0, 0, + 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 0, 0, 0, 0, 0, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 0, + 6, 6, 6, 6, 6, 6, 0, 0, 6, 0, + 6, 86, 0, 0, 0, 0, 0, 0, 6, 6, + 6, 6, 6, 6, 0, 6, 0, 0, 0, 6, + 6, 47, 48, 49, 8, 0, 0, 50, 0, 119, + 120, 121, 51, 122, 123, 124, 125, 0, 0, 0, + 0, 0, 0, 0, 0, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 0, 0, 0, 0, 0, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 0, 0, 0, 0, 0, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 88, 0, 76, 77, + 78, 79, 0, 85, 145, 146, 0, 0, 87, 0, + 0, 0, 0, 0, 0, 0, 80, 81, 82, 83, + 84, 0, 0, 0, 147, 148, 149, 29, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, + 0, 0, 47, 48, 49, 8, 0, 0, 50, 0, + 0, 0, 0, 51, 0, 0, 52, 53, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 0, 0, 0, 0, 0, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 104, 0, 76, + 77, 78, 79, 0, 103, 0, 0, 0, 0, 87, + 0, 0, 0, 0, 0, 0, 0, 80, 81, 82, + 83, 84, 0, 0, 0, 0, 0, 0, 29, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 86, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 47, 48, 49, 8, 0, 0, 50, 0, 0, 0, + 0, 51, 0, 0, 52, 53, 0, 0, 104, 0, + 0, 0, 0, 0, 0, 85, 0, 0, 0, 0, + 87, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 0, 0, 0, 0, 0, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 0, 0, 76, 77, 78, + 79, 86, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 80, 81, 82, 83, 84, + 0, 0, 0, 0, 0, 0, 29, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 104, + 0, 0, 0, 0, 0, 0, 266, 0, 0, 0, + 0, 87, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 47, 48, 49, 8, 0, 0, 50, 0, 0, + 0, 0, 51, 0, 0, 52, 53, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 86, 0, 0, 0, 0, 0, 0, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 0, 0, 0, 0, 0, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 0, 0, 76, 77, + 78, 79, 88, 0, 0, 0, 0, 0, 0, 103, + 0, 402, 0, 0, 87, 0, 80, 81, 82, 83, + 84, 0, 47, 48, 49, 8, 0, 29, 50, 0, + 0, 0, 0, 51, 0, 0, 52, 53, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 86, 0, 0, 0, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 0, 0, 0, 0, 0, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 0, 0, 76, + 77, 78, 79, 88, 0, 0, 0, 0, 0, 0, + 103, 0, 0, 0, 0, 87, 0, 80, 81, 82, + 83, 84, 0, 47, 48, 49, 8, 0, 29, 50, + 0, 0, 0, 0, 51, 0, 0, 52, 53, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 86, 0, 0, 0, + 0, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 0, 0, 0, 0, 0, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 0, 0, + 76, 77, 78, 79, 88, 0, 0, 0, 0, 0, + 0, 85, 0, 0, 0, 0, 87, 0, 80, 81, + 82, 83, 84, 0, 0, 0, 47, 48, 49, 29, + 0, 0, 50, 0, 0, 0, 0, 51, 0, 0, + 52, 53, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 86, 0, 0, + 0, 0, 0, 0, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 0, 0, 0, 0, + 0, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 0, 0, 76, 77, 78, 79, 88, 0, 0, + 0, 0, 0, 0, 266, 0, 0, 0, 0, 87, + 0, 80, 81, 82, 83, 84, 0, 47, 48, 49, + 0, 0, 0, 50, 0, 0, 0, 0, 51, 0, + 0, 52, 53, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 86, 0, 0, 0, 0, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 0, 0, 0, + 0, 0, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 0, 0, 76, 77, 78, 79, 88, 0, + 0, 0, 0, 0, 0, 103, 0, 0, 0, 0, + 87, 0, 80, 81, 82, 83, 84, 0, 47, 48, + 49, 0, 0, 0, 50, 0, 0, 0, 0, 51, + 0, 0, 52, 53, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 86, 0, 0, 0, 0, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 65, 0, 0, + 0, 0, 0, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 0, 0, 76, 77, 78, 79, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 80, 81, 82, 83, 84, 0, 0, + 0, 47, 48, 49, 0, 0, 0, 50, 0, 0, + 0, 0, 51, 0, 0, 52, 53, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 54, + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 0, 0, 0, 0, 0, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 0, 0, 76, 77, + 78, 79, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 80, 81, 82, 83, + 84, 0, 47, 48, 49, 0, 0, 0, 50, 0, + 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 0, 0, 0, 0, 0, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, 0, 0, 76, + 77, 78, 79, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 80, 81, 82, + 83, 84, +}; +static YYCONST short yycheck[] = { 24, + 118, 44, 0, 28, 93, 30, 59, 43, 37, 45, + 260, 36, 59, 42, 43, 37, 45, 260, 47, 0, + 42, 43, 0, 45, 96, 47, 104, 85, 43, 4, + 45, 60, 43, 62, 45, 0, 154, 35, 98, 100, + 346, 347, 41, 41, 43, 58, 45, 62, 61, 24, + 41, 41, 113, 44, 44, 30, 348, 349, 0, 258, + 85, 36, 87, 88, 58, 94, 317, 318, 319, 320, + 321, 258, 94, 114, 115, 100, 134, 96, 43, 104, + 45, 59, 37, 333, 43, 44, 45, 42, 113, 95, + 40, 0, 47, 345, 59, 61, 333, 122, 123, 124, + 125, 126, 127, 128, 129, 130, 131, 132, 0, 134, + 91, 136, 137, 138, 203, 93, 262, 59, 40, 40, + 363, 0, 147, 148, 40, 100, 40, 133, 93, 154, + 40, 61, 41, 40, 0, 44, 111, 40, 113, 94, + 40, 40, 123, 118, 271, 272, 40, 125, 290, 0, + 59, 93, 230, 231, 212, 213, 234, 235, 260, 258, + 125, 262, 187, 188, 189, 190, 191, 192, 193, 194, + 195, 196, 197, 198, 199, 200, 201, 202, 0, 154, + 0, 41, 33, 125, 93, 257, 41, 212, 213, 40, + 264, 263, 94, 59, 45, 301, 268, 46, 258, 259, + 257, 93, 227, 271, 272, 230, 231, 232, 266, 234, + 235, 0, 93, 125, 93, 258, 125, 93, 85, 41, + 262, 41, 44, 257, 44, 352, 353, 93, 300, 262, + 96, 260, 44, 125, 43, 44, 45, 59, 257, 59, + 91, 266, 41, 41, 263, 96, 125, 41, 41, 268, + 41, 257, 44, 371, 260, 43, 44, 45, 264, 125, + 44, 236, 237, 130, 131, 132, 241, 0, 304, 0, + 59, 93, 123, 93, 299, 41, 257, 258, 300, 260, + 261, 303, 342, 41, 352, 353, 0, 154, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 302, 346, 33, 125, 93, 125, 37, 44, 262, 40, + 41, 42, 43, 44, 45, 303, 47, 346, 347, 348, + 349, 350, 351, 257, 260, 41, 59, 194, 59, 60, + 358, 62, 41, 41, 363, 202, 125, 343, 344, 41, + 365, 366, 367, 343, 369, 59, 0, 262, 41, 154, + 343, 332, 30, 377, 343, 264, 343, 338, 339, 35, + 93, 342, 93, 344, -1, 96, 372, -1, -1, 375, + -1, -1, -1, -1, 399, -1, 357, 402, 359, 93, + -1, 290, 363, 364, -1, -1, -1, -1, -1, 0, + -1, 257, 125, 37, 125, -1, 371, 263, 42, 43, + -1, 45, 268, 47, -1, -1, 257, 258, 259, 260, + 261, 125, 263, -1, -1, -1, -1, 268, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 41, -1, 299, 44, 300, -1, -1, 346, 347, -1, + -1, -1, 264, -1, 264, -1, -1, -1, 59, -1, + 94, -1, -1, -1, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, -1, -1, 290, -1, + 290, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 93, 334, 335, 336, 337, 338, 339, -1, + -1, 342, -1, 344, -1, -1, -1, -1, 365, 366, + -1, 352, 353, 354, 355, 356, 357, -1, 359, -1, + -1, -1, 363, 364, 125, -1, 91, -1, -1, -1, + -1, 257, -1, -1, 260, 347, 257, 258, 259, 260, + -1, -1, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, -1, -1, -1, 91, -1, -1, -1, -1, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, + -1, -1, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, -1, -1, 0, -1, + 0, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, 0, -1, 334, 335, 336, 337, 343, 344, 340, + 341, -1, 343, 0, 0, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, 360, + 361, 362, 363, 43, 33, 45, 372, -1, 37, 375, + -1, 40, 41, 42, 43, 44, 45, 59, 47, 59, + -1, 0, 26, 264, 41, -1, -1, 44, -1, -1, + 59, 60, -1, 62, -1, 91, -1, -1, 42, -1, + -1, -1, 59, 59, -1, -1, -1, -1, 0, 290, + -1, 93, -1, 93, -1, 260, -1, -1, -1, 300, + -1, -1, 303, 268, 93, -1, -1, 96, 273, 274, + 275, 276, 277, 278, -1, 280, 93, 93, 0, -1, + 59, -1, 86, 125, 260, 125, -1, -1, -1, 0, + 0, -1, 268, -1, -1, -1, 125, 273, 274, 275, + 276, 277, 278, -1, 280, 346, 347, 59, 125, 125, + -1, 33, -1, -1, 93, 37, -1, -1, 40, 41, + 42, 43, 44, 45, -1, 47, -1, -1, -1, -1, + 41, 41, -1, 44, 44, -1, -1, 59, 60, -1, + 62, 93, -1, -1, -1, 37, 125, -1, 59, 59, + 42, 43, 156, 45, -1, 47, 160, 161, 162, 163, + 164, 165, 166, 167, 168, 169, -1, -1, 60, -1, + 62, 93, -1, 125, 96, -1, -1, -1, -1, -1, + -1, -1, 93, 93, -1, -1, -1, 37, -1, -1, + -1, -1, 42, 43, 44, 45, -1, 47, -1, -1, + -1, -1, 94, 125, 260, -1, -1, -1, -1, -1, + 60, -1, 62, -1, 125, 125, -1, 273, 274, 275, + 276, 277, 278, -1, 280, -1, -1, -1, 257, 258, + 259, 260, -1, -1, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, 94, -1, -1, 264, -1, -1, + -1, -1, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, -1, 290, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, -1, -1, + -1, -1, -1, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, -1, -1, 334, 335, 336, 337, -1, + -1, 340, 341, -1, 343, -1, -1, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + 347, 360, 361, 362, 363, 257, 258, 259, 260, -1, + -1, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 355, -1, 264, 264, 359, 360, -1, -1, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 298, 299, 300, 290, + 290, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, -1, -1, -1, -1, -1, + 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, + 0, -1, 334, 335, 336, 337, -1, -1, 340, 341, + -1, 343, -1, -1, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, -1, 347, -1, 360, 361, + 362, 363, -1, 33, -1, -1, -1, 37, -1, -1, + 40, 41, 42, 43, 44, 45, -1, 47, 350, 351, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, + 60, -1, 62, -1, -1, -1, -1, 24, -1, -1, + -1, -1, 37, 30, -1, -1, -1, 42, 43, -1, + 45, -1, 47, -1, -1, -1, 346, 347, 348, 349, + 350, 351, -1, 93, -1, 60, 96, 62, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, + -1, -1, -1, 37, -1, -1, -1, -1, 42, 43, + -1, 45, -1, 47, -1, 125, -1, -1, 85, 94, + -1, -1, -1, -1, -1, -1, 60, -1, 62, -1, + 33, -1, -1, 100, 37, -1, -1, 40, 41, 42, + 43, 44, 45, -1, 47, -1, 113, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 59, 60, -1, 62, + 94, -1, -1, 130, 131, 132, 37, -1, -1, -1, + -1, 42, 43, 37, 45, -1, 47, -1, 42, 43, + 44, 45, -1, 47, -1, -1, -1, 154, -1, 60, + 93, 62, -1, 96, 37, -1, 60, -1, 62, 42, + 43, 44, 45, -1, 47, -1, 37, -1, -1, -1, + -1, 42, 43, -1, 45, -1, 47, 60, -1, 62, + -1, -1, 125, 94, -1, -1, -1, 194, -1, 60, + 94, 62, -1, -1, -1, 202, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 257, 258, 259, + 260, 94, -1, 263, 264, 265, 266, 267, 268, 269, + 270, 271, 272, 94, -1, -1, -1, -1, -1, -1, + -1, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + 300, -1, -1, 303, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, -1, -1, -1, + -1, 286, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, -1, -1, 334, 335, 336, 337, -1, -1, + 340, 341, 299, 343, -1, -1, 346, 347, 348, 349, + 350, 351, 352, 353, 354, 355, 356, -1, -1, -1, + 360, 361, 362, 363, 257, 258, 259, 260, -1, -1, + 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, + -1, 346, 347, 348, 349, 350, 351, -1, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, 365, 366, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 348, 349, 350, 351, -1, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + -1, 334, 335, 336, 337, -1, 300, 340, 341, 303, + 343, -1, -1, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, 360, 361, 362, + 363, -1, 33, -1, -1, -1, 37, -1, -1, 40, + 41, 42, 43, 44, 45, 346, 47, 348, 349, 350, + 351, -1, 346, 347, 348, 349, 350, 351, 59, 60, + -1, 62, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 346, 347, 348, 349, 350, 351, -1, + -1, -1, -1, -1, -1, 346, 347, 348, 349, 350, + 351, -1, 93, -1, -1, 96, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 125, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, + -1, -1, -1, -1, -1, -1, 40, 41, -1, 43, + 44, 45, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 59, 60, -1, 62, -1, + -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, + 42, 43, 37, 45, -1, 47, -1, 42, 43, 44, + 45, -1, 47, -1, -1, -1, -1, -1, 60, 93, + 62, -1, 96, 37, -1, 60, -1, 62, 42, 43, + -1, 45, -1, 47, -1, 37, -1, -1, -1, -1, + 42, 43, -1, 45, -1, 47, 60, -1, 62, -1, + -1, 125, 94, -1, -1, -1, -1, -1, 60, 94, + 62, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 257, 258, 259, 260, + 94, -1, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 94, -1, -1, -1, -1, -1, -1, -1, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, + -1, -1, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, -1, -1, -1, -1, + -1, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, -1, -1, 334, 335, 336, 337, -1, -1, 340, + 341, -1, 343, -1, -1, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, -1, -1, -1, 360, + 361, 362, 363, 257, 258, 259, 260, -1, -1, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, -1, + 0, -1, -1, -1, -1, -1, -1, 281, 282, 283, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, + 294, 295, 296, 297, 298, 299, 300, -1, -1, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, -1, -1, -1, -1, 289, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 59, + 334, 335, 336, 337, -1, 300, 340, 341, 303, 343, + -1, -1, 346, 347, 348, 349, 350, 351, 352, 353, + 354, 355, 356, -1, -1, -1, 360, 361, 362, 363, + -1, 33, -1, 93, -1, -1, 96, -1, 40, 41, + -1, 43, 44, 45, 346, 347, 348, 349, 350, 351, + -1, 346, 347, 348, 349, 350, 351, 59, 60, -1, + 62, -1, -1, -1, -1, 125, -1, -1, -1, -1, + -1, -1, 346, 347, 348, 349, 350, 351, -1, -1, + -1, -1, -1, -1, 346, -1, 348, 349, 350, 351, + -1, 93, -1, -1, 96, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 125, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, + -1, -1, -1, -1, -1, 40, 41, -1, -1, 44, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 59, 60, -1, 62, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 37, -1, -1, -1, -1, 42, 43, 44, 45, + -1, 47, -1, -1, -1, -1, -1, 257, 93, -1, + -1, 96, -1, 263, 60, -1, 62, -1, 268, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 125, -1, -1, -1, -1, -1, -1, -1, 94, -1, + 300, -1, -1, -1, -1, -1, 46, -1, -1, -1, + -1, -1, -1, -1, -1, 257, 258, 259, 260, 46, + -1, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, -1, -1, -1, -1, -1, -1, -1, -1, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 298, 299, 300, -1, + -1, 303, 304, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, -1, -1, -1, -1, -1, + 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, + -1, -1, 334, 335, 336, 337, -1, -1, 340, 341, + -1, 343, -1, -1, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 46, -1, -1, 360, 361, + 362, 363, 257, 258, 259, 260, -1, -1, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, -1, -1, + -1, -1, -1, -1, -1, -1, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, -1, -1, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, -1, -1, -1, -1, -1, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, -1, 334, + 335, 336, 337, -1, 300, 340, 341, 303, 343, -1, + -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, -1, -1, -1, 360, 361, 362, 363, -1, + 33, 271, 272, -1, -1, -1, -1, 40, 41, -1, + -1, 44, -1, -1, 271, 272, -1, -1, -1, -1, + 346, 347, 348, 349, 350, 351, 59, 60, -1, 62, + -1, -1, -1, -1, -1, -1, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, -1, -1, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + 93, -1, -1, 96, 334, 335, 336, 337, -1, -1, + -1, -1, -1, -1, 0, -1, -1, 334, 335, 336, + 337, -1, 352, 353, 354, 355, 356, -1, -1, -1, + -1, -1, 125, -1, -1, 352, 353, 354, 355, 356, + -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, + -1, -1, -1, -1, 40, 41, -1, -1, 44, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 59, 60, -1, 62, -1, -1, -1, + -1, -1, -1, -1, -1, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, + 96, -1, -1, 334, 335, 336, 337, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 352, 353, 354, 355, 356, -1, -1, -1, 125, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 257, 258, 259, 260, -1, -1, + 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, + -1, -1, -1, -1, -1, -1, -1, -1, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, -1, -1, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, -1, -1, -1, -1, -1, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, -1, + -1, 334, 335, 336, 337, -1, -1, 340, 341, -1, + 343, -1, -1, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, 360, 361, 362, + 363, 257, 258, 259, 260, -1, -1, 263, 264, 265, + 266, 267, 268, 269, 270, 271, 272, -1, -1, -1, + -1, -1, -1, -1, -1, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, 300, -1, -1, 303, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, -1, -1, -1, -1, -1, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 0, -1, 334, 335, + 336, 337, -1, -1, 340, 341, -1, 343, -1, -1, + 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, + 356, -1, -1, -1, 360, 361, 362, 363, -1, 33, + -1, -1, -1, -1, -1, -1, 40, 41, -1, -1, + 44, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 59, 60, -1, 62, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, + -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 125, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, + -1, -1, -1, 40, 41, -1, 43, 44, 45, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 59, -1, -1, 62, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 93, -1, -1, 96, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 125, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 257, 258, 259, 260, -1, -1, 263, + 264, 265, 266, 267, 268, 269, 270, 271, 272, -1, + -1, -1, -1, -1, -1, -1, -1, 281, 282, 283, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, + 294, 295, 296, 297, 298, 299, 300, -1, -1, 303, + 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, -1, -1, -1, -1, -1, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, -1, -1, + 334, 335, 336, 337, -1, -1, 340, 341, -1, 343, + -1, -1, 346, 347, 348, 349, 350, 351, 352, 353, + 354, 355, 356, -1, -1, -1, 360, 361, 362, 363, + 257, 258, 259, 260, -1, -1, 263, -1, 265, 266, + 267, 268, 269, 270, 271, 272, -1, -1, -1, -1, + -1, -1, -1, -1, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, + 297, 298, 299, -1, -1, -1, -1, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, + 327, 328, 329, 330, 331, 0, -1, 334, 335, 336, + 337, -1, -1, 340, 341, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 352, 353, 354, 355, 356, + -1, -1, -1, 360, 361, 362, 363, -1, 33, -1, + -1, -1, -1, -1, -1, 40, 41, -1, -1, 44, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 59, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, + -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 0, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 125, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, + -1, -1, 40, 41, -1, -1, 44, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 59, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 93, -1, -1, 96, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 125, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 257, 258, 259, 260, -1, -1, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, -1, -1, + -1, -1, -1, -1, -1, -1, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, 300, -1, -1, 303, 304, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, -1, -1, -1, -1, -1, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, -1, -1, 334, + 335, 336, 337, -1, -1, 340, 341, -1, 343, -1, + -1, 346, 347, 348, 349, -1, -1, 352, 353, 354, + 355, 356, -1, -1, -1, 360, 361, 362, 363, 257, + 258, 259, 260, -1, -1, 263, 264, 265, 266, 267, + 268, 269, 270, 271, 272, -1, -1, -1, -1, -1, + -1, -1, -1, 281, 282, 283, 284, 285, 286, 287, + 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, + 298, 299, 300, -1, -1, 303, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, -1, + -1, -1, -1, -1, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, -1, 334, 335, 336, 337, + -1, -1, 340, 341, -1, 343, -1, -1, 346, 347, + 348, 349, -1, -1, 352, 353, 354, 355, 356, -1, + -1, -1, 360, 361, 362, 363, -1, 33, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 59, -1, -1, 62, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, + 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 125, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, + -1, 40, 41, -1, -1, 44, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 59, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 93, -1, -1, 96, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 125, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 257, 258, 259, 260, -1, -1, 263, -1, 265, + 266, 267, 268, 269, 270, 271, 272, -1, -1, -1, + -1, -1, -1, -1, -1, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, -1, -1, -1, -1, 304, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, -1, -1, 334, 335, + 336, 337, -1, -1, 340, 341, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 352, 353, 354, 355, + 356, -1, -1, -1, 360, 361, 362, 363, 257, 258, + 259, 260, -1, -1, 263, 264, 265, 266, 267, 268, + 269, 270, 271, 272, -1, -1, -1, -1, -1, -1, + -1, -1, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 300, -1, -1, 303, 304, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, -1, -1, + -1, -1, -1, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, -1, 334, 335, 336, 337, -1, + -1, 340, 341, -1, 343, -1, -1, 346, 347, -1, + -1, -1, -1, 352, 353, 354, 355, 356, -1, -1, + -1, 360, 361, 362, 363, -1, 33, -1, -1, -1, + -1, -1, -1, 40, 41, -1, -1, 44, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 59, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 93, -1, -1, 96, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 125, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, + 40, 41, -1, 43, 44, 45, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, + -1, -1, 62, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 93, -1, -1, 96, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 125, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 257, 258, 259, 260, -1, -1, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, -1, -1, -1, -1, + -1, -1, -1, -1, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, + 297, 298, 299, 300, -1, -1, 303, 304, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + -1, -1, -1, -1, -1, 322, 323, 324, 325, 326, + 327, 328, 329, 330, 331, -1, -1, 334, 335, 336, + 337, -1, -1, 340, 341, -1, 343, -1, -1, -1, + 347, -1, -1, -1, -1, 352, 353, 354, 355, 356, + -1, -1, -1, 360, 361, 362, 363, 257, 258, 259, + 260, -1, -1, 263, -1, 265, 266, 267, 268, 269, + 270, 271, 272, -1, -1, -1, -1, -1, -1, -1, + -1, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + -1, -1, -1, -1, 304, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, -1, -1, -1, + -1, -1, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, 0, -1, 334, 335, 336, 337, -1, -1, + 340, 341, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 352, 353, 354, 355, 356, -1, -1, -1, + 360, 361, 362, 363, -1, 33, -1, -1, -1, -1, + -1, -1, 40, 41, -1, -1, 44, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 59, -1, -1, 62, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 93, -1, -1, 96, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 125, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 33, -1, -1, -1, -1, -1, -1, 40, + 41, -1, -1, 44, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 93, -1, -1, 96, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 125, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, + 258, 259, 260, -1, -1, 263, -1, 265, 266, 267, + 268, 269, 270, 271, 272, -1, -1, -1, -1, -1, + -1, -1, -1, 281, 282, 283, 284, 285, 286, 287, + 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, + 298, 299, -1, -1, -1, -1, 304, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, -1, + -1, -1, -1, -1, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, -1, -1, 334, 335, 336, 337, + 40, -1, 340, 341, -1, -1, 46, -1, -1, -1, + -1, -1, -1, -1, 352, 353, 354, 355, 356, -1, + -1, -1, 360, 361, 362, 363, 257, 258, 259, 260, + -1, -1, 263, -1, 265, 266, 267, 268, 269, 270, + 271, 272, -1, -1, -1, -1, -1, -1, -1, -1, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, -1, + -1, -1, -1, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, 0, -1, -1, -1, + -1, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, -1, -1, 334, 335, 336, 337, -1, -1, 340, + 341, -1, -1, -1, -1, -1, -1, -1, -1, 33, + -1, 352, 353, 354, 355, 356, 40, -1, -1, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, + -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 125, -1, -1, -1, -1, -1, 257, -1, -1, + -1, -1, -1, 263, -1, -1, 33, -1, 268, -1, + -1, 271, 272, 40, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 59, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 93, -1, -1, 96, + -1, -1, -1, -1, 334, 335, 336, 337, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 352, 353, 354, 355, 356, -1, 125, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 257, 258, 259, 260, -1, -1, 263, + -1, 265, 266, 267, 268, 269, 270, 271, 272, -1, + -1, -1, -1, -1, -1, -1, -1, 281, 282, 283, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, + 294, 295, 296, 297, 298, 299, -1, -1, -1, -1, + -1, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, -1, -1, 91, -1, -1, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, -1, -1, + 334, 335, 336, 337, -1, -1, 340, 341, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 123, 352, 353, + 354, 355, 356, -1, -1, -1, 360, 361, 362, 363, + 257, 258, 259, 260, -1, -1, 263, -1, 265, 266, + 267, 268, 269, 270, 271, 272, -1, -1, -1, -1, + -1, -1, -1, -1, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, + 297, 298, 299, -1, -1, -1, -1, -1, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + 0, -1, -1, -1, -1, 322, 323, 324, 325, 326, + 327, 328, 329, 330, 331, -1, -1, 334, 335, 336, + 337, -1, -1, 340, 341, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, 352, 353, 354, 355, 356, + 40, -1, -1, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, + -1, 257, 258, -1, 260, 261, -1, -1, -1, -1, + -1, -1, -1, 269, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, -1, -1, -1, -1, -1, + -1, -1, -1, 93, -1, -1, 96, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 125, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 332, -1, -1, -1, + 33, -1, 338, 339, -1, -1, 342, 40, 344, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 357, -1, 359, -1, -1, 59, 363, 364, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 93, -1, -1, 96, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 125, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 257, 258, 259, + 260, -1, -1, 263, -1, 265, 266, 267, 268, 269, + 270, 271, 272, -1, -1, -1, -1, -1, -1, -1, + -1, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + -1, -1, -1, -1, -1, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, -1, -1, 91, + -1, -1, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, -1, -1, 334, 335, 336, 337, -1, -1, + 340, 341, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 123, 352, 353, 354, 355, 356, -1, -1, -1, + 360, 361, 362, 363, 257, 258, 259, 260, -1, -1, + 263, -1, 265, 266, 267, 268, 269, 270, 271, 272, + -1, -1, -1, -1, -1, -1, -1, -1, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, -1, -1, -1, + -1, -1, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 0, -1, -1, -1, -1, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, -1, + -1, 334, 335, 336, 337, -1, -1, 340, 341, -1, + -1, -1, -1, -1, -1, -1, -1, 33, -1, 352, + 353, 354, 355, 356, 40, -1, -1, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 59, -1, 257, 258, -1, 260, 261, + -1, -1, -1, -1, -1, -1, -1, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, -1, + -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, + 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 125, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 332, -1, -1, -1, 33, -1, 338, 339, -1, -1, + 342, 40, 344, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 357, -1, 359, -1, -1, + 59, 363, 364, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 93, -1, -1, 96, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 125, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 257, 258, 259, 260, -1, -1, 263, -1, 265, + 266, 267, 268, 269, 270, 271, 272, -1, -1, -1, + -1, -1, -1, -1, -1, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, -1, -1, -1, -1, -1, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, -1, -1, -1, -1, -1, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, -1, -1, 334, 335, + 336, 337, -1, -1, 340, 341, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 352, 353, 354, 355, + 356, -1, -1, -1, 360, 361, 362, 363, 257, 258, + 259, 260, -1, -1, 263, -1, 265, 266, 267, 268, + 269, 270, 271, 272, -1, -1, -1, -1, -1, -1, + -1, -1, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, -1, -1, -1, -1, -1, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 0, -1, + -1, -1, -1, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, -1, -1, 334, 335, 336, 337, -1, + -1, 340, 341, -1, -1, -1, -1, -1, -1, -1, + -1, 33, -1, 352, 353, 354, 355, 356, 40, -1, + -1, 360, 361, 362, 363, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 93, -1, -1, 96, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 125, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, + -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 59, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 93, -1, + -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 125, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 257, 258, 259, 260, -1, + -1, 263, -1, 265, 266, 267, 268, 269, 270, 271, + 272, -1, -1, -1, -1, -1, -1, -1, -1, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 298, 299, -1, -1, + -1, -1, -1, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, -1, -1, -1, -1, -1, + 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, + -1, -1, 334, 335, 336, 337, -1, -1, 340, 341, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 352, 353, 354, 355, 356, -1, -1, -1, 360, 361, + 362, 363, 257, 258, 259, 260, -1, -1, 263, -1, + 265, 266, 267, 268, 269, 270, 271, 272, -1, -1, + -1, -1, -1, -1, -1, -1, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, -1, -1, -1, -1, -1, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, 0, -1, -1, -1, -1, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, -1, -1, 334, + 335, 336, 337, -1, -1, 340, 341, -1, -1, -1, + -1, -1, -1, -1, -1, 33, -1, 352, 353, 354, + 355, 356, 40, -1, -1, 360, 361, 362, 363, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 59, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 93, -1, -1, 96, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 125, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 33, -1, -1, -1, -1, -1, -1, 40, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 59, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 93, -1, -1, 96, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 125, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 257, + 258, 259, 260, -1, -1, 263, -1, 265, 266, 267, + 268, 269, 270, 271, 272, -1, -1, -1, -1, -1, + -1, -1, -1, 281, 282, 283, 284, 285, 286, 287, + 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, + 298, 299, -1, -1, -1, -1, -1, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, -1, + -1, -1, -1, -1, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, -1, -1, 334, 335, 336, 337, + -1, -1, 340, 341, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 352, 353, 354, 355, 356, -1, + -1, -1, 360, 361, 362, 363, 257, 258, 259, 260, + -1, -1, 263, -1, 265, 266, 267, 268, 269, 270, + 271, 272, -1, -1, -1, -1, -1, -1, -1, -1, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, -1, + -1, -1, -1, -1, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, 0, -1, -1, -1, + -1, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, -1, -1, 334, 335, 336, 337, -1, -1, 340, + 341, -1, -1, -1, -1, -1, -1, -1, -1, 33, + -1, 352, 353, 354, 355, 356, 40, -1, -1, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, + -1, -1, 96, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 0, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 125, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, + -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 59, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 93, -1, -1, 96, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 125, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 257, 258, 259, 260, -1, -1, 263, + -1, 265, 266, 267, 268, 269, 270, 271, 272, -1, + -1, -1, -1, -1, -1, -1, -1, 281, 282, 283, + 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, + 294, 295, 296, 297, 298, 299, -1, -1, -1, -1, + -1, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, -1, -1, -1, -1, -1, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, -1, -1, + 334, 335, 336, 337, -1, -1, 340, 341, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 352, 353, + 354, 355, 356, -1, -1, -1, 360, 361, 362, 363, + 257, 258, 259, 260, -1, -1, 263, -1, 265, 266, + 267, 268, 269, 270, 271, 272, -1, -1, -1, -1, + -1, -1, -1, -1, 281, 282, 283, 284, 285, 286, + 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, + 297, 298, 299, -1, -1, -1, -1, -1, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + 0, -1, -1, -1, -1, 322, 323, 324, 325, 326, + 327, 328, 329, 330, 331, -1, -1, 334, 335, 336, + 337, -1, -1, 340, 341, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, 352, 353, 354, 355, 356, + 40, -1, -1, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 93, -1, -1, 96, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 125, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 33, -1, -1, -1, -1, -1, -1, 40, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 59, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 93, -1, -1, 96, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 125, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 257, 258, 259, + 260, -1, -1, 263, -1, 265, 266, 267, 268, 269, + 270, 271, 272, -1, -1, -1, -1, -1, -1, -1, + -1, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + -1, -1, -1, -1, -1, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, -1, -1, -1, + -1, -1, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, -1, -1, 334, 335, 336, 337, -1, -1, + 340, 341, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 352, 353, 354, 355, 356, -1, -1, -1, + 360, 361, 362, 363, 257, 258, 259, 260, -1, -1, + 263, -1, 265, 266, 267, 268, 269, 270, 271, 272, + -1, -1, -1, -1, -1, -1, -1, -1, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, -1, -1, -1, + -1, -1, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 0, -1, -1, -1, -1, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, -1, + -1, 334, 335, 336, 337, -1, -1, 340, 341, -1, + -1, -1, -1, -1, -1, -1, -1, 33, -1, 352, + 353, 354, 355, 356, 40, -1, -1, 360, 361, 362, + 363, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 59, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, + 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 125, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, + -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 59, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 93, -1, -1, 96, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 125, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 257, 258, 259, 260, -1, -1, 263, -1, 265, + 266, 267, 268, 269, 270, 271, 272, -1, -1, -1, + -1, -1, -1, -1, -1, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, -1, -1, -1, -1, -1, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, -1, -1, -1, -1, -1, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, -1, -1, 334, 335, + 336, 337, -1, -1, 340, 341, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 352, 353, 354, 355, + 356, -1, -1, -1, 360, 361, 362, 363, 257, 258, + 259, 260, -1, -1, 263, -1, 265, 266, 267, 268, + 269, 270, 271, 272, -1, -1, -1, -1, -1, -1, + -1, -1, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, -1, -1, -1, -1, -1, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 0, -1, + -1, -1, -1, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, -1, -1, 334, 335, 336, 337, -1, + -1, 340, 341, -1, -1, -1, -1, -1, -1, -1, + -1, 33, -1, 352, 353, 354, 355, 356, 40, -1, + -1, 360, 361, 362, 363, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, + -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 93, -1, -1, 96, -1, -1, -1, -1, -1, + -1, -1, -1, 37, -1, 0, -1, 41, 42, 43, + 44, 45, -1, 47, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 125, -1, 59, 60, -1, 62, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, + -1, -1, -1, -1, -1, 40, 41, -1, 43, 44, + 45, -1, -1, -1, -1, -1, -1, -1, -1, 93, + -1, -1, -1, -1, 59, -1, -1, 62, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 125, -1, -1, -1, -1, -1, -1, 93, -1, + -1, 96, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 125, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 257, 258, 259, 260, -1, + -1, 263, -1, 265, 266, 267, 268, 269, 270, 271, + 272, -1, -1, -1, -1, -1, -1, -1, -1, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 298, 299, -1, -1, + -1, -1, -1, 305, 306, 307, 308, 309, 310, 311, + 312, 313, 314, 315, 316, -1, -1, -1, -1, -1, + 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, + 264, -1, 334, 335, 336, 337, -1, -1, 340, 341, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 352, 353, 354, 355, 356, -1, 290, -1, 360, 361, + 362, 363, 257, 258, 259, 260, 300, -1, 263, 303, + 265, 266, 267, 268, 269, 270, 271, 272, -1, -1, + -1, -1, -1, -1, -1, -1, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 295, 296, 297, 298, 299, -1, -1, -1, -1, 304, + 305, 0, 346, 347, 348, 349, 350, 351, -1, -1, + -1, -1, 317, 318, 319, 320, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, -1, -1, -1, + -1, -1, -1, -1, 33, 340, 341, -1, -1, -1, + -1, 40, 41, -1, 0, 44, 45, -1, -1, -1, + -1, -1, -1, -1, -1, 360, 361, 362, 363, -1, + 59, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, + -1, -1, -1, -1, 40, 41, -1, -1, 44, -1, + -1, -1, -1, -1, 93, -1, -1, 96, -1, -1, + -1, -1, -1, 59, 60, -1, 62, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 125, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 93, -1, -1, + 96, -1, -1, -1, -1, -1, -1, -1, 0, -1, + -1, 0, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 125, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 33, -1, -1, -1, -1, 41, + -1, 40, 44, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 59, -1, -1, + 59, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 93, -1, -1, 93, -1, -1, 96, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 257, 258, + 259, 260, -1, -1, 263, -1, 265, 266, 267, 268, + 269, 270, -1, 125, -1, -1, 125, -1, -1, -1, + -1, -1, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, 257, 258, 259, 260, -1, 305, 263, -1, -1, + -1, -1, 268, -1, -1, 271, 272, -1, -1, -1, + -1, -1, -1, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, -1, -1, -1, -1, -1, -1, -1, + -1, 340, 341, 0, -1, -1, -1, -1, -1, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, 360, 361, 362, 363, -1, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 33, -1, 334, 335, + 336, 337, -1, 40, -1, -1, -1, -1, -1, -1, + 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, + 356, -1, 59, -1, -1, -1, -1, 363, 257, 258, + 259, 260, 264, -1, 263, -1, -1, -1, -1, 268, + -1, -1, 271, 272, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 93, -1, 290, 96, + -1, -1, 0, -1, -1, -1, -1, -1, 300, -1, + -1, 303, -1, -1, -1, -1, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 125, -1, + -1, -1, -1, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, -1, -1, 334, 335, 336, 337, -1, + -1, -1, -1, -1, -1, 347, -1, -1, -1, -1, + -1, 59, -1, 352, 353, 354, 355, 356, -1, -1, + -1, -1, -1, -1, 363, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 93, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 125, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 257, 258, 259, 260, -1, -1, 263, -1, -1, 59, + -1, 268, -1, -1, 271, 272, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 93, -1, -1, -1, -1, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + 0, -1, -1, -1, -1, 322, 323, 324, 325, 326, + 327, 328, 329, 330, 331, 125, -1, 334, 335, 336, + 337, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 352, 353, 354, 355, 356, + 0, -1, 260, -1, -1, -1, 363, 265, 266, 267, + -1, 269, 270, 271, 272, -1, -1, -1, -1, 59, + -1, -1, -1, 281, 282, 283, 284, 285, 286, 287, + 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, + 298, 299, 300, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 93, -1, -1, -1, -1, -1, 59, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 340, 341, -1, 125, -1, -1, -1, -1, + -1, -1, -1, 93, -1, -1, -1, -1, -1, 0, + -1, -1, 360, 361, 362, 363, -1, -1, -1, -1, + 260, -1, -1, -1, -1, 265, 266, 267, -1, 269, + 270, 271, 272, -1, -1, 125, -1, -1, -1, -1, + -1, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + 300, -1, -1, -1, -1, -1, -1, -1, 59, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 340, 341, 93, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, + 360, 361, 362, 363, -1, -1, -1, -1, -1, -1, + 260, -1, -1, -1, 125, 265, 266, 267, -1, 269, + 270, 271, 272, -1, -1, -1, -1, -1, -1, -1, + -1, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + 260, -1, -1, -1, -1, 265, 266, 267, 59, 269, + 270, 271, 272, -1, -1, -1, -1, -1, -1, -1, + -1, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + 340, 341, 93, -1, -1, -1, -1, -1, 0, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 360, 361, 362, 363, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 125, -1, -1, -1, -1, -1, + 340, 341, -1, -1, -1, -1, -1, -1, 0, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 260, + 360, 361, 362, 363, 265, 266, 267, 59, 269, 270, + 271, 272, -1, -1, -1, -1, -1, -1, -1, -1, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, -1, + -1, 93, -1, -1, -1, -1, -1, 59, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 125, -1, -1, -1, -1, -1, 340, + 341, 93, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, 260, + -1, -1, -1, 125, 265, 266, 267, -1, 269, 270, + 271, 272, -1, -1, -1, -1, -1, -1, -1, -1, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 340, + 341, -1, 59, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 260, 360, + 361, 362, 363, 265, 266, 267, -1, 269, 270, 271, + 272, -1, -1, -1, 91, -1, -1, -1, -1, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 298, 299, 260, -1, + -1, -1, -1, 265, 266, 267, 123, 269, 270, 271, + 272, 0, -1, -1, -1, -1, -1, -1, -1, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 295, 296, 297, 298, 299, 340, 341, + -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, + -1, 40, -1, -1, -1, -1, -1, -1, 360, 361, + 362, 363, -1, -1, -1, -1, -1, -1, -1, -1, + 59, -1, 0, -1, -1, -1, -1, -1, 340, 341, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 360, 361, + 362, 363, -1, -1, 93, -1, -1, 96, -1, -1, + -1, -1, -1, -1, -1, 43, -1, 45, 46, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 59, -1, -1, -1, -1, 125, -1, -1, -1, + 257, 258, -1, 260, 261, -1, -1, -1, -1, -1, + -1, -1, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, -1, 93, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, + -1, -1, 40, -1, -1, -1, -1, 45, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 125, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 332, -1, -1, -1, -1, + -1, 338, 339, -1, -1, 342, -1, 344, -1, -1, + -1, -1, -1, 91, -1, -1, -1, -1, 96, -1, + 357, -1, 359, -1, -1, -1, 363, 364, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 123, -1, -1, 257, 258, + 259, -1, -1, -1, 263, -1, 265, 266, 267, 268, + 269, 270, 271, 272, -1, -1, -1, -1, -1, -1, + -1, -1, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, + 299, -1, -1, -1, -1, -1, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, -1, -1, + -1, -1, -1, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 271, 272, 334, 335, 336, 337, -1, + -1, 340, 341, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 352, 353, 354, 355, 356, -1, -1, + -1, 360, 361, 362, -1, -1, -1, -1, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, + 318, 319, 320, 321, -1, -1, -1, -1, -1, 257, + 258, 259, 260, 261, -1, 263, 334, 335, 336, 337, + 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, + 278, 279, 280, -1, 352, 353, 354, 355, 356, 33, + -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, + -1, 45, -1, -1, -1, -1, -1, 305, 306, 307, + 308, 309, 310, 311, 312, 313, 314, 315, 316, -1, + -1, -1, -1, -1, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 332, -1, 334, 335, 336, 337, + 338, 339, -1, -1, 342, -1, 344, 91, -1, -1, + -1, -1, 96, -1, 352, 353, 354, 355, 356, 357, + -1, 359, -1, -1, -1, 363, 364, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 123, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, + -1, -1, -1, -1, 40, -1, -1, -1, -1, 45, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 257, 258, 259, 260, 261, -1, 263, + -1, -1, -1, -1, 268, 269, 270, 271, 272, 273, + 274, 275, 276, 277, 278, 279, 280, -1, 33, -1, + -1, -1, -1, -1, -1, 40, 41, -1, -1, -1, + 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, -1, -1, -1, -1, -1, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 332, -1, + 334, 335, 336, 337, 338, 339, -1, -1, 342, -1, + 344, 96, -1, -1, -1, -1, -1, -1, 352, 353, + 354, 355, 356, 357, -1, 359, -1, -1, -1, 363, + 364, 257, 258, 259, 260, -1, -1, 263, -1, 265, + 266, 267, 268, 269, 270, 271, 272, -1, -1, -1, + -1, -1, -1, -1, -1, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, -1, -1, -1, -1, -1, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, -1, -1, -1, -1, -1, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 33, -1, 334, 335, + 336, 337, -1, 40, 340, 341, -1, -1, 45, -1, + -1, -1, -1, -1, -1, -1, 352, 353, 354, 355, + 356, -1, -1, -1, 360, 361, 362, 363, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 96, + -1, -1, 257, 258, 259, 260, -1, -1, 263, -1, + -1, -1, -1, 268, -1, -1, 271, 272, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, -1, -1, -1, -1, -1, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 33, -1, 334, + 335, 336, 337, -1, 40, -1, -1, -1, -1, 45, + -1, -1, -1, -1, -1, -1, -1, 352, 353, 354, + 355, 356, -1, -1, -1, -1, -1, -1, 363, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 96, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 257, 258, 259, 260, -1, -1, 263, -1, -1, -1, + -1, 268, -1, -1, 271, 272, -1, -1, 33, -1, + -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, + 45, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 305, 306, + 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, + -1, -1, -1, -1, -1, 322, 323, 324, 325, 326, + 327, 328, 329, 330, 331, -1, -1, 334, 335, 336, + 337, 96, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 352, 353, 354, 355, 356, + -1, -1, -1, -1, -1, -1, 363, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, + -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, + -1, 45, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 257, 258, 259, 260, -1, -1, 263, -1, -1, + -1, -1, 268, -1, -1, 271, 272, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 96, -1, -1, -1, -1, -1, -1, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, -1, -1, -1, -1, -1, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, -1, -1, 334, 335, + 336, 337, 33, -1, -1, -1, -1, -1, -1, 40, + -1, 42, -1, -1, 45, -1, 352, 353, 354, 355, + 356, -1, 257, 258, 259, 260, -1, 363, 263, -1, + -1, -1, -1, 268, -1, -1, 271, 272, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 96, -1, -1, -1, -1, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, -1, -1, -1, -1, -1, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, -1, -1, 334, + 335, 336, 337, 33, -1, -1, -1, -1, -1, -1, + 40, -1, -1, -1, -1, 45, -1, 352, 353, 354, + 355, 356, -1, 257, 258, 259, 260, -1, 363, 263, + -1, -1, -1, -1, 268, -1, -1, 271, 272, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 96, -1, -1, -1, + -1, 305, 306, 307, 308, 309, 310, 311, 312, 313, + 314, 315, 316, -1, -1, -1, -1, -1, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, -1, -1, + 334, 335, 336, 337, 33, -1, -1, -1, -1, -1, + -1, 40, -1, -1, -1, -1, 45, -1, 352, 353, + 354, 355, 356, -1, -1, -1, 257, 258, 259, 363, + -1, -1, 263, -1, -1, -1, -1, 268, -1, -1, + 271, 272, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 96, -1, -1, + -1, -1, -1, -1, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, -1, -1, -1, -1, + -1, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, -1, -1, 334, 335, 336, 337, 33, -1, -1, + -1, -1, -1, -1, 40, -1, -1, -1, -1, 45, + -1, 352, 353, 354, 355, 356, -1, 257, 258, 259, + -1, -1, -1, 263, -1, -1, -1, -1, 268, -1, + -1, 271, 272, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 96, -1, -1, -1, -1, 305, 306, 307, 308, 309, + 310, 311, 312, 313, 314, 315, 316, -1, -1, -1, + -1, -1, 322, 323, 324, 325, 326, 327, 328, 329, + 330, 331, -1, -1, 334, 335, 336, 337, 33, -1, + -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, + 45, -1, 352, 353, 354, 355, 356, -1, 257, 258, + 259, -1, -1, -1, 263, -1, -1, -1, -1, 268, + -1, -1, 271, 272, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 96, -1, -1, -1, -1, 305, 306, 307, 308, + 309, 310, 311, 312, 313, 314, 315, 316, -1, -1, + -1, -1, -1, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, -1, -1, 334, 335, 336, 337, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 352, 353, 354, 355, 356, -1, -1, + -1, 257, 258, 259, -1, -1, -1, 263, -1, -1, + -1, -1, 268, -1, -1, 271, 272, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 305, + 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, + 316, -1, -1, -1, -1, -1, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, -1, -1, 334, 335, + 336, 337, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 352, 353, 354, 355, + 356, -1, 257, 258, 259, -1, -1, -1, 263, -1, + -1, -1, -1, 268, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, + 315, 316, -1, -1, -1, -1, -1, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, -1, -1, 334, + 335, 336, 337, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 352, 353, 354, + 355, 356, +}; +#define YYFINAL 2 +#ifndef YYDEBUG +#define YYDEBUG 0 +#endif +#define YYMAXTOKEN 366 +#if YYDEBUG +static YYCONST char *YYCONST yyname[] = { +"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +"'!'",0,0,0,"'%'",0,0,"'('","')'","'*'","'+'","','","'-'","'.'","'/'",0,0,0,0,0, +0,0,0,0,0,"':'","';'","'<'","'='","'>'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,"'['",0,"']'","'^'",0,"'`'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,"'{'",0,"'}'",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"LABEL","VARIABLE","NUMBER", +"TEXT","COMMAND_LINE","DELIMITED","ORDINAL","TH","LEFT_ARROW_HEAD", +"RIGHT_ARROW_HEAD","DOUBLE_ARROW_HEAD","LAST","UP","DOWN","LEFT","RIGHT","BOX", +"CIRCLE","ELLIPSE","ARC","LINE","ARROW","MOVE","SPLINE","HEIGHT","RADIUS", +"WIDTH","DIAMETER","FROM","TO","AT","WITH","BY","THEN","DOTTED","DASHED","CHOP", +"SAME","INVISIBLE","LJUST","RJUST","ABOVE","BELOW","OF","THE","WAY","BETWEEN", +"AND","HERE","DOT_N","DOT_E","DOT_W","DOT_S","DOT_NE","DOT_SE","DOT_NW", +"DOT_SW","DOT_C","DOT_START","DOT_END","DOT_X","DOT_Y","DOT_HT","DOT_WID", +"DOT_RAD","SIN","COS","ATAN2","LOG","EXP","SQRT","K_MAX","K_MIN","INT","RAND", +"COPY","THRU","TOP","BOTTOM","UPPER","LOWER","SH","PRINT","CW","CCW","FOR","DO", +"IF","ELSE","ANDAND","OROR","NOTEQUAL","EQUALEQUAL","LESSEQUAL","GREATEREQUAL", +"LEFT_CORNER","RIGHT_CORNER","CENTER","END","START","RESET","UNTIL","PLOT", +"THICKNESS","FILL","ALIGNED","SPRINTF","COMMAND","DEFINE","UNDEF", +}; +static YYCONST char *YYCONST yyrule[] = { +"$accept : top", +"top : optional_separator", +"top : element_list", +"element_list : optional_separator middle_element_list optional_separator", +"middle_element_list : element", +"middle_element_list : middle_element_list separator element", +"optional_separator :", +"optional_separator : separator", +"separator : ';'", +"separator : separator ';'", +"placeless_element : VARIABLE '=' any_expr", +"placeless_element : VARIABLE ':' '=' any_expr", +"placeless_element : UP", +"placeless_element : DOWN", +"placeless_element : LEFT", +"placeless_element : RIGHT", +"placeless_element : COMMAND_LINE", +"placeless_element : COMMAND print_args", +"placeless_element : PRINT print_args", +"$$1 :", +"placeless_element : SH $$1 DELIMITED", +"placeless_element : COPY TEXT", +"$$2 :", +"$$3 :", +"placeless_element : COPY TEXT THRU $$2 DELIMITED $$3 until", +"$$4 :", +"$$5 :", +"placeless_element : COPY THRU $$4 DELIMITED $$5 until", +"$$6 :", +"placeless_element : FOR VARIABLE '=' expr TO expr optional_by DO $$6 DELIMITED", +"placeless_element : simple_if", +"$$7 :", +"placeless_element : simple_if ELSE $$7 DELIMITED", +"placeless_element : reset_variables", +"placeless_element : RESET", +"reset_variables : RESET VARIABLE", +"reset_variables : reset_variables VARIABLE", +"reset_variables : reset_variables ',' VARIABLE", +"print_args : print_arg", +"print_args : print_args print_arg", +"print_arg : expr", +"print_arg : text", +"print_arg : position", +"$$8 :", +"simple_if : IF any_expr THEN $$8 DELIMITED", +"until :", +"until : UNTIL TEXT", +"any_expr : expr", +"any_expr : text_expr", +"text_expr : text EQUALEQUAL text", +"text_expr : text NOTEQUAL text", +"text_expr : text_expr ANDAND text_expr", +"text_expr : text_expr ANDAND expr", +"text_expr : expr ANDAND text_expr", +"text_expr : text_expr OROR text_expr", +"text_expr : text_expr OROR expr", +"text_expr : expr OROR text_expr", +"text_expr : '!' text_expr", +"optional_by :", +"optional_by : BY expr", +"optional_by : BY '*' expr", +"element : object_spec", +"element : LABEL ':' optional_separator element", +"element : LABEL ':' optional_separator position_not_place", +"element : LABEL ':' optional_separator place", +"$$9 :", +"$$10 :", +"element : '{' $$9 element_list '}' $$10 optional_element", +"element : placeless_element", +"optional_element :", +"optional_element : element", +"object_spec : BOX", +"object_spec : CIRCLE", +"object_spec : ELLIPSE", +"object_spec : ARC", +"object_spec : LINE", +"object_spec : ARROW", +"object_spec : MOVE", +"object_spec : SPLINE", +"object_spec : text", +"object_spec : PLOT expr", +"object_spec : PLOT expr text", +"$$11 :", +"object_spec : '[' $$11 element_list ']'", +"object_spec : object_spec HEIGHT expr", +"object_spec : object_spec RADIUS expr", +"object_spec : object_spec WIDTH expr", +"object_spec : object_spec DIAMETER expr", +"object_spec : object_spec expr", +"object_spec : object_spec UP", +"object_spec : object_spec UP expr", +"object_spec : object_spec DOWN", +"object_spec : object_spec DOWN expr", +"object_spec : object_spec RIGHT", +"object_spec : object_spec RIGHT expr", +"object_spec : object_spec LEFT", +"object_spec : object_spec LEFT expr", +"object_spec : object_spec FROM position", +"object_spec : object_spec TO position", +"object_spec : object_spec AT position", +"object_spec : object_spec WITH path", +"object_spec : object_spec BY expr_pair", +"object_spec : object_spec THEN", +"object_spec : object_spec DOTTED", +"object_spec : object_spec DOTTED expr", +"object_spec : object_spec DASHED", +"object_spec : object_spec DASHED expr", +"object_spec : object_spec FILL", +"object_spec : object_spec FILL expr", +"object_spec : object_spec CHOP", +"object_spec : object_spec CHOP expr", +"object_spec : object_spec SAME", +"object_spec : object_spec INVISIBLE", +"object_spec : object_spec LEFT_ARROW_HEAD", +"object_spec : object_spec RIGHT_ARROW_HEAD", +"object_spec : object_spec DOUBLE_ARROW_HEAD", +"object_spec : object_spec CW", +"object_spec : object_spec CCW", +"object_spec : object_spec text", +"object_spec : object_spec LJUST", +"object_spec : object_spec RJUST", +"object_spec : object_spec ABOVE", +"object_spec : object_spec BELOW", +"object_spec : object_spec THICKNESS expr", +"object_spec : object_spec ALIGNED", +"text : TEXT", +"text : SPRINTF '(' TEXT sprintf_args ')'", +"sprintf_args :", +"sprintf_args : sprintf_args ',' expr", +"position : position_not_place", +"position : place", +"position_not_place : expr_pair", +"position_not_place : position '+' expr_pair", +"position_not_place : position '-' expr_pair", +"position_not_place : '(' position ',' position ')'", +"position_not_place : expr between position AND position", +"position_not_place : expr '<' position ',' position '>'", +"between : BETWEEN", +"between : OF THE WAY BETWEEN", +"expr_pair : expr ',' expr", +"expr_pair : '(' expr_pair ')'", +"place : label", +"place : label corner", +"place : corner label", +"place : corner OF label", +"place : HERE", +"label : LABEL", +"label : nth_primitive", +"label : label '.' LABEL", +"ordinal : ORDINAL", +"ordinal : '`' any_expr TH", +"optional_ordinal_last : LAST", +"optional_ordinal_last : ordinal LAST", +"nth_primitive : ordinal object_type", +"nth_primitive : optional_ordinal_last object_type", +"object_type : BOX", +"object_type : CIRCLE", +"object_type : ELLIPSE", +"object_type : ARC", +"object_type : LINE", +"object_type : ARROW", +"object_type : SPLINE", +"object_type : '[' ']'", +"object_type : TEXT", +"label_path : '.' LABEL", +"label_path : label_path '.' LABEL", +"relative_path : corner", +"relative_path : label_path", +"relative_path : label_path corner", +"path : relative_path", +"path : '(' relative_path ',' relative_path ')'", +"path : ORDINAL LAST object_type relative_path", +"path : LAST object_type relative_path", +"path : ORDINAL object_type relative_path", +"path : LABEL relative_path", +"corner : DOT_N", +"corner : DOT_E", +"corner : DOT_W", +"corner : DOT_S", +"corner : DOT_NE", +"corner : DOT_SE", +"corner : DOT_NW", +"corner : DOT_SW", +"corner : DOT_C", +"corner : DOT_START", +"corner : DOT_END", +"corner : TOP", +"corner : BOTTOM", +"corner : LEFT", +"corner : RIGHT", +"corner : UPPER LEFT", +"corner : LOWER LEFT", +"corner : UPPER RIGHT", +"corner : LOWER RIGHT", +"corner : LEFT_CORNER", +"corner : RIGHT_CORNER", +"corner : UPPER LEFT_CORNER", +"corner : LOWER LEFT_CORNER", +"corner : UPPER RIGHT_CORNER", +"corner : LOWER RIGHT_CORNER", +"corner : CENTER", +"corner : START", +"corner : END", +"expr : VARIABLE", +"expr : NUMBER", +"expr : place DOT_X", +"expr : place DOT_Y", +"expr : place DOT_HT", +"expr : place DOT_WID", +"expr : place DOT_RAD", +"expr : expr '+' expr", +"expr : expr '-' expr", +"expr : expr '*' expr", +"expr : expr '/' expr", +"expr : expr '%' expr", +"expr : expr '^' expr", +"expr : '-' expr", +"expr : '(' any_expr ')'", +"expr : SIN '(' any_expr ')'", +"expr : COS '(' any_expr ')'", +"expr : ATAN2 '(' any_expr ',' any_expr ')'", +"expr : LOG '(' any_expr ')'", +"expr : EXP '(' any_expr ')'", +"expr : SQRT '(' any_expr ')'", +"expr : K_MAX '(' any_expr ',' any_expr ')'", +"expr : K_MIN '(' any_expr ',' any_expr ')'", +"expr : INT '(' any_expr ')'", +"expr : RAND '(' any_expr ')'", +"expr : RAND '(' ')'", +"expr : expr '<' expr", +"expr : expr LESSEQUAL expr", +"expr : expr '>' expr", +"expr : expr GREATEREQUAL expr", +"expr : expr EQUALEQUAL expr", +"expr : expr NOTEQUAL expr", +"expr : expr ANDAND expr", +"expr : expr OROR expr", +"expr : '!' expr", +}; +#endif +#define YYLEX yylex() +#define YYEMPTY -1 +#define yyclearin (yychar=(YYEMPTY)) +#define yyerrok (yyerrflag=0) +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif +#ifdef YYSTACKSIZE +#undef YYMAXDEPTH +#define YYMAXDEPTH YYSTACKSIZE +#else +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 10000 +#define YYMAXDEPTH 10000 +#endif +#endif +int yydebug; +int yynerrs; +int yyerrflag; +int yychar; +YYSTYPE yyval; +YYSTYPE yylval; +static short *yyss; +static YYSTYPE *yyvs; +static int yystacksize; +static int yygrow (); +static YYPTR yymalloc YYPARAMS((unsigned)); +static YYPTR yyrealloc YYPARAMS((YYPTR, unsigned)); +#define yyfree(x) free(x) +#line 1529 "pic.y" + +/* 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"; + else { + // this is a fairly feeble attempt at validation of the format + int nspecs = 0; + for (const char *p = form; *p != '\0'; p++) + if (*p == '%') { + if (p[1] == '%') + p++; + else + nspecs++; + } + if (nspecs > 1) { + lex_error("bad format `%1'", form); + return strsave(form); + } + } + sprintf(sprintf_buf, form, n); + return strsave(sprintf_buf); +} + +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'; + sprintf(sprintf_buf, one_format.contents()); + } + else { + if (i >= nv) { + lex_error("too few arguments to sprintf"); + result += one_format; + result += form; + break; + } + one_format += *form++; + one_format += '\0'; + sprintf(sprintf_buf, one_format.contents(), v[i++]); + } + one_format.clear(); + result += sprintf_buf; + } + else + result += *form++; + } + result += '\0'; + return strsave(result.contents()); +} +#line 3397 "y.tab.c" +#define YYABORT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab + +#if YYDEBUG +#ifdef __cplusplus +extern "C" char *getenv(); +#else +extern char *getenv(); +#endif +#endif + +int +yyparse() +{ + register int yym, yyn, yystate; + register YYSTYPE *yyvsp; + register short *yyssp; + short *yysse; +#if YYDEBUG + register YYCONST char *yys; + + if (yys = getenv("YYDEBUG")) + { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif + + yynerrs = 0; + yyerrflag = 0; + yychar = (-1); + + if (yyss == 0) + { + yyss = (short *) yymalloc (YYINITDEPTH * sizeof (short)); + if (yyss == 0) + goto yyabort; + yyvs = (YYSTYPE *) yymalloc (YYINITDEPTH * sizeof (YYSTYPE)); + if (yyvs == 0) + { + yyfree (yyss); + goto yyabort; + } + yystacksize = YYINITDEPTH; + } + yysse = yyss + yystacksize - 1; + yyssp = yyss; + yyvsp = yyvs; + *yyssp = yystate = 0; + +yyloop: + if (yyn = yydefred[yystate]) goto yyreduce; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("yydebug: state %d, reading %d (%s)\n", yystate, + yychar, yys); + } +#endif + } + if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, shifting to state %d\n", + yystate, yytable[yyn]); +#endif + if (yyssp >= yysse) + { + /* FIXME: Rework so there's only one of these. */ + int depth = yyssp - yyss; + if (yygrow () != 0) + goto yyoverflow; + yysse = yyss + yystacksize - 1; + yyssp = yyss + depth; + yyvsp = yyvs + depth; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + yychar = (-1); + if (yyerrflag > 0) --yyerrflag; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yychar) + { + yyn = yytable[yyn]; + goto yyreduce; + } + if (yyerrflag) goto yyinrecovery; +#ifdef lint + goto yynewerror; +#endif +yynewerror: + yyerror("syntax error"); +#ifdef lint + goto yyerrlab; +#endif +yyerrlab: + ++yynerrs; +yyinrecovery: + if (yyerrflag < 3) + { + yyerrflag = 3; + for (;;) + { + if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE) + { +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, error recovery shifting\ + to state %d\n", *yyssp, yytable[yyn]); +#endif + if (yyssp >= yysse) + { + int depth = yyssp - yyss; + if (yygrow () != 0) + goto yyoverflow; + yysse = yyss + yystacksize - 1; + yyssp = yyss + depth; + yyvsp = yyvs + depth; + } + *++yyssp = yystate = yytable[yyn]; + *++yyvsp = yylval; + goto yyloop; + } + else + { +#if YYDEBUG + if (yydebug) + printf("yydebug: error recovery discarding state %d\n", + *yyssp); +#endif + if (yyssp <= yyss) goto yyabort; + --yyssp; + --yyvsp; + } + } + } + else + { + if (yychar == 0) goto yyabort; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("yydebug: state %d, error recovery discards token %d (%s)\n", + yystate, yychar, yys); + } +#endif + yychar = (-1); + goto yyloop; + } +yyreduce: +#if YYDEBUG + if (yydebug) + printf("yydebug: state %d, reducing by rule %d (%s)\n", + yystate, yyn, yyrule[yyn]); +#endif + yym = yylen[yyn]; + yyval = yyvsp[1-yym]; + switch (yyn) + { +case 2: +#line 272 "pic.y" +{ + if (olist.head) + print_picture(olist.head); + } +break; +case 3: +#line 281 "pic.y" +{ yyval.pl = yyvsp[-1].pl; } +break; +case 4: +#line 286 "pic.y" +{ yyval.pl = yyvsp[0].pl; } +break; +case 5: +#line 288 "pic.y" +{ yyval.pl = yyvsp[-2].pl; } +break; +case 10: +#line 303 "pic.y" +{ + define_variable(yyvsp[-2].str, yyvsp[0].x); + a_delete yyvsp[-2].str; + } +break; +case 11: +#line 308 "pic.y" +{ + place *p = lookup_label(yyvsp[-3].str); + if (!p) { + lex_error("variable `%1' not defined", yyvsp[-3].str); + YYABORT; + } + p->obj = 0; + p->x = yyvsp[0].x; + p->y = 0.0; + a_delete yyvsp[-3].str; + } +break; +case 12: +#line 320 "pic.y" +{ current_direction = UP_DIRECTION; } +break; +case 13: +#line 322 "pic.y" +{ current_direction = DOWN_DIRECTION; } +break; +case 14: +#line 324 "pic.y" +{ current_direction = LEFT_DIRECTION; } +break; +case 15: +#line 326 "pic.y" +{ current_direction = RIGHT_DIRECTION; } +break; +case 16: +#line 328 "pic.y" +{ + olist.append(make_command_object(yyvsp[0].lstr.str, yyvsp[0].lstr.filename, + yyvsp[0].lstr.lineno)); + } +break; +case 17: +#line 333 "pic.y" +{ + olist.append(make_command_object(yyvsp[0].lstr.str, yyvsp[0].lstr.filename, + yyvsp[0].lstr.lineno)); + } +break; +case 18: +#line 338 "pic.y" +{ + fprintf(stderr, "%s\n", yyvsp[0].lstr.str); + a_delete yyvsp[0].lstr.str; + fflush(stderr); + } +break; +case 19: +#line 344 "pic.y" +{ delim_flag = 1; } +break; +case 20: +#line 346 "pic.y" +{ + delim_flag = 0; + if (safer_flag) + lex_error("unsafe to run command `%1'", yyvsp[0].str); + else + system(yyvsp[0].str); + a_delete yyvsp[0].str; + } +break; +case 21: +#line 355 "pic.y" +{ + if (yychar < 0) + do_lookahead(); + do_copy(yyvsp[0].lstr.str); + /* do not delete the filename*/ + } +break; +case 22: +#line 362 "pic.y" +{ delim_flag = 2; } +break; +case 23: +#line 364 "pic.y" +{ delim_flag = 0; } +break; +case 24: +#line 366 "pic.y" +{ + if (yychar < 0) + do_lookahead(); + copy_file_thru(yyvsp[-5].lstr.str, yyvsp[-2].str, yyvsp[0].str); + /* do not delete the filename*/ + a_delete yyvsp[-2].str; + a_delete yyvsp[0].str; + } +break; +case 25: +#line 375 "pic.y" +{ delim_flag = 2; } +break; +case 26: +#line 377 "pic.y" +{ delim_flag = 0; } +break; +case 27: +#line 379 "pic.y" +{ + if (yychar < 0) + do_lookahead(); + copy_rest_thru(yyvsp[-2].str, yyvsp[0].str); + a_delete yyvsp[-2].str; + a_delete yyvsp[0].str; + } +break; +case 28: +#line 387 "pic.y" +{ delim_flag = 1; } +break; +case 29: +#line 389 "pic.y" +{ + delim_flag = 0; + if (yychar < 0) + do_lookahead(); + do_for(yyvsp[-8].str, yyvsp[-6].x, yyvsp[-4].x, yyvsp[-3].by.is_multiplicative, yyvsp[-3].by.val, yyvsp[0].str); + } +break; +case 30: +#line 396 "pic.y" +{ + if (yychar < 0) + do_lookahead(); + if (yyvsp[0].if_data.x != 0.0) + push_body(yyvsp[0].if_data.body); + a_delete yyvsp[0].if_data.body; + } +break; +case 31: +#line 404 "pic.y" +{ delim_flag = 1; } +break; +case 32: +#line 406 "pic.y" +{ + delim_flag = 0; + if (yychar < 0) + do_lookahead(); + if (yyvsp[-3].if_data.x != 0.0) + push_body(yyvsp[-3].if_data.body); + else + push_body(yyvsp[0].str); + a_delete yyvsp[-3].if_data.body; + a_delete yyvsp[0].str; + } +break; +case 34: +#line 419 "pic.y" +{ define_variable("scale", 1.0); } +break; +case 35: +#line 424 "pic.y" +{ reset(yyvsp[0].str); a_delete yyvsp[0].str; } +break; +case 36: +#line 426 "pic.y" +{ reset(yyvsp[0].str); a_delete yyvsp[0].str; } +break; +case 37: +#line 428 "pic.y" +{ reset(yyvsp[0].str); a_delete yyvsp[0].str; } +break; +case 38: +#line 433 "pic.y" +{ yyval.lstr = yyvsp[0].lstr; } +break; +case 39: +#line 435 "pic.y" +{ + yyval.lstr.str = new char[strlen(yyvsp[-1].lstr.str) + strlen(yyvsp[0].lstr.str) + 1]; + strcpy(yyval.lstr.str, yyvsp[-1].lstr.str); + strcat(yyval.lstr.str, yyvsp[0].lstr.str); + a_delete yyvsp[-1].lstr.str; + a_delete yyvsp[0].lstr.str; + if (yyvsp[-1].lstr.filename) { + yyval.lstr.filename = yyvsp[-1].lstr.filename; + yyval.lstr.lineno = yyvsp[-1].lstr.lineno; + } + else if (yyvsp[0].lstr.filename) { + yyval.lstr.filename = yyvsp[0].lstr.filename; + yyval.lstr.lineno = yyvsp[0].lstr.lineno; + } + } +break; +case 40: +#line 454 "pic.y" +{ + yyval.lstr.str = new char[GDIGITS + 1]; + sprintf(yyval.lstr.str, "%g", yyvsp[0].x); + yyval.lstr.filename = 0; + yyval.lstr.lineno = 0; + } +break; +case 41: +#line 461 "pic.y" +{ yyval.lstr = yyvsp[0].lstr; } +break; +case 42: +#line 463 "pic.y" +{ + yyval.lstr.str = new char[GDIGITS + 2 + GDIGITS + 1]; + sprintf(yyval.lstr.str, "%g, %g", yyvsp[0].pair.x, yyvsp[0].pair.y); + yyval.lstr.filename = 0; + yyval.lstr.lineno = 0; + } +break; +case 43: +#line 472 "pic.y" +{ delim_flag = 1; } +break; +case 44: +#line 474 "pic.y" +{ delim_flag = 0; yyval.if_data.x = yyvsp[-3].x; yyval.if_data.body = yyvsp[0].str; } +break; +case 45: +#line 479 "pic.y" +{ yyval.str = 0; } +break; +case 46: +#line 481 "pic.y" +{ yyval.str = yyvsp[0].lstr.str; } +break; +case 47: +#line 486 "pic.y" +{ yyval.x = yyvsp[0].x; } +break; +case 48: +#line 488 "pic.y" +{ yyval.x = yyvsp[0].x; } +break; +case 49: +#line 493 "pic.y" +{ + yyval.x = strcmp(yyvsp[-2].lstr.str, yyvsp[0].lstr.str) == 0; + a_delete yyvsp[-2].lstr.str; + a_delete yyvsp[0].lstr.str; + } +break; +case 50: +#line 499 "pic.y" +{ + yyval.x = strcmp(yyvsp[-2].lstr.str, yyvsp[0].lstr.str) != 0; + a_delete yyvsp[-2].lstr.str; + a_delete yyvsp[0].lstr.str; + } +break; +case 51: +#line 505 "pic.y" +{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); } +break; +case 52: +#line 507 "pic.y" +{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); } +break; +case 53: +#line 509 "pic.y" +{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); } +break; +case 54: +#line 511 "pic.y" +{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); } +break; +case 55: +#line 513 "pic.y" +{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); } +break; +case 56: +#line 515 "pic.y" +{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); } +break; +case 57: +#line 517 "pic.y" +{ yyval.x = (yyvsp[0].x == 0.0); } +break; +case 58: +#line 523 "pic.y" +{ yyval.by.val = 1.0; yyval.by.is_multiplicative = 0; } +break; +case 59: +#line 525 "pic.y" +{ yyval.by.val = yyvsp[0].x; yyval.by.is_multiplicative = 0; } +break; +case 60: +#line 527 "pic.y" +{ yyval.by.val = yyvsp[0].x; yyval.by.is_multiplicative = 1; } +break; +case 61: +#line 532 "pic.y" +{ + yyval.pl.obj = yyvsp[0].spec->make_object(¤t_position, + ¤t_direction); + if (yyval.pl.obj == 0) + YYABORT; + delete yyvsp[0].spec; + if (yyval.pl.obj) + olist.append(yyval.pl.obj); + else { + yyval.pl.x = current_position.x; + yyval.pl.y = current_position.y; + } + } +break; +case 62: +#line 546 "pic.y" +{ yyval.pl = yyvsp[0].pl; define_label(yyvsp[-3].str, & yyval.pl); a_delete yyvsp[-3].str; } +break; +case 63: +#line 548 "pic.y" +{ + yyval.pl.obj = 0; + yyval.pl.x = yyvsp[0].pair.x; + yyval.pl.y = yyvsp[0].pair.y; + define_label(yyvsp[-3].str, & yyval.pl); + a_delete yyvsp[-3].str; + } +break; +case 64: +#line 556 "pic.y" +{ + yyval.pl = yyvsp[0].pl; + define_label(yyvsp[-3].str, & yyval.pl); + a_delete yyvsp[-3].str; + } +break; +case 65: +#line 562 "pic.y" +{ + yyval.state.x = current_position.x; + yyval.state.y = current_position.y; + yyval.state.dir = current_direction; + } +break; +case 66: +#line 568 "pic.y" +{ + current_position.x = yyvsp[-2].state.x; + current_position.y = yyvsp[-2].state.y; + current_direction = yyvsp[-2].state.dir; + } +break; +case 67: +#line 574 "pic.y" +{ + yyval.pl = yyvsp[-3].pl; + } +break; +case 68: +#line 578 "pic.y" +{ + yyval.pl.obj = 0; + yyval.pl.x = current_position.x; + yyval.pl.y = current_position.y; + } +break; +case 69: +#line 587 "pic.y" +{} +break; +case 70: +#line 589 "pic.y" +{} +break; +case 71: +#line 594 "pic.y" +{ + yyval.spec = new object_spec(BOX_OBJECT); + } +break; +case 72: +#line 598 "pic.y" +{ + yyval.spec = new object_spec(CIRCLE_OBJECT); + } +break; +case 73: +#line 602 "pic.y" +{ + yyval.spec = new object_spec(ELLIPSE_OBJECT); + } +break; +case 74: +#line 606 "pic.y" +{ + yyval.spec = new object_spec(ARC_OBJECT); + yyval.spec->dir = current_direction; + } +break; +case 75: +#line 611 "pic.y" +{ + yyval.spec = new object_spec(LINE_OBJECT); + lookup_variable("lineht", & yyval.spec->segment_height); + lookup_variable("linewid", & yyval.spec->segment_width); + yyval.spec->dir = current_direction; + } +break; +case 76: +#line 618 "pic.y" +{ + yyval.spec = new object_spec(ARROW_OBJECT); + lookup_variable("lineht", & yyval.spec->segment_height); + lookup_variable("linewid", & yyval.spec->segment_width); + yyval.spec->dir = current_direction; + } +break; +case 77: +#line 625 "pic.y" +{ + yyval.spec = new object_spec(MOVE_OBJECT); + lookup_variable("moveht", & yyval.spec->segment_height); + lookup_variable("movewid", & yyval.spec->segment_width); + yyval.spec->dir = current_direction; + } +break; +case 78: +#line 632 "pic.y" +{ + yyval.spec = new object_spec(SPLINE_OBJECT); + lookup_variable("lineht", & yyval.spec->segment_height); + lookup_variable("linewid", & yyval.spec->segment_width); + yyval.spec->dir = current_direction; + } +break; +case 79: +#line 639 "pic.y" +{ + yyval.spec = new object_spec(TEXT_OBJECT); + yyval.spec->text = new text_item(yyvsp[0].lstr.str, yyvsp[0].lstr.filename, yyvsp[0].lstr.lineno); + } +break; +case 80: +#line 644 "pic.y" +{ + yyval.spec = new object_spec(TEXT_OBJECT); + yyval.spec->text = new text_item(format_number(0, yyvsp[0].x), 0, -1); + } +break; +case 81: +#line 649 "pic.y" +{ + yyval.spec = new object_spec(TEXT_OBJECT); + yyval.spec->text = new text_item(format_number(yyvsp[0].lstr.str, yyvsp[-1].x), + yyvsp[0].lstr.filename, yyvsp[0].lstr.lineno); + a_delete yyvsp[0].lstr.str; + } +break; +case 82: +#line 656 "pic.y" +{ + saved_state *p = new saved_state; + yyval.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()); + } +break; +case 83: +#line 671 "pic.y" +{ + current_position.x = yyvsp[-2].pstate->x; + current_position.y = yyvsp[-2].pstate->y; + current_direction = yyvsp[-2].pstate->dir; + yyval.spec = new object_spec(BLOCK_OBJECT); + olist.wrap_up_block(& yyval.spec->oblist); + yyval.spec->tbl = current_table; + current_table = yyvsp[-2].pstate->tbl; + current_saved_state = yyvsp[-2].pstate->prev; + delete yyvsp[-2].pstate; + } +break; +case 84: +#line 683 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->height = yyvsp[0].x; + yyval.spec->flags |= HAS_HEIGHT; + } +break; +case 85: +#line 689 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->radius = yyvsp[0].x; + yyval.spec->flags |= HAS_RADIUS; + } +break; +case 86: +#line 695 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->width = yyvsp[0].x; + yyval.spec->flags |= HAS_WIDTH; + } +break; +case 87: +#line 701 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->radius = yyvsp[0].x/2.0; + yyval.spec->flags |= HAS_RADIUS; + } +break; +case 88: +#line 707 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= HAS_SEGMENT; + switch (yyval.spec->dir) { + case UP_DIRECTION: + yyval.spec->segment_pos.y += yyvsp[0].x; + break; + case DOWN_DIRECTION: + yyval.spec->segment_pos.y -= yyvsp[0].x; + break; + case RIGHT_DIRECTION: + yyval.spec->segment_pos.x += yyvsp[0].x; + break; + case LEFT_DIRECTION: + yyval.spec->segment_pos.x -= yyvsp[0].x; + break; + } + } +break; +case 89: +#line 726 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->dir = UP_DIRECTION; + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.y += yyval.spec->segment_height; + } +break; +case 90: +#line 733 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->dir = UP_DIRECTION; + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.y += yyvsp[0].x; + } +break; +case 91: +#line 740 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->dir = DOWN_DIRECTION; + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.y -= yyval.spec->segment_height; + } +break; +case 92: +#line 747 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->dir = DOWN_DIRECTION; + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.y -= yyvsp[0].x; + } +break; +case 93: +#line 754 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->dir = RIGHT_DIRECTION; + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.x += yyval.spec->segment_width; + } +break; +case 94: +#line 761 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->dir = RIGHT_DIRECTION; + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.x += yyvsp[0].x; + } +break; +case 95: +#line 768 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->dir = LEFT_DIRECTION; + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.x -= yyval.spec->segment_width; + } +break; +case 96: +#line 775 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->dir = LEFT_DIRECTION; + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.x -= yyvsp[0].x; + } +break; +case 97: +#line 782 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->flags |= HAS_FROM; + yyval.spec->from.x = yyvsp[0].pair.x; + yyval.spec->from.y = yyvsp[0].pair.y; + } +break; +case 98: +#line 789 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + if (yyval.spec->flags & HAS_SEGMENT) + yyval.spec->segment_list = new segment(yyval.spec->segment_pos, + yyval.spec->segment_is_absolute, + yyval.spec->segment_list); + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.x = yyvsp[0].pair.x; + yyval.spec->segment_pos.y = yyvsp[0].pair.y; + yyval.spec->segment_is_absolute = 1; + yyval.spec->flags |= HAS_TO; + yyval.spec->to.x = yyvsp[0].pair.x; + yyval.spec->to.y = yyvsp[0].pair.y; + } +break; +case 99: +#line 804 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->flags |= HAS_AT; + yyval.spec->at.x = yyvsp[0].pair.x; + yyval.spec->at.y = yyvsp[0].pair.y; + if (yyval.spec->type != ARC_OBJECT) { + yyval.spec->flags |= HAS_FROM; + yyval.spec->from.x = yyvsp[0].pair.x; + yyval.spec->from.y = yyvsp[0].pair.y; + } + } +break; +case 100: +#line 816 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->flags |= HAS_WITH; + yyval.spec->with = yyvsp[0].pth; + } +break; +case 101: +#line 822 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->flags |= HAS_SEGMENT; + yyval.spec->segment_pos.x += yyvsp[0].pair.x; + yyval.spec->segment_pos.y += yyvsp[0].pair.y; + } +break; +case 102: +#line 829 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + if (yyval.spec->flags & HAS_SEGMENT) { + yyval.spec->segment_list = new segment(yyval.spec->segment_pos, + yyval.spec->segment_is_absolute, + yyval.spec->segment_list); + yyval.spec->flags &= ~HAS_SEGMENT; + yyval.spec->segment_pos.x = yyval.spec->segment_pos.y = 0.0; + yyval.spec->segment_is_absolute = 0; + } + } +break; +case 103: +#line 841 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= IS_DOTTED; + lookup_variable("dashwid", & yyval.spec->dash_width); + } +break; +case 104: +#line 847 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->flags |= IS_DOTTED; + yyval.spec->dash_width = yyvsp[0].x; + } +break; +case 105: +#line 853 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= IS_DASHED; + lookup_variable("dashwid", & yyval.spec->dash_width); + } +break; +case 106: +#line 859 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->flags |= IS_DASHED; + yyval.spec->dash_width = yyvsp[0].x; + } +break; +case 107: +#line 865 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= IS_DEFAULT_FILLED; + } +break; +case 108: +#line 870 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->flags |= IS_FILLED; + yyval.spec->fill = yyvsp[0].x; + } +break; +case 109: +#line 876 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + /* line chop chop means line chop 0 chop 0*/ + if (yyval.spec->flags & IS_DEFAULT_CHOPPED) { + yyval.spec->flags |= IS_CHOPPED; + yyval.spec->flags &= ~IS_DEFAULT_CHOPPED; + yyval.spec->start_chop = yyval.spec->end_chop = 0.0; + } + else if (yyval.spec->flags & IS_CHOPPED) { + yyval.spec->end_chop = 0.0; + } + else { + yyval.spec->flags |= IS_DEFAULT_CHOPPED; + } + } +break; +case 110: +#line 892 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + if (yyval.spec->flags & IS_DEFAULT_CHOPPED) { + yyval.spec->flags |= IS_CHOPPED; + yyval.spec->flags &= ~IS_DEFAULT_CHOPPED; + yyval.spec->start_chop = 0.0; + yyval.spec->end_chop = yyvsp[0].x; + } + else if (yyval.spec->flags & IS_CHOPPED) { + yyval.spec->end_chop = yyvsp[0].x; + } + else { + yyval.spec->start_chop = yyval.spec->end_chop = yyvsp[0].x; + yyval.spec->flags |= IS_CHOPPED; + } + } +break; +case 111: +#line 909 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= IS_SAME; + } +break; +case 112: +#line 914 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= IS_INVISIBLE; + } +break; +case 113: +#line 919 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= HAS_LEFT_ARROW_HEAD; + } +break; +case 114: +#line 924 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= HAS_RIGHT_ARROW_HEAD; + } +break; +case 115: +#line 929 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= (HAS_LEFT_ARROW_HEAD|HAS_RIGHT_ARROW_HEAD); + } +break; +case 116: +#line 934 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= IS_CLOCKWISE; + } +break; +case 117: +#line 939 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags &= ~IS_CLOCKWISE; + } +break; +case 118: +#line 944 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + text_item **p; + for (p = & yyval.spec->text; *p; p = &(*p)->next) + ; + *p = new text_item(yyvsp[0].lstr.str, yyvsp[0].lstr.filename, yyvsp[0].lstr.lineno); + } +break; +case 119: +#line 952 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + if (yyval.spec->text) { + text_item *p; + for (p = yyval.spec->text; p->next; p = p->next) + ; + p->adj.h = LEFT_ADJUST; + } + } +break; +case 120: +#line 962 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + if (yyval.spec->text) { + text_item *p; + for (p = yyval.spec->text; p->next; p = p->next) + ; + p->adj.h = RIGHT_ADJUST; + } + } +break; +case 121: +#line 972 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + if (yyval.spec->text) { + text_item *p; + for (p = yyval.spec->text; p->next; p = p->next) + ; + p->adj.v = ABOVE_ADJUST; + } + } +break; +case 122: +#line 982 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + if (yyval.spec->text) { + text_item *p; + for (p = yyval.spec->text; p->next; p = p->next) + ; + p->adj.v = BELOW_ADJUST; + } + } +break; +case 123: +#line 992 "pic.y" +{ + yyval.spec = yyvsp[-2].spec; + yyval.spec->flags |= HAS_THICKNESS; + yyval.spec->thickness = yyvsp[0].x; + } +break; +case 124: +#line 998 "pic.y" +{ + yyval.spec = yyvsp[-1].spec; + yyval.spec->flags |= IS_ALIGNED; + } +break; +case 125: +#line 1006 "pic.y" +{ + yyval.lstr = yyvsp[0].lstr; + } +break; +case 126: +#line 1010 "pic.y" +{ + yyval.lstr.filename = yyvsp[-2].lstr.filename; + yyval.lstr.lineno = yyvsp[-2].lstr.lineno; + yyval.lstr.str = do_sprintf(yyvsp[-2].lstr.str, yyvsp[-1].dv.v, yyvsp[-1].dv.nv); + a_delete yyvsp[-1].dv.v; + a_delete yyvsp[-2].lstr.str; + } +break; +case 127: +#line 1021 "pic.y" +{ + yyval.dv.v = 0; + yyval.dv.nv = 0; + yyval.dv.maxv = 0; + } +break; +case 128: +#line 1027 "pic.y" +{ + yyval.dv = yyvsp[-2].dv; + if (yyval.dv.nv >= yyval.dv.maxv) { + if (yyval.dv.nv == 0) { + yyval.dv.v = new double[4]; + yyval.dv.maxv = 4; + } + else { + double *oldv = yyval.dv.v; + yyval.dv.maxv *= 2; + yyval.dv.v = new double[yyval.dv.maxv]; + memcpy(yyval.dv.v, oldv, yyval.dv.nv*sizeof(double)); + a_delete oldv; + } + } + yyval.dv.v[yyval.dv.nv] = yyvsp[0].x; + yyval.dv.nv += 1; + } +break; +case 129: +#line 1049 "pic.y" +{ yyval.pair = yyvsp[0].pair; } +break; +case 130: +#line 1051 "pic.y" +{ + position pos = yyvsp[0].pl; + yyval.pair.x = pos.x; + yyval.pair.y = pos.y; + } +break; +case 131: +#line 1060 "pic.y" +{ yyval.pair = yyvsp[0].pair; } +break; +case 132: +#line 1062 "pic.y" +{ + yyval.pair.x = yyvsp[-2].pair.x + yyvsp[0].pair.x; + yyval.pair.y = yyvsp[-2].pair.y + yyvsp[0].pair.y; + } +break; +case 133: +#line 1067 "pic.y" +{ + yyval.pair.x = yyvsp[-2].pair.x - yyvsp[0].pair.x; + yyval.pair.y = yyvsp[-2].pair.y - yyvsp[0].pair.y; + } +break; +case 134: +#line 1072 "pic.y" +{ + yyval.pair.x = yyvsp[-3].pair.x; + yyval.pair.y = yyvsp[-1].pair.y; + } +break; +case 135: +#line 1077 "pic.y" +{ + yyval.pair.x = (1.0 - yyvsp[-4].x)*yyvsp[-2].pair.x + yyvsp[-4].x*yyvsp[0].pair.x; + yyval.pair.y = (1.0 - yyvsp[-4].x)*yyvsp[-2].pair.y + yyvsp[-4].x*yyvsp[0].pair.y; + } +break; +case 136: +#line 1082 "pic.y" +{ + yyval.pair.x = (1.0 - yyvsp[-5].x)*yyvsp[-3].pair.x + yyvsp[-5].x*yyvsp[-1].pair.x; + yyval.pair.y = (1.0 - yyvsp[-5].x)*yyvsp[-3].pair.y + yyvsp[-5].x*yyvsp[-1].pair.y; + } +break; +case 139: +#line 1095 "pic.y" +{ yyval.pair.x = yyvsp[-2].x; yyval.pair.y = yyvsp[0].x; } +break; +case 140: +#line 1097 "pic.y" +{ yyval.pair = yyvsp[-1].pair; } +break; +case 141: +#line 1102 "pic.y" +{ yyval.pl = yyvsp[0].pl; } +break; +case 142: +#line 1104 "pic.y" +{ + path pth(yyvsp[0].crn); + if (!pth.follow(yyvsp[-1].pl, & yyval.pl)) + YYABORT; + } +break; +case 143: +#line 1110 "pic.y" +{ + path pth(yyvsp[-1].crn); + if (!pth.follow(yyvsp[0].pl, & yyval.pl)) + YYABORT; + } +break; +case 144: +#line 1116 "pic.y" +{ + path pth(yyvsp[-2].crn); + if (!pth.follow(yyvsp[0].pl, & yyval.pl)) + YYABORT; + } +break; +case 145: +#line 1122 "pic.y" +{ + yyval.pl.x = current_position.x; + yyval.pl.y = current_position.y; + yyval.pl.obj = 0; + } +break; +case 146: +#line 1131 "pic.y" +{ + place *p = lookup_label(yyvsp[0].str); + if (!p) { + lex_error("there is no place `%1'", yyvsp[0].str); + YYABORT; + } + yyval.pl = *p; + a_delete yyvsp[0].str; + } +break; +case 147: +#line 1141 "pic.y" +{ + yyval.pl.obj = yyvsp[0].obj; + } +break; +case 148: +#line 1145 "pic.y" +{ + path pth(yyvsp[0].str); + if (!pth.follow(yyvsp[-2].pl, & yyval.pl)) + YYABORT; + } +break; +case 149: +#line 1154 "pic.y" +{ yyval.n = yyvsp[0].n; } +break; +case 150: +#line 1156 "pic.y" +{ + /* XXX Check for overflow (and non-integers?).*/ + yyval.n = (int)yyvsp[-1].x; + } +break; +case 151: +#line 1164 "pic.y" +{ yyval.n = 1; } +break; +case 152: +#line 1166 "pic.y" +{ yyval.n = yyvsp[-1].n; } +break; +case 153: +#line 1171 "pic.y" +{ + int count = 0; + object *p; + for (p = olist.head; p != 0; p = p->next) + if (p->type() == yyvsp[0].obtype && ++count == yyvsp[-1].n) { + yyval.obj = p; + break; + } + if (p == 0) { + lex_error("there is no %1%2 %3", yyvsp[-1].n, ordinal_postfix(yyvsp[-1].n), + object_type_name(yyvsp[0].obtype)); + YYABORT; + } + } +break; +case 154: +#line 1186 "pic.y" +{ + int count = 0; + object *p; + for (p = olist.tail; p != 0; p = p->prev) + if (p->type() == yyvsp[0].obtype && ++count == yyvsp[-1].n) { + yyval.obj = p; + break; + } + if (p == 0) { + lex_error("there is no %1%2 last %3", yyvsp[-1].n, + ordinal_postfix(yyvsp[-1].n), object_type_name(yyvsp[0].obtype)); + YYABORT; + } + } +break; +case 155: +#line 1204 "pic.y" +{ yyval.obtype = BOX_OBJECT; } +break; +case 156: +#line 1206 "pic.y" +{ yyval.obtype = CIRCLE_OBJECT; } +break; +case 157: +#line 1208 "pic.y" +{ yyval.obtype = ELLIPSE_OBJECT; } +break; +case 158: +#line 1210 "pic.y" +{ yyval.obtype = ARC_OBJECT; } +break; +case 159: +#line 1212 "pic.y" +{ yyval.obtype = LINE_OBJECT; } +break; +case 160: +#line 1214 "pic.y" +{ yyval.obtype = ARROW_OBJECT; } +break; +case 161: +#line 1216 "pic.y" +{ yyval.obtype = SPLINE_OBJECT; } +break; +case 162: +#line 1218 "pic.y" +{ yyval.obtype = BLOCK_OBJECT; } +break; +case 163: +#line 1220 "pic.y" +{ yyval.obtype = TEXT_OBJECT; } +break; +case 164: +#line 1225 "pic.y" +{ + yyval.pth = new path(yyvsp[0].str); + } +break; +case 165: +#line 1229 "pic.y" +{ + yyval.pth = yyvsp[-2].pth; + yyval.pth->append(yyvsp[0].str); + } +break; +case 166: +#line 1237 "pic.y" +{ + yyval.pth = new path(yyvsp[0].crn); + } +break; +case 167: +#line 1244 "pic.y" +{ + yyval.pth = yyvsp[0].pth; + } +break; +case 168: +#line 1248 "pic.y" +{ + yyval.pth = yyvsp[-1].pth; + yyval.pth->append(yyvsp[0].crn); + } +break; +case 169: +#line 1256 "pic.y" +{ + yyval.pth = yyvsp[0].pth; + } +break; +case 170: +#line 1260 "pic.y" +{ + yyval.pth = yyvsp[-3].pth; + yyval.pth->set_ypath(yyvsp[-1].pth); + } +break; +case 171: +#line 1266 "pic.y" +{ + lex_warning("`%1%2 last %3' in `with' argument ignored", + yyvsp[-3].n, ordinal_postfix(yyvsp[-3].n), object_type_name(yyvsp[-1].obtype)); + yyval.pth = yyvsp[0].pth; + } +break; +case 172: +#line 1272 "pic.y" +{ + lex_warning("`last %1' in `with' argument ignored", + object_type_name(yyvsp[-1].obtype)); + yyval.pth = yyvsp[0].pth; + } +break; +case 173: +#line 1278 "pic.y" +{ + lex_warning("`%1%2 %3' in `with' argument ignored", + yyvsp[-2].n, ordinal_postfix(yyvsp[-2].n), object_type_name(yyvsp[-1].obtype)); + yyval.pth = yyvsp[0].pth; + } +break; +case 174: +#line 1284 "pic.y" +{ + lex_warning("initial `%1' in `with' argument ignored", yyvsp[-1].str); + a_delete yyvsp[-1].str; + yyval.pth = yyvsp[0].pth; + } +break; +case 175: +#line 1293 "pic.y" +{ yyval.crn = &object::north; } +break; +case 176: +#line 1295 "pic.y" +{ yyval.crn = &object::east; } +break; +case 177: +#line 1297 "pic.y" +{ yyval.crn = &object::west; } +break; +case 178: +#line 1299 "pic.y" +{ yyval.crn = &object::south; } +break; +case 179: +#line 1301 "pic.y" +{ yyval.crn = &object::north_east; } +break; +case 180: +#line 1303 "pic.y" +{ yyval.crn = &object:: south_east; } +break; +case 181: +#line 1305 "pic.y" +{ yyval.crn = &object::north_west; } +break; +case 182: +#line 1307 "pic.y" +{ yyval.crn = &object::south_west; } +break; +case 183: +#line 1309 "pic.y" +{ yyval.crn = &object::center; } +break; +case 184: +#line 1311 "pic.y" +{ yyval.crn = &object::start; } +break; +case 185: +#line 1313 "pic.y" +{ yyval.crn = &object::end; } +break; +case 186: +#line 1315 "pic.y" +{ yyval.crn = &object::north; } +break; +case 187: +#line 1317 "pic.y" +{ yyval.crn = &object::south; } +break; +case 188: +#line 1319 "pic.y" +{ yyval.crn = &object::west; } +break; +case 189: +#line 1321 "pic.y" +{ yyval.crn = &object::east; } +break; +case 190: +#line 1323 "pic.y" +{ yyval.crn = &object::north_west; } +break; +case 191: +#line 1325 "pic.y" +{ yyval.crn = &object::south_west; } +break; +case 192: +#line 1327 "pic.y" +{ yyval.crn = &object::north_east; } +break; +case 193: +#line 1329 "pic.y" +{ yyval.crn = &object::south_east; } +break; +case 194: +#line 1331 "pic.y" +{ yyval.crn = &object::west; } +break; +case 195: +#line 1333 "pic.y" +{ yyval.crn = &object::east; } +break; +case 196: +#line 1335 "pic.y" +{ yyval.crn = &object::north_west; } +break; +case 197: +#line 1337 "pic.y" +{ yyval.crn = &object::south_west; } +break; +case 198: +#line 1339 "pic.y" +{ yyval.crn = &object::north_east; } +break; +case 199: +#line 1341 "pic.y" +{ yyval.crn = &object::south_east; } +break; +case 200: +#line 1343 "pic.y" +{ yyval.crn = &object::center; } +break; +case 201: +#line 1345 "pic.y" +{ yyval.crn = &object::start; } +break; +case 202: +#line 1347 "pic.y" +{ yyval.crn = &object::end; } +break; +case 203: +#line 1352 "pic.y" +{ + if (!lookup_variable(yyvsp[0].str, & yyval.x)) { + lex_error("there is no variable `%1'", yyvsp[0].str); + YYABORT; + } + a_delete yyvsp[0].str; + } +break; +case 204: +#line 1360 "pic.y" +{ yyval.x = yyvsp[0].x; } +break; +case 205: +#line 1362 "pic.y" +{ + if (yyvsp[-1].pl.obj != 0) + yyval.x = yyvsp[-1].pl.obj->origin().x; + else + yyval.x = yyvsp[-1].pl.x; + } +break; +case 206: +#line 1369 "pic.y" +{ + if (yyvsp[-1].pl.obj != 0) + yyval.x = yyvsp[-1].pl.obj->origin().y; + else + yyval.x = yyvsp[-1].pl.y; + } +break; +case 207: +#line 1376 "pic.y" +{ + if (yyvsp[-1].pl.obj != 0) + yyval.x = yyvsp[-1].pl.obj->height(); + else + yyval.x = 0.0; + } +break; +case 208: +#line 1383 "pic.y" +{ + if (yyvsp[-1].pl.obj != 0) + yyval.x = yyvsp[-1].pl.obj->width(); + else + yyval.x = 0.0; + } +break; +case 209: +#line 1390 "pic.y" +{ + if (yyvsp[-1].pl.obj != 0) + yyval.x = yyvsp[-1].pl.obj->radius(); + else + yyval.x = 0.0; + } +break; +case 210: +#line 1397 "pic.y" +{ yyval.x = yyvsp[-2].x + yyvsp[0].x; } +break; +case 211: +#line 1399 "pic.y" +{ yyval.x = yyvsp[-2].x - yyvsp[0].x; } +break; +case 212: +#line 1401 "pic.y" +{ yyval.x = yyvsp[-2].x * yyvsp[0].x; } +break; +case 213: +#line 1403 "pic.y" +{ + if (yyvsp[0].x == 0.0) { + lex_error("division by zero"); + YYABORT; + } + yyval.x = yyvsp[-2].x/yyvsp[0].x; + } +break; +case 214: +#line 1411 "pic.y" +{ + if (yyvsp[0].x == 0.0) { + lex_error("modulus by zero"); + YYABORT; + } + yyval.x = fmod(yyvsp[-2].x, yyvsp[0].x); + } +break; +case 215: +#line 1419 "pic.y" +{ + errno = 0; + yyval.x = pow(yyvsp[-2].x, yyvsp[0].x); + if (errno == EDOM) { + lex_error("arguments to `^' operator out of domain"); + YYABORT; + } + if (errno == ERANGE) { + lex_error("result of `^' operator out of range"); + YYABORT; + } + } +break; +case 216: +#line 1432 "pic.y" +{ yyval.x = -yyvsp[0].x; } +break; +case 217: +#line 1434 "pic.y" +{ yyval.x = yyvsp[-1].x; } +break; +case 218: +#line 1436 "pic.y" +{ + errno = 0; + yyval.x = sin(yyvsp[-1].x); + if (errno == ERANGE) { + lex_error("sin result out of range"); + YYABORT; + } + } +break; +case 219: +#line 1445 "pic.y" +{ + errno = 0; + yyval.x = cos(yyvsp[-1].x); + if (errno == ERANGE) { + lex_error("cos result out of range"); + YYABORT; + } + } +break; +case 220: +#line 1454 "pic.y" +{ + errno = 0; + yyval.x = atan2(yyvsp[-3].x, yyvsp[-1].x); + if (errno == EDOM) { + lex_error("atan2 argument out of domain"); + YYABORT; + } + if (errno == ERANGE) { + lex_error("atan2 result out of range"); + YYABORT; + } + } +break; +case 221: +#line 1467 "pic.y" +{ + errno = 0; + yyval.x = log10(yyvsp[-1].x); + if (errno == ERANGE) { + lex_error("log result out of range"); + YYABORT; + } + } +break; +case 222: +#line 1476 "pic.y" +{ + errno = 0; + yyval.x = pow(10.0, yyvsp[-1].x); + if (errno == ERANGE) { + lex_error("exp result out of range"); + YYABORT; + } + } +break; +case 223: +#line 1485 "pic.y" +{ + errno = 0; + yyval.x = sqrt(yyvsp[-1].x); + if (errno == EDOM) { + lex_error("sqrt argument out of domain"); + YYABORT; + } + } +break; +case 224: +#line 1494 "pic.y" +{ yyval.x = yyvsp[-3].x > yyvsp[-1].x ? yyvsp[-3].x : yyvsp[-1].x; } +break; +case 225: +#line 1496 "pic.y" +{ yyval.x = yyvsp[-3].x < yyvsp[-1].x ? yyvsp[-3].x : yyvsp[-1].x; } +break; +case 226: +#line 1498 "pic.y" +{ yyval.x = floor(yyvsp[-1].x); } +break; +case 227: +#line 1500 "pic.y" +{ yyval.x = 1.0 + floor(((rand()&0x7fff)/double(0x7fff))*yyvsp[-1].x); } +break; +case 228: +#line 1502 "pic.y" +{ + /* return a random number in the range [0,1) */ + /* portable, but not very random */ + yyval.x = (rand() & 0x7fff) / double(0x8000); + } +break; +case 229: +#line 1508 "pic.y" +{ yyval.x = (yyvsp[-2].x < yyvsp[0].x); } +break; +case 230: +#line 1510 "pic.y" +{ yyval.x = (yyvsp[-2].x <= yyvsp[0].x); } +break; +case 231: +#line 1512 "pic.y" +{ yyval.x = (yyvsp[-2].x > yyvsp[0].x); } +break; +case 232: +#line 1514 "pic.y" +{ yyval.x = (yyvsp[-2].x >= yyvsp[0].x); } +break; +case 233: +#line 1516 "pic.y" +{ yyval.x = (yyvsp[-2].x == yyvsp[0].x); } +break; +case 234: +#line 1518 "pic.y" +{ yyval.x = (yyvsp[-2].x != yyvsp[0].x); } +break; +case 235: +#line 1520 "pic.y" +{ yyval.x = (yyvsp[-2].x != 0.0 && yyvsp[0].x != 0.0); } +break; +case 236: +#line 1522 "pic.y" +{ yyval.x = (yyvsp[-2].x != 0.0 || yyvsp[0].x != 0.0); } +break; +case 237: +#line 1524 "pic.y" +{ yyval.x = (yyvsp[0].x == 0.0); } +break; +#line 5174 "y.tab.c" + } + yyssp -= yym; + yystate = *yyssp; + yyvsp -= yym; + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) + { +#if YYDEBUG + if (yydebug) + printf("yydebug: after reduction, shifting from state 0 to\ + state %d\n", YYFINAL); +#endif + yystate = YYFINAL; + *++yyssp = YYFINAL; + *++yyvsp = yyval; + if (yychar < 0) + { + if ((yychar = yylex()) < 0) yychar = 0; +#if YYDEBUG + if (yydebug) + { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + printf("yydebug: state %d, reading %d (%s)\n", + YYFINAL, yychar, yys); + } +#endif + } + if (yychar == 0) goto yyaccept; + goto yyloop; + } + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) + yystate = yytable[yyn]; + else + yystate = yydgoto[yym]; +#if YYDEBUG + if (yydebug) + printf("yydebug: after reduction, shifting from state %d \ +to state %d\n", *yyssp, yystate); +#endif + if (yyssp >= yysse) + { + int depth = yyssp - yyss; + if (yygrow () != 0) + goto yyoverflow; + yysse = yyss + yystacksize - 1; + yyssp = yyss + depth; + yyvsp = yyvs + depth; + } + *++yyssp = yystate; + *++yyvsp = yyval; + goto yyloop; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + return (1); +yyaccept: + return (0); +} + +static int +yygrow () +{ + int old_stacksize = yystacksize; + short *new_yyss; + YYSTYPE *new_yyvs; + + if (yystacksize >= YYMAXDEPTH) + return (1); + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; +#if YYDEBUG + if (yydebug) + printf("yydebug: growing stack size from %d to %d\n", + old_stacksize, yystacksize); +#endif + new_yyss = (short *) yyrealloc (yyss, yystacksize * sizeof (short)); + if (new_yyss == 0) + return (1); + new_yyvs = (YYSTYPE *) yyrealloc (yyvs, yystacksize * sizeof (YYSTYPE)); + if (new_yyvs == 0) + { + yyfree (new_yyss); + return (1); + } + yyss = new_yyss; + yyvs = new_yyvs; + return (0); +} + +static YYPTR +YYDEFUN (yymalloc, (bytes), unsigned bytes) +{ + YYPTR ptr = (YYPTR) malloc (bytes); + if (ptr != 0) return (ptr); + yyerror ("yyparse: memory exhausted"); + return (0); +} + +static YYPTR +YYDEFUN (yyrealloc, (old, bytes), YYPTR old YYAND unsigned bytes) +{ + YYPTR ptr = (YYPTR) realloc (old, bytes); + if (ptr != 0) return (ptr); + yyerror ("yyparse: memory exhausted"); + return (0); +} diff --git a/contrib/groff/pic/pic.h b/contrib/groff/pic/pic.h new file mode 100644 index 000000000000..70e95676e9f3 --- /dev/null +++ b/contrib/groff/pic/pic.h @@ -0,0 +1,102 @@ +// -*- C++ -*- +/* 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 <stdio.h> +#include <string.h> +#include <math.h> +#include <stdlib.h> +#include <errno.h> + +extern "C" { + double hypot(double, double); +} + +#include "assert.h" +#include "cset.h" +#include "lib.h" +#include "stringclass.h" +#include "errarg.h" +#include "error.h" +#include "position.h" +#include "text.h" +#include "output.h" + +#ifndef M_SQRT2 +#define M_SQRT2 1.41421356237309504880 +#endif + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +class input { + input *next; +public: + input(); + virtual ~input(); + virtual int get() = 0; + virtual int peek() = 0; + virtual int get_location(const char **, int *); + friend class input_stack; + friend class copy_rest_thru_input; +}; + +class file_input : public input { + FILE *fp; + const char *filename; + int lineno; + string line; + const char *ptr; + int read_line(); +public: + file_input(FILE *, const char *); + ~file_input(); + int get(); + int peek(); + int get_location(const char **, int *); +}; + +void lex_init(input *); +int get_location(char **, int *); + +void do_copy(const char *file); +void parse_init(); +void parse_cleanup(); + +void lex_error(const char *message, + const errarg &arg1 = empty_errarg, + const errarg &arg2 = empty_errarg, + const errarg &arg3 = empty_errarg); + +void lex_warning(const char *message, + const errarg &arg1 = empty_errarg, + const errarg &arg2 = empty_errarg, + const errarg &arg3 = empty_errarg); + +void lex_cleanup(); + +extern int flyback_flag; +extern int command_char; +// zero_length_line_flag is non-zero if zero-length lines are drawn +// as dots by the output device +extern int zero_length_line_flag; +extern int driver_extension_flag; +extern int compatible_flag; +extern int safer_flag; diff --git a/contrib/groff/pic/pic.man b/contrib/groff/pic/pic.man new file mode 100644 index 000000000000..5e2d142f331c --- /dev/null +++ b/contrib/groff/pic/pic.man @@ -0,0 +1,753 @@ +.ig \"-*- nroff -*- +Copyright (C) 1989-1995 Free Software Foundation, Inc. + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the +entire resulting derived work is distributed under the terms of a +permission notice identical to this one. + +Permission is granted to copy and distribute translations of this +manual into another language, under the above conditions for modified +versions, except that this permission notice may be included in +translations approved by the Free Software Foundation instead of in +the original English. +.. +.\" Like TP, but if specified indent is more than half +.\" the current line-length - indent, use the default indent. +.de Tp +.ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP +.el .TP "\\$1" +.. +.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X +.el .ds tx TeX +.ie \n(.g .ds ic \/ +.el .ds ic \^ +.\" The BSD man macros can't handle " in arguments to font change macros, +.\" so use \(ts instead of ". +.tr \(ts" +.TH @G@PIC @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@" +.SH NAME +@g@pic \- compile pictures for troff or TeX +.SH SYNOPSIS +.B @g@pic +[ +.B \-nvC +] +[ +.I filename +\&.\|.\|. +] +.br +.B @g@pic +.B \-t +[ +.B \-cvzC +] +[ +.I filename +\&.\|.\|. +] +.SH DESCRIPTION +.LP +This manual page describes the GNU version of +.BR pic , +which is part of the groff document formatting system. +.B pic +compiles descriptions of pictures embedded within +.B troff +or \*(tx input files into commands that are understood by \*(tx or +.BR troff . +Each picture starts with a line beginning with +.B .PS +and ends with a line beginning with +.BR .PE . +Anything outside of +.B .PS +and +.B .PE +is passed through without change. +.LP +It is the user's responsibility to provide appropriate definitions of the +.B PS +and +.B PE +macros. +When the macro package being used does not supply such definitions +(for example, old versions of \-ms), +appropriate definitions can be obtained with +.BR \-mpic : +these will center each picture. +.SH OPTIONS +.LP +Options that do not take arguments may be grouped behind a single +.BR \- . +The special option +.B \-\^\- +can be used to mark the end of the options. +A filename of +.B \- +refers to the standard input. +.TP +.B \-C +Recognize +.B .PS +and +.B .PE +even when followed by a character other than space or newline. +.TP +.B \-S +Safer mode; do not execute +.B sh +commands. +This can be useful when operating on untrustworthy input. +.TP +.B \-n +Don't use the groff extensions to the troff drawing commands. +You should use this if you are using a postprocessor that doesn't support +these extensions. +The extensions are described in +.BR groff_out (@MAN5EXT@). +The +.B \-n +option also causes pic +not to use zero-length lines to draw dots in troff mode. +.TP +.B \-t +\*(tx mode. +.TP +.B \-c +Be more compatible with +.BR tpic . +Implies +.BR \-t . +Lines beginning with +.B \e +are not passed through transparently. +Lines beginning with +.B . +are passed through with the initial +.B . +changed to +.BR \e . +A line beginning with +.B .ps +is given special treatment: +it takes an optional integer argument specifying +the line thickness (pen size) in milliinches; +a missing argument restores the previous line thickness; +the default line thickness is 8 milliinches. +The line thickness thus specified takes effect only +when a non-negative line thickness has not been +specified by use of the +.B thickness +attribute or by setting the +.B linethick +variable. +.TP +.B \-v +Print the version number. +.TP +.B \-z +In \*(tx mode draw dots using zero-length lines. +.LP +The following options supported by other versions of +.B pic +are ignored: +.TP +.B \-D +Draw all lines using the \eD escape sequence. +.B pic +always does this. +.TP +.BI \-T \ dev +Generate output for the +.B troff +device +.IR dev . +This is unnecessary because the +.B troff +output generated by +.B pic +is device-independent. +.SH USAGE +This section describes only the differences between GNU pic and the original +version of pic. +Many of these differences also apply to newer versions of Unix pic. +.SS \*(tx mode +.LP +\*(tx mode is enabled by the +.B \-t +option. +In \*(tx mode, pic will define a vbox called +.B \egraph +for each picture. +You must yourself print that vbox using, for example, the command +.RS +.LP +.B +\ecenterline{\ebox\egraph} +.RE +.LP +Actually, since the vbox has a height of zero this will produce +slightly more vertical space above the picture than below it; +.RS +.LP +.B +\ecenterline{\eraise 1em\ebox\egraph} +.RE +.LP +would avoid this. +.LP +You must use a \*(tx driver that supports the +.B tpic +specials, version 2. +.LP +Lines beginning with +.B \e +are passed through transparently; a +.B % +is added to the end of the line to avoid unwanted spaces. +You can safely use this feature to change fonts or to +change the value of +.BR \ebaselineskip . +Anything else may well produce undesirable results; use at your own risk. +Lines beginning with a period are not given any special treatment. +.SS Commands +.TP +\fBfor\fR \fIvariable\fR \fB=\fR \fIexpr1\fR \fBto\fR \fIexpr2\fR \ +[\fBby\fR [\fB*\fR]\fIexpr3\fR] \fBdo\fR \fIX\fR \fIbody\fR \fIX\fR +Set +.I variable +to +.IR expr1 . +While the value of +.I variable +is less than or equal to +.IR expr2 , +do +.I body +and increment +.I variable +by +.IR expr3 ; +if +.B by +is not given, increment +.I variable +by 1. +If +.I expr3 +is prefixed by +.B * +then +.I variable +will instead be multiplied by +.IR expr3 . +.I X +can be any character not occurring in +.IR body . +.TP +\fBif\fR \fIexpr\fR \fBthen\fR \fIX\fR \fIif-true\fR \fIX\fR \ +[\fBelse\fR \fIY\fR \fIif-false\fR \fIY\fR] +Evaluate +.IR expr ; +if it is non-zero then do +.IR if-true , +otherwise do +.IR if-false . +.I X +can be any character not occurring in +.IR if-true . +.I Y +can be any character not occurring in +.IR if-false . +.TP +\fBprint\fR \fIarg\fR\|.\|.\|. +Concatenate the arguments and print as a line on stderr. +Each +.I arg +must be an expression, a position, or text. +This is useful for debugging. +.TP +\fBcommand\fR \fIarg\fR\|.\|.\|. +Concatenate the arguments +and pass them through as a line to troff or\*(tx. +Each +.I arg +must be an expression, a position, or text. +This has a similar effect to a line beginning with +.B . +or +.BR \e , +but allows the values of variables to be passed through. +.TP +\fBsh\fR \fIX\fR \fIcommand\fR \fIX\fR +Pass +.I command +to a shell. +.I X +can be any character not occurring in +.IR command . +.TP +\fBcopy\fR \fB"\fIfilename\fB"\fR +Include +.I filename +at this point in the file. +.TP +\fBcopy\fR [\fB"\fIfilename\fB"\fR] \fBthru\fR \fIX\fR \fIbody\fR \fIX\fR \ +[\fBuntil\fR \fB"\fIword\*(ic\fB"\fR] +.ns +.TP +\fBcopy\fR [\fB"\fIfilename\fB"\fR] \fBthru\fR \fImacro\fR \ +[\fBuntil\fR \fB"\fIword\*(ic\fB"\fR] +This construct does +.I body +once for each line of +.IR filename ; +the line is split into blank-delimited words, +and occurrences of +.BI $ i +in +.IR body , +for +.I i +between 1 and 9, +are replaced by the +.IR i -th +word of the line. +If +.I filename +is not given, lines are taken from the current input up to +.BR .PE . +If an +.B until +clause is specified, +lines will be read only until a line the first word of which is +.IR word ; +that line will then be discarded. +.I X +can be any character not occurring in +.IR body . +For example, +.RS +.IP +.ft B +.nf +\&.PS +copy thru % circle at ($1,$2) % until "END" +1 2 +3 4 +5 6 +END +box +\&.PE +.ft +.fi +.RE +.IP +is equivalent to +.RS +.IP +.ft B +.nf +\&.PS +circle at (1,2) +circle at (3,4) +circle at (5,6) +box +\&.PE +.ft +.fi +.RE +.IP +The commands to be performed for each line can also be taken +from a macro defined earlier by giving the name of the macro +as the argument to +.BR thru . +.LP +.B reset +.br +.ns +.TP +\fBreset\fI variable1\fB,\fI variable2 .\^.\^. +Reset pre-defined variables +.IR variable1 , +.I variable2 +\&.\^.\^. to their default values. +If no arguments are given, reset all pre-defined variables +to their default values. +Note that assigning a value to +.B scale +also causes all pre-defined variables that control dimensions +to be reset to their default values times the new value of scale. +.TP +\fBplot\fR \fIexpr\fR [\fB"\fItext\*(ic\fB"\fR] +This is a text object which is constructed by using +.I text +as a format string for sprintf +with an argument of +.IR expr . +If +.I text +is omitted a format string of +.B "\(ts%g\(ts" +is used. +Attributes can be specified in the same way as for a normal text +object. +Be very careful that you specify an appropriate format string; +pic does only very limited checking of the string. +This is deprecated in favour of +.BR sprintf . +.TP +.IB variable := expr +This is similar to +.B = +except +.I variable +must already be defined, +and the value of +.I variable +will be changed only in the innermost block in which it is defined. +(By contrast, +.B = +defines the variable in the current block if it is not already defined there, +and then changes the value in the current block.) +.LP +Arguments of the form +.IP +.IR X\ anything\ X +.LP +are also allowed to be of the form +.IP +.BI {\ anything\ } +.LP +In this case +.I anything +can contain balanced occurrences of +.B { +and +.BR } . +Strings may contain +.I X +or imbalanced occurrences of +.B { +and +.BR } . +.SS Expressions +The syntax for expressions has been significantly extended: +.LP +.IB x\ ^\ y +(exponentiation) +.br +.BI sin( x ) +.br +.BI cos( x ) +.br +.BI atan2( y , \ x ) +.br +.BI log( x ) +(base 10) +.br +.BI exp( x ) +(base 10, ie 10\v'-.4m'\fIx\*(ic\fR\v'.4m') +.br +.BI sqrt( x ) +.br +.BI int( x ) +.br +.B rand() +(return a random number between 0 and 1) +.br +.BI rand( x ) +(return a random number between 1 and +.IR x ; +deprecated) +.br +.BI max( e1 , \ e2 ) +.br +.BI min( e1 , \ e2 ) +.br +.BI ! e +.br +\fIe1\fB && \fIe2\fR +.br +\fIe1\fB || \fIe2\fR +.br +\fIe1\fB == \fIe2\fR +.br +\fIe1\fB != \fIe2\fR +.br +\fIe1\fB >= \fIe2\fR +.br +\fIe1\fB > \fIe2\fR +.br +\fIe1\fB <= \fIe2\fR +.br +\fIe1\fB < \fIe2\fR +.br +\fB"\fIstr1\*(ic\fB" == "\fIstr2\*(ic\fB"\fR +.br +\fB"\fIstr1\*(ic\fB" != "\fIstr2\*(ic\fB"\fR +.br +.LP +String comparison expressions must be parenthesised in some contexts +to avoid ambiguity. +.SS Other Changes +.LP +A bare expression, +.IR expr , +is acceptable as an attribute; +it is equivalent to +.IR dir\ expr , +where +.I dir +is the current direction. +For example +.IP +.B line 2i +.LP +means draw a line 2 inches long in the current direction. +.LP +The maximum width and height of the picture are taken from the variables +.B maxpswid +and +.BR maxpsht . +Initially these have values 8.5 and 11. +.LP +Scientific notation is allowed for numbers. +For example +.RS +.B +x = 5e\-2 +.RE +.LP +Text attributes can be compounded. +For example, +.RS +.B +"foo" above ljust +.RE +is legal. +.LP +There is no limit to the depth to which blocks can be examined. +For example, +.RS +.B +[A: [B: [C: box ]]] with .A.B.C.sw at 1,2 +.br +.B +circle at last [\^].A.B.C +.RE +is acceptable. +.LP +Arcs now have compass points +determined by the circle of which the arc is a part. +.LP +Circles and arcs can be dotted or dashed. +In \*(tx mode splines can be dotted or dashed. +.LP +Boxes can have rounded corners. +The +.B rad +attribute specifies the radius of the quarter-circles at each corner. +If no +.B rad +or +.B diam +attribute is given, a radius of +.B boxrad +is used. +Initially, +.B boxrad +has a value of 0. +A box with rounded corners can be dotted or dashed. +.LP +The +.B .PS +line can have a second argument specifying a maximum height for +the picture. +If the width of zero is specified the width will be ignored in computing +the scaling factor for the picture. +Note that GNU pic will always scale a picture by the same amount +vertically as horizontally. +This is different from the +.SM DWB +2.0 pic which may scale a picture by a +different amount vertically than horizontally if a height is +specified. +.LP +Each text object has an invisible box associated with it. +The compass points of a text object are determined by this box. +The implicit motion associated with the object is also determined +by this box. +The dimensions of this box are taken from the width and height attributes; +if the width attribute is not supplied then the width will be taken to be +.BR textwid ; +if the height attribute is not supplied then the height will be taken to be +the number of text strings associated with the object +times +.BR textht . +Initially +.B textwid +and +.B textht +have a value of 0. +.LP +In places where a quoted text string can be used, +an expression of the form +.IP +.BI sprintf(\(ts format \(ts,\ arg ,\fR.\|.\|.\fB) +.LP +can also be used; +this will produce the arguments formatted according to +.IR format , +which should be a string as described in +.BR printf (3) +appropriate for the number of arguments supplied, +using only the +.BR e , +.BR f , +.B g +or +.B % +format characters. +.LP +The thickness of the lines used to draw objects is controlled by the +.B linethick +variable. +This gives the thickness of lines in points. +A negative value means use the default thickness: +in \*(tx output mode, this means use a thickness of 8 milliinches; +in \*(tx output mode with the +.B -c +option, this means use the line thickness specified by +.B .ps +lines; +in troff output mode, this means use a thickness proportional +to the pointsize. +A zero value means draw the thinnest possible line supported by +the output device. +Initially it has a value of -1. +There is also a +.BR thick [ ness ] +attribute. +For example, +.RS +.LP +.B circle thickness 1.5 +.RE +.LP +would draw a circle using a line with a thickness of 1.5 points. +The thickness of lines is not affected by the +value of the +.B scale +variable, nor by the width or height given in the +.B .PS +line. +.LP +Boxes (including boxes with rounded corners), +circles and ellipses can be filled by giving then an attribute of +.BR fill [ ed ]. +This takes an optional argument of an expression with a value between +0 and 1; 0 will fill it with white, 1 with black, values in between +with a proportionally gray shade. +A value greater than 1 can also be used: +this means fill with the +shade of gray that is currently being used for text and lines. +Normally this will be black, but output devices may provide +a mechanism for changing this. +Without an argument, then the value of the variable +.B fillval +will be used. +Initially this has a value of 0.5. +The invisible attribute does not affect the filling of objects. +Any text associated with a filled object will be added after the +object has been filled, so that the text will not be obscured +by the filling. +.LP +Arrow heads will be drawn as solid triangles if the variable +.B arrowhead +is non-zero and either \*(tx mode is enabled or +the +.B \-x +option has been given. +Initially +.B arrowhead +has a value of 1. +.LP +The troff output of pic is device-independent. +The +.B \-T +option is therefore redundant. +All numbers are taken to be in inches; numbers are never interpreted +to be in troff machine units. +.LP +Objects can have an +.B aligned +attribute. +This will only work when the postprocessor is +.BR grops . +Any text associated with an object having the +.B aligned +attribute will be rotated about the center of the object +so that it is aligned in the direction from the start point +to the end point of the object. +Note that this attribute will have no effect for objects whose start and +end points are coincident. +.LP +In places where +.IB n th +is allowed +.BI ` expr 'th +is also allowed. +Note that +.B 'th +is a single token: no space is allowed between the +.B ' +and the +.BR th . +For example, +.IP +.B +.nf +for i = 1 to 4 do { + line from `i'th box.nw to `i+1'th box.se +} +.fi +.SH FILES +.Tp \w'\fB@MACRODIR@/tmac.pic'u+3n +.B +@MACRODIR@/tmac.pic +Example definitions of the +.B PS +and +.B PE +macros. +.SH "SEE ALSO" +.BR @g@troff (@MAN1EXT@), +.BR groff_out (@MAN5EXT@), +.BR tex (1) +.br +Tpic: Pic for \*(tx +.br +AT&T Bell Laboratories, Computing Science Technical Report No.\ 116, +PIC \(em A Graphics Language for Typesetting. +(This can be obtained by sending a mail message to netlib@research.att.com +with a body of `send\ 116\ from\ research/cstr'.) +.SH BUGS +.LP +Input characters that are illegal for +.B groff +(ie those with +.SM ASCII +code 0 or between 013 and 037 octal or between 0200 and 0237 octal) +are rejected even in \*(tx mode. +.LP +The interpretation of +.B fillval +is incompatible with the pic in 10th edition Unix, +which interprets 0 as black and 1 as white. diff --git a/contrib/groff/pic/pic.tab.h b/contrib/groff/pic/pic.tab.h new file mode 100644 index 000000000000..c71bdfd2cd3e --- /dev/null +++ b/contrib/groff/pic/pic.tab.h @@ -0,0 +1,129 @@ +#define LABEL 257 +#define VARIABLE 258 +#define NUMBER 259 +#define TEXT 260 +#define COMMAND_LINE 261 +#define DELIMITED 262 +#define ORDINAL 263 +#define TH 264 +#define LEFT_ARROW_HEAD 265 +#define RIGHT_ARROW_HEAD 266 +#define DOUBLE_ARROW_HEAD 267 +#define LAST 268 +#define UP 269 +#define DOWN 270 +#define LEFT 271 +#define RIGHT 272 +#define BOX 273 +#define CIRCLE 274 +#define ELLIPSE 275 +#define ARC 276 +#define LINE 277 +#define ARROW 278 +#define MOVE 279 +#define SPLINE 280 +#define HEIGHT 281 +#define RADIUS 282 +#define WIDTH 283 +#define DIAMETER 284 +#define FROM 285 +#define TO 286 +#define AT 287 +#define WITH 288 +#define BY 289 +#define THEN 290 +#define DOTTED 291 +#define DASHED 292 +#define CHOP 293 +#define SAME 294 +#define INVISIBLE 295 +#define LJUST 296 +#define RJUST 297 +#define ABOVE 298 +#define BELOW 299 +#define OF 300 +#define THE 301 +#define WAY 302 +#define BETWEEN 303 +#define AND 304 +#define HERE 305 +#define DOT_N 306 +#define DOT_E 307 +#define DOT_W 308 +#define DOT_S 309 +#define DOT_NE 310 +#define DOT_SE 311 +#define DOT_NW 312 +#define DOT_SW 313 +#define DOT_C 314 +#define DOT_START 315 +#define DOT_END 316 +#define DOT_X 317 +#define DOT_Y 318 +#define DOT_HT 319 +#define DOT_WID 320 +#define DOT_RAD 321 +#define SIN 322 +#define COS 323 +#define ATAN2 324 +#define LOG 325 +#define EXP 326 +#define SQRT 327 +#define K_MAX 328 +#define K_MIN 329 +#define INT 330 +#define RAND 331 +#define COPY 332 +#define THRU 333 +#define TOP 334 +#define BOTTOM 335 +#define UPPER 336 +#define LOWER 337 +#define SH 338 +#define PRINT 339 +#define CW 340 +#define CCW 341 +#define FOR 342 +#define DO 343 +#define IF 344 +#define ELSE 345 +#define ANDAND 346 +#define OROR 347 +#define NOTEQUAL 348 +#define EQUALEQUAL 349 +#define LESSEQUAL 350 +#define GREATEREQUAL 351 +#define LEFT_CORNER 352 +#define RIGHT_CORNER 353 +#define CENTER 354 +#define END 355 +#define START 356 +#define RESET 357 +#define UNTIL 358 +#define PLOT 359 +#define THICKNESS 360 +#define FILL 361 +#define ALIGNED 362 +#define SPRINTF 363 +#define COMMAND 364 +#define DEFINE 365 +#define UNDEF 366 +typedef 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; +} YYSTYPE; +extern YYSTYPE yylval; diff --git a/contrib/groff/pic/pic.y b/contrib/groff/pic/pic.y new file mode 100644 index 000000000000..6c7f4ae0b5a8 --- /dev/null +++ b/contrib/groff/pic/pic.y @@ -0,0 +1,1795 @@ +/* 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(); + +#undef fmod +#undef rand + +extern "C" { + double fmod(double, double); + 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"; + else { + // this is a fairly feeble attempt at validation of the format + int nspecs = 0; + for (const char *p = form; *p != '\0'; p++) + if (*p == '%') { + if (p[1] == '%') + p++; + else + nspecs++; + } + if (nspecs > 1) { + lex_error("bad format `%1'", form); + return strsave(form); + } + } + sprintf(sprintf_buf, form, n); + return strsave(sprintf_buf); +} + +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'; + sprintf(sprintf_buf, one_format.contents()); + } + else { + if (i >= nv) { + lex_error("too few arguments to sprintf"); + result += one_format; + result += form; + break; + } + one_format += *form++; + one_format += '\0'; + sprintf(sprintf_buf, one_format.contents(), v[i++]); + } + one_format.clear(); + result += sprintf_buf; + } + else + result += *form++; + } + result += '\0'; + return strsave(result.contents()); +} diff --git a/contrib/groff/pic/position.h b/contrib/groff/pic/position.h new file mode 100644 index 000000000000..ab7d5469c006 --- /dev/null +++ b/contrib/groff/pic/position.h @@ -0,0 +1,47 @@ +// -*- C++ -*- +/* 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. */ + +struct place; +struct position { + double x; + double y; + position(double, double ); + position(); + position(const place &); + position &operator+=(const position &); + position &operator-=(const position &); + position &operator*=(double); + position &operator/=(double); +}; + +position operator-(const position &); +position operator+(const position &, const position &); +position operator-(const position &, const position &); +position operator/(const position &, double); +position operator*(const position &, double); +// dot product +double operator*(const position &, const position &); +int operator==(const position &, const position &); +int operator!=(const position &, const position &); + +double hypot(const position &a); + +typedef position distance; + diff --git a/contrib/groff/pic/tex.cc b/contrib/groff/pic/tex.cc new file mode 100644 index 000000000000..531078260922 --- /dev/null +++ b/contrib/groff/pic/tex.cc @@ -0,0 +1,411 @@ +// -*- C++ -*- +/* 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" + +#ifdef TEX_SUPPORT + +#include "common.h" + +class tex_output : public common_output { +public: + tex_output(); + ~tex_output(); + void start_picture(double, const position &ll, const position &ur); + void finish_picture(); + void text(const position &, text_piece *, int, double); + void line(const position &, const position *, int n, + const line_type &); + void polygon(const position *, int n, + const line_type &, double); + void spline(const position &, const position *, int n, + const line_type &); + void arc(const position &, const position &, const position &, + const line_type &); + void circle(const position &, double rad, const line_type &, double); + void ellipse(const position &, const distance &, const line_type &, double); + void command(const char *, const char *, int); + int supports_filled_polygons(); +private: + position upper_left; + double height; + double width; + double scale; + double pen_size; + + void point(const position &); + void dot(const position &, const line_type &); + void solid_arc(const position ¢, double rad, double start_angle, + double end_angle, const line_type <); + position transform(const position &); +protected: + virtual void set_pen_size(double ps); +}; + +// convert inches to milliinches + +inline int milliinches(double x) +{ + return int(x*1000.0 + .5); +} + +inline position tex_output::transform(const position &pos) +{ + return position((pos.x - upper_left.x)/scale, + (upper_left.y - pos.y)/scale); +} + +output *make_tex_output() +{ + return new tex_output; +} + +tex_output::tex_output() +{ +} + +tex_output::~tex_output() +{ +} + +const int DEFAULT_PEN_SIZE = 8; + +void tex_output::set_pen_size(double ps) +{ + if (ps < 0.0) + ps = -1.0; + if (ps != pen_size) { + pen_size = ps; + printf(" \\special{pn %d}%%\n", + ps < 0.0 ? DEFAULT_PEN_SIZE : int(ps*(1000.0/72.0) + .5)); + } +} + +void tex_output::start_picture(double sc, const position &ll, + const position &ur) +{ + upper_left.x = ll.x; + upper_left.y = ur.y; + scale = compute_scale(sc, ll, ur); + height = (ur.y - ll.y)/scale; + width = (ur.x - ll.x)/scale; + /* the point of \vskip 0pt is to ensure that the vtop gets + a height of 0 rather than the height of the hbox; this + might be non-zero if text from text attributes lies outside pic's + idea of the bounding box of the picture. */ + fputs("\\expandafter\\ifx\\csname graph\\endcsname\\relax \\csname newbox\\endcsname\\graph\\fi\n" + "\\expandafter\\ifx\\csname graphtemp\\endcsname\\relax \\csname newdimen\\endcsname\\graphtemp\\fi\n" + "\\setbox\\graph=\\vtop{\\vskip 0pt\\hbox{%\n", + stdout); + pen_size = -2.0; +} + +void tex_output::finish_picture() +{ + printf(" \\hbox{\\vrule depth%.3fin width0pt height 0pt}%%\n" + " \\kern %.3fin\n" + " }%%\n" + "}%%\n", + height, width); +} + +void tex_output::text(const position ¢er, text_piece *v, int n, double) +{ + position c = transform(center); + for (int i = 0; i < n; i++) + if (v[i].text != 0 && *v[i].text != '\0') { + int j = 2*i - n + 1; + if (v[i].adj.v == ABOVE_ADJUST) + j--; + else if (v[i].adj.v == BELOW_ADJUST) + j++; + if (j == 0) { + printf(" \\graphtemp=.5ex\\advance\\graphtemp by %.3fin\n", c.y); + } + else { + printf(" \\graphtemp=\\baselineskip" + "\\multiply\\graphtemp by %d" + "\\divide\\graphtemp by 2\n" + " \\advance\\graphtemp by .5ex" + "\\advance\\graphtemp by %.3fin\n", + j, c.y); + } + printf(" \\rlap{\\kern %.3fin\\lower\\graphtemp", c.x); + fputs("\\hbox to 0pt{", stdout); + if (v[i].adj.h != LEFT_ADJUST) + fputs("\\hss ", stdout); + fputs(v[i].text, stdout); + if (v[i].adj.h != RIGHT_ADJUST) + fputs("\\hss", stdout); + fputs("}}%\n", stdout); + } +} + +void tex_output::point(const position &pos) +{ + position p = transform(pos); + printf(" \\special{pa %d %d}%%\n", milliinches(p.x), milliinches(p.y)); +} + +void tex_output::line(const position &start, const position *v, int n, + const line_type <) +{ + set_pen_size(lt.thickness); + point(start); + for (int i = 0; i < n; i++) + point(v[i]); + fputs(" \\special{", stdout); + switch(lt.type) { + case line_type::invisible: + fputs("ip", stdout); + break; + case line_type::solid: + fputs("fp", stdout); + break; + case line_type::dotted: + printf("dt %.3f", lt.dash_width/scale); + break; + case line_type::dashed: + printf("da %.3f", lt.dash_width/scale); + break; + } + fputs("}%\n", stdout); +} + +void tex_output::polygon(const position *v, int n, + const line_type <, double fill) +{ + if (fill >= 0.0) { + if (fill > 1.0) + fill = 1.0; + printf(" \\special{sh %.3f}%%\n", fill); + } + line(v[n-1], v, n, lt); +} + +void tex_output::spline(const position &start, const position *v, int n, + const line_type <) +{ + if (lt.type == line_type::invisible) + return; + set_pen_size(lt.thickness); + point(start); + for (int i = 0; i < n; i++) + point(v[i]); + fputs(" \\special{sp", stdout); + switch(lt.type) { + case line_type::solid: + break; + case line_type::dotted: + printf(" %.3f", -lt.dash_width/scale); + break; + case line_type::dashed: + printf(" %.3f", lt.dash_width/scale); + break; + case line_type::invisible: + assert(0); + } + fputs("}%\n", stdout); +} + +void tex_output::solid_arc(const position ¢, double rad, + double start_angle, double end_angle, + const line_type <) +{ + set_pen_size(lt.thickness); + position c = transform(cent); + printf(" \\special{ar %d %d %d %d %f %f}%%\n", + milliinches(c.x), + milliinches(c.y), + milliinches(rad/scale), + milliinches(rad/scale), + -end_angle, + (-end_angle > -start_angle) ? M_PI * 2 - start_angle : -start_angle); +} + +void tex_output::arc(const position &start, const position ¢, + const position &end, const line_type <) +{ + switch (lt.type) { + case line_type::invisible: + break; + case line_type::dashed: + dashed_arc(start, cent, end, lt); + break; + case line_type::dotted: + dotted_arc(start, cent, end, lt); + break; + case line_type::solid: + { + position c; + if (!compute_arc_center(start, cent, end, &c)) { + line(start, &end, 1, lt); + break; + } + solid_arc(c, + hypot(cent - start), + atan2(start.y - c.y, start.x - c.x), + atan2(end.y - c.y, end.x - c.x), + lt); + break; + } + } +} + +void tex_output::circle(const position ¢, double rad, + const line_type <, double fill) +{ + if (fill >= 0.0 && lt.type != line_type::solid) { + if (fill > 1.0) + fill = 1.0; + line_type ilt; + ilt.type = line_type::invisible; + ellipse(cent, position(rad*2.0, rad*2.0), ilt, fill); + } + switch (lt.type) { + case line_type::dashed: + dashed_circle(cent, rad, lt); + break; + case line_type::invisible: + break; + case line_type::solid: + ellipse(cent, position(rad*2.0,rad*2.0), lt, fill); + break; + case line_type::dotted: + dotted_circle(cent, rad, lt); + break; + default: + assert(0); + } +} + +void tex_output::ellipse(const position ¢, const distance &dim, + const line_type <, double fill) +{ + if (lt.type == line_type::invisible) { + if (fill < 0.0) + return; + } + else + set_pen_size(lt.thickness); + if (fill >= 0.0) { + if (fill > 1.0) + fill = 1.0; + printf(" \\special{sh %.3f}%%\n", fill); + } + position c = transform(cent); + printf(" \\special{%s %d %d %d %d 0 6.28319}%%\n", + (lt.type == line_type::invisible ? "ia" : "ar"), + milliinches(c.x), + milliinches(c.y), + milliinches(dim.x/(2.0*scale)), + milliinches(dim.y/(2.0*scale))); +} + +void tex_output::command(const char *s, const char *, int) +{ + fputs(s, stdout); + putchar('%'); // avoid unwanted spaces + putchar('\n'); +} + +int tex_output::supports_filled_polygons() +{ + return 1; +} + +void tex_output::dot(const position &pos, const line_type <) +{ + if (zero_length_line_flag) { + line_type slt = lt; + slt.type = line_type::solid; + line(pos, &pos, 1, slt); + } + else { + int dot_rad = int(lt.thickness*(1000.0/(72.0*2)) + .5); + if (dot_rad == 0) + dot_rad = 1; + position p = transform(pos); + printf(" \\special{sh 1}%%\n" + " \\special{ia %d %d %d %d 0 6.28319}%%\n", + milliinches(p.x), milliinches(p.y), dot_rad, dot_rad); + } +} + +class tpic_output : public tex_output { +public: + tpic_output(); + void command(const char *, const char *, int); +private: + void set_pen_size(double ps); + int default_pen_size; + int prev_default_pen_size; +}; + +tpic_output::tpic_output() +: default_pen_size(DEFAULT_PEN_SIZE), prev_default_pen_size(DEFAULT_PEN_SIZE) +{ +} + +void tpic_output::command(const char *s, const char *filename, int lineno) +{ + assert(s[0] == '.'); + if (s[1] == 'p' && s[2] == 's' && (s[3] == '\0' || !csalpha(s[3]))) { + const char *p = s + 3; + while (csspace(*p)) + p++; + if (*p == '\0') { + int temp = default_pen_size; + default_pen_size = prev_default_pen_size; + prev_default_pen_size = temp; + } + else { + char *ptr; + int temp = (int)strtol(p, &ptr, 10); + if (temp == 0 && ptr == p) + error_with_file_and_line(filename, lineno, + "argument to `.ps' not an integer"); + else if (temp < 0) + error_with_file_and_line(filename, lineno, + "negative pen size"); + else { + prev_default_pen_size = default_pen_size; + default_pen_size = temp; + } + } + } + else + printf("\\%s%%\n", s + 1); +} + +void tpic_output::set_pen_size(double ps) +{ + if (ps < 0.0) + printf(" \\special{pn %d}%%\n", default_pen_size); + else + tex_output::set_pen_size(ps); +} + +output *make_tpic_output() +{ + return new tpic_output; +} + +#endif diff --git a/contrib/groff/pic/text.h b/contrib/groff/pic/text.h new file mode 100644 index 000000000000..f9d34875075f --- /dev/null +++ b/contrib/groff/pic/text.h @@ -0,0 +1,28 @@ +// -*- C++ -*- + +enum hadjustment { + CENTER_ADJUST, + LEFT_ADJUST, + RIGHT_ADJUST + }; + +enum vadjustment { + NONE_ADJUST, + ABOVE_ADJUST, + BELOW_ADJUST + }; + +struct adjustment { + hadjustment h; + vadjustment v; +}; + +struct text_piece { + char *text; + adjustment adj; + const char *filename; + int lineno; + + text_piece(); + ~text_piece(); +}; diff --git a/contrib/groff/pic/troff.cc b/contrib/groff/pic/troff.cc new file mode 100644 index 000000000000..71444cdbf7e2 --- /dev/null +++ b/contrib/groff/pic/troff.cc @@ -0,0 +1,500 @@ +// -*- C++ -*- +/* 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 "common.h" + + +const double RELATIVE_THICKNESS = -1.0; +const double BAD_THICKNESS = -2.0; + +class simple_output : public common_output { + virtual void simple_line(const position &, const position &) = 0; + virtual void simple_spline(const position &, const position *, int n) = 0; + virtual void simple_arc(const position &, const position &, + const position &) = 0; + virtual void simple_circle(int, const position &, double rad) = 0; + virtual void simple_ellipse(int, const position &, const distance &) = 0; + virtual void simple_polygon(int, const position *, int) = 0; + virtual void line_thickness(double) = 0; + virtual void set_fill(double) = 0; + void dot(const position &, const line_type &) = 0; +public: + void start_picture(double sc, const position &ll, const position &ur) = 0; + void finish_picture() = 0; + void text(const position &, text_piece *, int, double) = 0; + void line(const position &, const position *, int n, + const line_type &); + void polygon(const position *, int n, + const line_type &, double); + void spline(const position &, const position *, int n, + const line_type &); + void arc(const position &, const position &, const position &, + const line_type &); + void circle(const position &, double rad, const line_type &, double); + void ellipse(const position &, const distance &, const line_type &, double); + int supports_filled_polygons(); +}; + +int simple_output::supports_filled_polygons() +{ + return driver_extension_flag != 0; +} + +void simple_output::arc(const position &start, const position ¢, + const position &end, const line_type <) +{ + switch (lt.type) { + case line_type::solid: + line_thickness(lt.thickness); + simple_arc(start, cent, end); + break; + case line_type::invisible: + break; + case line_type::dashed: + dashed_arc(start, cent, end, lt); + break; + case line_type::dotted: + dotted_arc(start, cent, end, lt); + break; + } +} + +void simple_output::line(const position &start, const position *v, int n, + const line_type <) +{ + position pos = start; + line_thickness(lt.thickness); + for (int i = 0; i < n; i++) { + switch (lt.type) { + case line_type::solid: + simple_line(pos, v[i]); + break; + case line_type::dotted: + { + distance vec(v[i] - pos); + double dist = hypot(vec); + int ndots = int(dist/lt.dash_width + .5); + if (ndots == 0) + dot(pos, lt); + else { + vec /= double(ndots); + for (int j = 0; j <= ndots; j++) + dot(pos + vec*j, lt); + } + } + break; + case line_type::dashed: + { + distance vec(v[i] - pos); + double dist = hypot(vec); + if (dist <= lt.dash_width*2.0) + simple_line(pos, v[i]); + else { + int ndashes = int((dist - lt.dash_width)/(lt.dash_width*2.0) + .5); + distance dash_vec = vec*(lt.dash_width/dist); + double dash_gap = (dist - lt.dash_width)/ndashes; + distance dash_gap_vec = vec*(dash_gap/dist); + for (int j = 0; j <= ndashes; j++) { + position s(pos + dash_gap_vec*j); + simple_line(s, s + dash_vec); + } + } + } + break; + case line_type::invisible: + break; + default: + assert(0); + } + pos = v[i]; + } +} + +void simple_output::spline(const position &start, const position *v, int n, + const line_type <) +{ + line_thickness(lt.thickness); + simple_spline(start, v, n); +} + +void simple_output::polygon(const position *v, int n, + const line_type <, double fill) +{ + if (driver_extension_flag) { + if (fill >= 0.0) { + set_fill(fill); + simple_polygon(1, v, n); + } + } + if (lt.type == line_type::solid && driver_extension_flag) { + line_thickness(lt.thickness); + simple_polygon(0, v, n); + } + else if (lt.type != line_type::invisible) { + line_thickness(lt.thickness); + line(v[n - 1], v, n, lt); + } +} + +void simple_output::circle(const position ¢, double rad, + const line_type <, double fill) +{ + if (driver_extension_flag && fill >= 0.0) { + set_fill(fill); + simple_circle(1, cent, rad); + } + line_thickness(lt.thickness); + switch (lt.type) { + case line_type::invisible: + break; + case line_type::dashed: + dashed_circle(cent, rad, lt); + break; + case line_type::dotted: + dotted_circle(cent, rad, lt); + break; + case line_type::solid: + simple_circle(0, cent, rad); + break; + default: + assert(0); + } +} + +void simple_output::ellipse(const position ¢, const distance &dim, + const line_type <, double fill) +{ + if (driver_extension_flag && fill >= 0.0) { + set_fill(fill); + simple_ellipse(1, cent, dim); + } + if (lt.type != line_type::invisible) + line_thickness(lt.thickness); + switch (lt.type) { + case line_type::invisible: + break; + case line_type::dotted: + case line_type::dashed: + case line_type::solid: + simple_ellipse(0, cent, dim); + break; + default: + assert(0); + } +} + +#define FILL_MAX 1000 + +class troff_output : public simple_output { + const char *last_filename; + position upper_left; + double height; + double scale; + double last_line_thickness; + double last_fill; +public: + troff_output(); + ~troff_output(); + void start_picture(double, const position &ll, const position &ur); + void finish_picture(); + void text(const position &, text_piece *, int, double); + void dot(const position &, const line_type &); + void command(const char *, const char *, int); + void set_location(const char *, int); + void simple_line(const position &, const position &); + void simple_spline(const position &, const position *, int n); + void simple_arc(const position &, const position &, const position &); + void simple_circle(int, const position &, double rad); + void simple_ellipse(int, const position &, const distance &); + void simple_polygon(int, const position *, int); + void line_thickness(double p); + void set_fill(double); + position transform(const position &); +}; + +output *make_troff_output() +{ + return new troff_output; +} + +troff_output::troff_output() +: last_filename(0), last_line_thickness(BAD_THICKNESS), last_fill(-1.0) +{ +} + +troff_output::~troff_output() +{ +} + +inline position troff_output::transform(const position &pos) +{ + return position((pos.x - upper_left.x)/scale, + (upper_left.y - pos.y)/scale); +} + +#define FILL_REG "00" + +// If this register > 0, then pic will generate \X'ps: ...' commands +// if the aligned attribute is used. +#define GROPS_REG "0p" + +// If this register is defined, geqn won't produce `\x's. +#define EQN_NO_EXTRA_SPACE_REG "0x" + +void troff_output::start_picture(double sc, + const position &ll, const position &ur) +{ + upper_left.x = ll.x; + upper_left.y = ur.y; + scale = compute_scale(sc, ll, ur); + height = (ur.y - ll.y)/scale; + double width = (ur.x - ll.x)/scale; + printf(".PS %.3fi %.3fi", height, width); + if (args) + printf(" %s\n", args); + else + putchar('\n'); + printf(".\\\" %g %g %g %g\n", ll.x, ll.y, ur.x, ur.y); + printf(".\\\" %.3fi %.3fi %.3fi %.3fi\n", 0.0, height, width, 0.0); + printf(".nr " FILL_REG " \\n(.u\n.nf\n"); + printf(".nr " EQN_NO_EXTRA_SPACE_REG " 1\n"); + // This guarantees that if the picture is used in a diversion it will + // have the right width. + printf("\\h'%.3fi'\n.sp -1\n", width); +} + +void troff_output::finish_picture() +{ + line_thickness(BAD_THICKNESS); + last_fill = -1.0; // force it to be reset for each picture + if (!flyback_flag) + printf(".sp %.3fi+1\n", height); + printf(".if \\n(" FILL_REG " .fi\n"); + printf(".br\n"); + printf(".nr " EQN_NO_EXTRA_SPACE_REG " 0\n"); + // this is a little gross + set_location(current_filename, current_lineno); + fputs(flyback_flag ? ".PF\n" : ".PE\n", stdout); +} + +void troff_output::command(const char *s, + const char *filename, int lineno) +{ + if (filename != 0) + set_location(filename, lineno); + fputs(s, stdout); + putchar('\n'); +} + +void troff_output::simple_circle(int filled, const position ¢, double rad) +{ + position c = transform(cent); + printf("\\h'%.3fi'" + "\\v'%.3fi'" + "\\D'%c%.3fi'" + "\n.sp -1\n", + c.x - rad/scale, + c.y, + (filled ? 'C' : 'c'), + rad*2.0/scale); +} + +void troff_output::simple_ellipse(int filled, const position ¢, + const distance &dim) +{ + position c = transform(cent); + printf("\\h'%.3fi'" + "\\v'%.3fi'" + "\\D'%c%.3fi %.3fi'" + "\n.sp -1\n", + c.x - dim.x/(2.0*scale), + c.y, + (filled ? 'E' : 'e'), + dim.x/scale, dim.y/scale); +} + +void troff_output::simple_arc(const position &start, const distance ¢, + const distance &end) +{ + position s = transform(start); + position c = transform(cent); + distance cv = c - s; + distance ev = transform(end) - c; + printf("\\h'%.3fi'" + "\\v'%.3fi'" + "\\D'a%.3fi %.3fi %.3fi %.3fi'" + "\n.sp -1\n", + s.x, s.y, cv.x, cv.y, ev.x, ev.y); +} + +void troff_output::simple_line(const position &start, const position &end) +{ + position s = transform(start); + distance ev = transform(end) - s; + printf("\\h'%.3fi'" + "\\v'%.3fi'" + "\\D'l%.3fi %.3fi'" + "\n.sp -1\n", + s.x, s.y, ev.x, ev.y); +} + +void troff_output::simple_spline(const position &start, + const position *v, int n) +{ + position pos = transform(start); + printf("\\h'%.3fi'" + "\\v'%.3fi'", + pos.x, pos.y); + fputs("\\D'~", stdout); + for (int i = 0; i < n; i++) { + position temp = transform(v[i]); + distance d = temp - pos; + pos = temp; + if (i != 0) + putchar(' '); + printf("%.3fi %.3fi", d.x, d.y); + } + printf("'\n.sp -1\n"); +} + +// a solid polygon + +void troff_output::simple_polygon(int filled, const position *v, int n) +{ + position pos = transform(v[0]); + printf("\\h'%.3fi'" + "\\v'%.3fi'", + pos.x, pos.y); + printf("\\D'%c", (filled ? 'P' : 'p')); + for (int i = 1; i < n; i++) { + position temp = transform(v[i]); + distance d = temp - pos; + pos = temp; + if (i != 1) + putchar(' '); + printf("%.3fi %.3fi", d.x, d.y); + } + printf("'\n.sp -1\n"); +} + +const double TEXT_AXIS = 0.22; // in ems + +static const char *choose_delimiter(const char *text) +{ + if (strchr(text, '\'') == 0) + return "'"; + else + return "\\(ts"; +} + +void troff_output::text(const position ¢er, text_piece *v, int n, + double ang) +{ + line_thickness(BAD_THICKNESS); // the text might use lines (eg in equations) + int rotate_flag = 0; + if (driver_extension_flag && ang != 0.0) { + rotate_flag = 1; + position c = transform(center); + printf(".if \\n(" GROPS_REG " \\{\\\n" + "\\h'%.3fi'" + "\\v'%.3fi'" + "\\X'ps: exec gsave currentpoint 2 copy translate %.4f rotate neg exch neg exch translate'" + "\n.sp -1\n" + ".\\}\n", + c.x, c.y, -ang*180.0/M_PI); + } + for (int i = 0; i < n; i++) + if (v[i].text != 0 && *v[i].text != '\0') { + position c = transform(center); + if (v[i].filename != 0) + set_location(v[i].filename, v[i].lineno); + printf("\\h'%.3fi", c.x); + const char *delim = choose_delimiter(v[i].text); + if (v[i].adj.h == RIGHT_ADJUST) + printf("-\\w%s%s%su", delim, v[i].text, delim); + else if (v[i].adj.h != LEFT_ADJUST) + printf("-(\\w%s%s%su/2u)", delim, v[i].text, delim); + putchar('\''); + printf("\\v'%.3fi-(%dv/2u)+%dv+%.2fm", + c.y, + n - 1, + i, + TEXT_AXIS); + if (v[i].adj.v == ABOVE_ADJUST) + printf("-.5v"); + else if (v[i].adj.v == BELOW_ADJUST) + printf("+.5v"); + putchar('\''); + fputs(v[i].text, stdout); + fputs("\n.sp -1\n", stdout); + } + if (rotate_flag) + printf(".if '\\*(.T'ps' \\{\\\n" + "\\X'ps: exec grestore'\n.sp -1\n" + ".\\}\n"); +} + +void troff_output::line_thickness(double p) +{ + if (p < 0.0) + p = RELATIVE_THICKNESS; + if (driver_extension_flag && p != last_line_thickness) { + printf("\\D't %.3fp'\\h'%.3fp'\n.sp -1\n", p, -p); + last_line_thickness = p; + } +} + +void troff_output::set_fill(double f) +{ + if (driver_extension_flag && f != last_fill) { + printf("\\D'f %du'\\h'%du'\n.sp -1\n", int(f*FILL_MAX), -int(f*FILL_MAX)); + last_fill = f; + } +} + +const double DOT_AXIS = .044; + +void troff_output::dot(const position ¢, const line_type <) +{ + if (driver_extension_flag) { + line_thickness(lt.thickness); + simple_line(cent, cent); + } + else { + position c = transform(cent); + printf("\\h'%.3fi-(\\w'.'u/2u)'" + "\\v'%.3fi+%.2fm'" + ".\n.sp -1\n", + c.x, + c.y, + DOT_AXIS); + } +} + +void troff_output::set_location(const char *s, int n) +{ + if (last_filename != 0 && strcmp(s, last_filename) == 0) + printf(".lf %d\n", n); + else { + printf(".lf %d %s\n", n, s); + last_filename = s; + } +} |