diff options
Diffstat (limited to 'contrib/groff/src/preproc/pic/pic.y')
-rw-r--r-- | contrib/groff/src/preproc/pic/pic.y | 196 |
1 files changed, 124 insertions, 72 deletions
diff --git a/contrib/groff/src/preproc/pic/pic.y b/contrib/groff/src/preproc/pic/pic.y index c0a7315..15b6b3f 100644 --- a/contrib/groff/src/preproc/pic/pic.y +++ b/contrib/groff/src/preproc/pic/pic.y @@ -1,4 +1,4 @@ -/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001 +/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.com) @@ -202,6 +202,10 @@ char *do_sprintf(const char *form, const double *v, int nv); %token GREATEREQUAL %token LEFT_CORNER %token RIGHT_CORNER +%token NORTH +%token SOUTH +%token EAST +%token WEST %token CENTER %token END %token START @@ -210,6 +214,9 @@ char *do_sprintf(const char *form, const double *v, int nv); %token PLOT %token THICKNESS %token FILL +%token COLORED +%token OUTLINED +%token SHADED %token ALIGNED %token SPRINTF %token COMMAND @@ -217,6 +224,8 @@ char *do_sprintf(const char *form, const double *v, int nv); %token DEFINE %token UNDEF +%left '.' + /* this ensures that plot 17 "%g" parses as (plot 17 "%g") */ %left PLOT %left TEXT SPRINTF @@ -231,12 +240,14 @@ box "foo" above ljust == box ("foo" above ljust) /* Give attributes that take an optional expression a higher precedence than left and right, so that eg `line chop left' parses properly. */ -%left CHOP SOLID DASHED DOTTED UP DOWN FILL +%left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED %left LABEL %left VARIABLE NUMBER '(' SIN COS ATAN2 LOG EXP SQRT K_MAX K_MIN INT RAND SRAND LAST %left ORDINAL HERE '`' +%left BOX CIRCLE ELLIPSE ARC LINE ARROW SPLINE '[' + /* these need to be lower than '-' */ %left HEIGHT RADIUS WIDTH DIAMETER FROM TO AT THICKNESS @@ -244,7 +255,7 @@ parses properly. */ 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 UPPER LOWER NORTH SOUTH EAST WEST CENTER START END %left ',' %left OROR @@ -350,7 +361,7 @@ placeless_element: { fprintf(stderr, "%s\n", $2.str); a_delete $2.str; - fflush(stderr); + fflush(stderr); } | SH { delim_flag = 1; } @@ -433,11 +444,20 @@ placeless_element: reset_variables: RESET VARIABLE - { reset($2); a_delete $2; } + { + reset($2); + a_delete $2; + } | reset_variables VARIABLE - { reset($2); a_delete $2; } + { + reset($2); + a_delete $2; + } | reset_variables ',' VARIABLE - { reset($3); a_delete $3; } + { + reset($3); + a_delete $3; + } ; print_args: @@ -462,7 +482,7 @@ print_args: ; print_arg: - expr %prec ',' + expr %prec ',' { $$.str = new char[GDIGITS + 1]; sprintf($$.str, "%g", $1); @@ -471,19 +491,24 @@ print_arg: } | text { $$ = $1; } - | position %prec ',' + | 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; } + { + delim_flag = 0; + $$.x = $2; + $$.body = $5; + } ; until: @@ -532,11 +557,20 @@ text_expr: optional_by: /* empty */ - { $$.val = 1.0; $$.is_multiplicative = 0; } + { + $$.val = 1.0; + $$.is_multiplicative = 0; + } | BY expr - { $$.val = $2; $$.is_multiplicative = 0; } + { + $$.val = $2; + $$.is_multiplicative = 0; + } | BY '*' expr - { $$.val = $3; $$.is_multiplicative = 1; } + { + $$.val = $3; + $$.is_multiplicative = 1; + } ; element: @@ -555,7 +589,11 @@ element: } } | LABEL ':' optional_separator element - { $$ = $4; define_label($1, & $$); a_delete $1; } + { + $$ = $4; + define_label($1, & $$); + a_delete $1; + } | LABEL ':' optional_separator position_not_place { $$.obj = 0; @@ -603,17 +641,11 @@ optional_element: object_spec: BOX - { - $$ = new object_spec(BOX_OBJECT); - } + { $$ = new object_spec(BOX_OBJECT); } | CIRCLE - { - $$ = new object_spec(CIRCLE_OBJECT); - } + { $$ = new object_spec(CIRCLE_OBJECT); } | ELLIPSE - { - $$ = new object_spec(ELLIPSE_OBJECT); - } + { $$ = new object_spec(ELLIPSE_OBJECT); } | ARC { $$ = new object_spec(ARC_OBJECT); @@ -647,7 +679,7 @@ object_spec: lookup_variable("linewid", & $$->segment_width); $$->dir = current_direction; } - | text %prec TEXT + | text %prec TEXT { $$ = new object_spec(TEXT_OBJECT); $$->text = new text_item($1.str, $1.filename, $1.lineno); @@ -715,7 +747,7 @@ object_spec: $$->radius = $3/2.0; $$->flags |= HAS_RADIUS; } - | object_spec expr %prec HEIGHT + | object_spec expr %prec HEIGHT { $$ = $1; $$->flags |= HAS_SEGMENT; @@ -830,6 +862,15 @@ object_spec: $$->flags |= HAS_WITH; $$->with = $3; } + | object_spec WITH position %prec ',' + { + $$ = $1; + $$->flags |= HAS_WITH; + position pos; + pos.x = $3.x; + pos.y = $3.y; + $$->with = new path(pos); + } | object_spec BY expr_pair { $$ = $1; @@ -888,6 +929,29 @@ object_spec: $$->flags |= IS_FILLED; $$->fill = $3; } + | object_spec SHADED text + { + $$ = $1; + $$->flags |= (IS_SHADED | IS_FILLED); + $$->shaded = new char[strlen($3.str)+1]; + strcpy($$->shaded, $3.str); + } + | object_spec COLORED text + { + $$ = $1; + $$->flags |= (IS_SHADED | IS_OUTLINED | IS_FILLED); + $$->shaded = new char[strlen($3.str)+1]; + strcpy($$->shaded, $3.str); + $$->outlined = new char[strlen($3.str)+1]; + strcpy($$->outlined, $3.str); + } + | object_spec OUTLINED text + { + $$ = $1; + $$->flags |= IS_OUTLINED; + $$->outlined = new char[strlen($3.str)+1]; + strcpy($$->outlined, $3.str); + } | object_spec CHOP { $$ = $1; @@ -956,7 +1020,7 @@ object_spec: $$ = $1; $$->flags &= ~IS_CLOCKWISE; } - | object_spec text %prec TEXT + | object_spec text %prec TEXT { $$ = $1; text_item **p; @@ -1019,9 +1083,7 @@ object_spec: text: TEXT - { - $$ = $1; - } + { $$ = $1; } | SPRINTF '(' TEXT sprintf_args ')' { $$.filename = $3.filename; @@ -1108,13 +1170,17 @@ between: expr_pair: expr ',' expr - { $$.x = $1; $$.y = $3; } + { + $$.x = $1; + $$.y = $3; + } | '(' expr_pair ')' { $$ = $2; } ; place: - label %prec CHOP /* line at A left == line (at A) left */ + /* line at A left == line (at A) left */ + label %prec CHOP { $$ = $1; } | label corner { @@ -1154,9 +1220,7 @@ label: a_delete $1; } | nth_primitive - { - $$.obj = $1; - } + { $$.obj = $1; } | label '.' LABEL { path pth($3); @@ -1176,7 +1240,7 @@ ordinal: ; optional_ordinal_last: - LAST + LAST { $$ = 1; } | ordinal LAST { $$ = $1; } @@ -1238,9 +1302,7 @@ object_type: label_path: '.' LABEL - { - $$ = new path($2); - } + { $$ = new path($2); } | label_path '.' LABEL { $$ = $1; @@ -1249,17 +1311,12 @@ label_path: ; relative_path: - corner - { - $$ = new path($1); - } + corner %prec CHOP + { $$ = 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 %prec TEXT + { $$ = $1; } | label_path corner { $$ = $1; @@ -1269,9 +1326,7 @@ relative_path: path: relative_path - { - $$ = $1; - } + { $$ = $1; } | '(' relative_path ',' relative_path ')' { $$ = $2; @@ -1355,6 +1410,14 @@ corner: { $$ = &object::north_east; } | LOWER RIGHT_CORNER { $$ = &object::south_east; } + | NORTH + { $$ = &object::north; } + | SOUTH + { $$ = &object::south; } + | EAST + { $$ = &object::east; } + | WEST + { $$ = &object::west; } | CENTER { $$ = &object::center; } | START @@ -1444,7 +1507,7 @@ expr: YYABORT; } } - | '-' expr %prec '!' + | '-' expr %prec '!' { $$ = -$2; } | '(' any_expr ')' { $$ = $2; } @@ -1521,7 +1584,10 @@ expr: $$ = (rand() & 0x7fff) / double(0x8000); } | SRAND '(' any_expr ')' - { $$ = 0; srand((unsigned int)$3); } + { + $$ = 0; + srand((unsigned int)$3); + } | expr '<' expr { $$ = ($1 < $3); } | expr LESSEQUAL expr @@ -1754,23 +1820,7 @@ 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); + return do_sprintf(form, &n, 1); } char *do_sprintf(const char *form, const double *v, int nv) @@ -1792,18 +1842,20 @@ char *do_sprintf(const char *form, const double *v, int nv) if (*form == '%') { one_format += *form++; one_format += '\0'; - sprintf(sprintf_buf, one_format.contents()); + snprintf(sprintf_buf, sizeof(sprintf_buf), + "%s", one_format.contents()); } else { if (i >= nv) { - lex_error("too few arguments to sprintf"); + lex_error("too few arguments to snprintf"); result += one_format; result += form; break; } one_format += *form++; one_format += '\0'; - sprintf(sprintf_buf, one_format.contents(), v[i++]); + snprintf(sprintf_buf, sizeof(sprintf_buf), + one_format.contents(), v[i++]); } one_format.clear(); result += sprintf_buf; |