2 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
37 static int parse_expr(units
*v
, int scale_indicator
, int parenthesised
);
38 static int start_number();
40 int get_vunits(vunits
*res
, unsigned char si
)
45 if (parse_expr(&x
, si
, 0)) {
53 int get_hunits(hunits
*res
, unsigned char si
)
58 if (parse_expr(&x
, si
, 0)) {
66 int get_number(units
*res
, unsigned char si
)
71 if (parse_expr(&x
, si
, 0)) {
79 int get_integer(int *res
)
84 if (parse_expr(&x
, 0, 0)) {
92 enum incr_number_result
{ BAD
, ABSOLUTE
, INCREMENT
, DECREMENT
};
94 static incr_number_result
get_incr_number(units
*res
, unsigned char);
96 int get_vunits(vunits
*res
, unsigned char si
, vunits prev_value
)
99 switch (get_incr_number(&v
, si
)) {
106 *res
= prev_value
+ v
;
109 *res
= prev_value
- v
;
117 int get_hunits(hunits
*res
, unsigned char si
, hunits prev_value
)
120 switch (get_incr_number(&v
, si
)) {
127 *res
= prev_value
+ v
;
130 *res
= prev_value
- v
;
138 int get_number(units
*res
, unsigned char si
, units prev_value
)
141 switch (get_incr_number(&v
, si
)) {
148 *res
= prev_value
+ v
;
151 *res
= prev_value
- v
;
159 int get_integer(int *res
, int prev_value
)
162 switch (get_incr_number(&v
, 0)) {
169 *res
= prev_value
+ int(v
);
172 *res
= prev_value
- int(v
);
181 static incr_number_result
get_incr_number(units
*res
, unsigned char si
)
185 incr_number_result result
= ABSOLUTE
;
186 if (tok
.ch() == '+') {
190 else if (tok
.ch() == '-') {
194 if (parse_expr(res
, si
, 0))
200 static int start_number()
205 warning(WARN_MISSING
, "missing number");
209 warning(WARN_TAB
, "tab character where number expected");
212 if (tok
.right_brace()) {
213 warning(WARN_RIGHT_BRACE
, "`\\}' where number expected");
219 enum { OP_LEQ
= 'L', OP_GEQ
= 'G', OP_MAX
= 'X', OP_MIN
= 'N' };
221 #define SCALE_INDICATOR_CHARS "icPmnpuvMsz"
223 static int parse_term(units
*v
, int scale_indicator
, int parenthesised
);
225 static int parse_expr(units
*v
, int scale_indicator
, int parenthesised
)
227 int result
= parse_term(v
, scale_indicator
, parenthesised
);
244 if (tok
.ch() == '=') {
248 else if (tok
.ch() == '?') {
255 if (tok
.ch() == '=') {
259 else if (tok
.ch() == '?') {
273 if (!parse_term(&v2
, scale_indicator
, parenthesised
))
301 *v
= *v
> 0 && v2
> 0;
304 *v
= *v
> 0 || v2
> 0;
307 if (*v
< INT_MIN
- v2
)
311 if (*v
> INT_MAX
- v2
)
315 error("addition overflow");
322 if (*v
> INT_MAX
+ v2
)
326 if (*v
< INT_MIN
+ v2
)
330 error("subtraction overflow");
338 if (*v
> -(unsigned)INT_MIN
/ -(unsigned)v2
)
341 else if (-(unsigned)*v
> INT_MAX
/ -(unsigned)v2
)
346 if (*v
> INT_MAX
/ v2
)
349 else if (-(unsigned)*v
> -(unsigned)INT_MIN
/ v2
)
353 error("multiplication overflow");
360 error("division by zero");
367 error("modulus by zero");
379 static int parse_term(units
*v
, int scale_indicator
, int parenthesised
)
383 if (parenthesised
&& tok
.space())
385 else if (tok
.ch() == '+')
387 else if (tok
.ch() == '-') {
389 negative
= !negative
;
393 unsigned char c
= tok
.ch();
396 // | is not restricted to the outermost level
399 if (!parse_term(v
, scale_indicator
, parenthesised
))
402 tem
= (scale_indicator
== 'v'
403 ? curdiv
->get_vertical_position().to_units()
404 : curenv
->get_input_line_position().to_units());
406 if (*v
< INT_MIN
+ tem
) {
407 error("numeric overflow");
412 if (*v
> INT_MAX
+ tem
) {
413 error("numeric overflow");
420 error("numeric overflow");
430 warning(WARN_SYNTAX
, "empty parentheses");
435 else if (c
!= 0 && strchr(SCALE_INDICATOR_CHARS
, c
) != 0) {
437 if (tok
.ch() == ';') {
442 error("expected `;' after scale-indicator (got %1)",
451 if (!parse_expr(v
, scale_indicator
, 1))
454 if (tok
.ch() != ')') {
455 warning(WARN_SYNTAX
, "missing `)' (got %1)", tok
.description());
461 error("numeric overflow");
482 if (*v
> INT_MAX
/10) {
483 error("numeric overflow");
487 if (*v
> INT_MAX
- (int(c
) - '0')) {
488 error("numeric overflow");
494 } while (csdigit(c
));
504 warning(WARN_SYNTAX
, "empty left operand");
508 warning(WARN_NUMBER
, "numeric expression expected (got %1)",
513 if (tok
.ch() == '.') {
519 // we may multiply the divisor by 254 later on
520 if (divisor
<= INT_MAX
/2540 && *v
<= (INT_MAX
- 9)/10) {
528 int si
= scale_indicator
;
530 if ((c
= tok
.ch()) != 0 && strchr(SCALE_INDICATOR_CHARS
, c
) != 0) {
531 switch (scale_indicator
) {
533 if (c
!= 'u' && c
!= 'z') {
535 "only `z' and `u' scale indicators valid in this context");
541 warning(WARN_SCALE
, "scale indicator invalid in this context");
548 warning(WARN_SCALE
, "`z' scale indicator invalid in this context");
554 // Don't do tok.next() here because the next token might be \s, which
555 // would affect the interpretation of m.
560 *v
= scale(*v
, units_per_inch
, divisor
);
563 *v
= scale(*v
, units_per_inch
*100, divisor
*254);
571 *v
= scale(*v
, units_per_inch
, divisor
*72);
574 *v
= scale(*v
, units_per_inch
, divisor
*6);
578 // Convert to hunits so that with -Tascii `m' behaves as in nroff.
579 hunits em
= curenv
->get_size();
580 *v
= scale(*v
, em
.is_zero() ? hresolution
: em
.to_units(), divisor
);
585 hunits em
= curenv
->get_size();
586 *v
= scale(*v
, em
.is_zero() ? hresolution
: em
.to_units(), divisor
*100);
591 // Convert to hunits so that with -Tascii `n' behaves as in nroff.
592 hunits en
= curenv
->get_size()/2;
593 *v
= scale(*v
, en
.is_zero() ? hresolution
: en
.to_units(), divisor
);
597 *v
= scale(*v
, curenv
->get_vertical_spacing().to_units(), divisor
);
600 while (divisor
> INT_MAX
/(sizescale
*72)) {
604 *v
= scale(*v
, units_per_inch
, divisor
*sizescale
*72);
607 *v
= scale(*v
, sizescale
, divisor
);
616 error("numeric overflow");
624 units
scale(units n
, units x
, units y
)
626 assert(x
>= 0 && y
> 0);
634 if (-(unsigned)n
<= -(unsigned)INT_MIN
/x
)
637 double res
= n
*double(x
)/double(y
);
639 error("numeric overflow");
642 else if (res
< INT_MIN
) {
643 error("numeric overflow");
649 vunits::vunits(units x
)
651 // don't depend on the rounding direction for division of negative integers
652 if (vresolution
== 1)
656 ? -((-x
+ vresolution
/2 - 1)/vresolution
)
657 : (x
+ vresolution
/2 - 1)/vresolution
);
660 hunits::hunits(units x
)
662 // don't depend on the rounding direction for division of negative integers
663 if (hresolution
== 1)
667 ? -((-x
+ hresolution
/2 - 1)/hresolution
)
668 : (x
+ hresolution
/2 - 1)/hresolution
);