/* Copyright (C) 1989, 1990 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.uucp)
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 1, or (at your option) any later
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
You should have received a copy of the GNU General Public License along
with groff; see the file LICENSE. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
object_dictionary
number_reg_dictionary(101);
int reg::get_value(units
* /*d*/)
error("can't increment read-only register");
error("can't decrement read-only register");
void reg::set_increment(units
/*n*/)
error("can't auto increment read-only register");
void reg::alter_format(char /*f*/, int /*w*/)
error("can't alter format of read-only register");
const char *reg::get_format()
void reg::set_value(units
/*n*/)
error("can't write read-only register");
general_reg::general_reg() : format('1'), width(0), inc(0)
static const char *number_value_to_ascii(int value
, char format
, int width
)
static char buf
[128]; // must be at least 21
else if (width
> sizeof(buf
) - 2)
sprintf(buf
, "%.*d", sizeof(buf
) - 2, int(value
));
sprintf(buf
, "%.*d", width
, int(value
));
// troff uses z and w to represent 10000 and 5000 in Roman
// numerals; I can find no historical basis for this usage
const char *s
= format
== 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
if (n
>= 40000 || n
<= -40000) {
error("magnitude of `%1' too big for i or I format", n
);
for (int i
= 1000; i
> 0; i
/= 10, s
+= 2) {
char *q
= buf
[0] == '-' ? buf
+1 : buf
;
const char *general_reg::get_string()
return number_value_to_ascii(n
, format
, width
);
void general_reg::increment()
void general_reg::decrement()
void general_reg::set_increment(units n
)
void general_reg::alter_format(char f
, int w
)
static const char *number_format_to_ascii(char format
, int width
)
if (n
> int(sizeof(buf
)) - 1)
n
= int(sizeof(buf
)) - 1;
sprintf(buf
, "%.*d", n
, 0);
const char *general_reg::get_format()
return number_format_to_ascii(format
, width
);
class number_reg
: public general_reg
{
number_reg::number_reg() : value(0)
int number_reg::get_value(units
*res
)
void number_reg::set_value(units n
)
variable_reg::variable_reg(units
*p
) : ptr(p
)
void variable_reg::set_value(units n
)
int variable_reg::get_value(units
*res
)
reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
number_reg_dictionary
.define(nm
, r
);
if (!r
->get_value(&prev_value
))
if (get_number(&v
, 'u', prev_value
)) {
if (tok
.space() && has_arg() && get_number(&v
, 'u'))
reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
number_reg_dictionary
.define(nm
, r
);
if (!r
->get_value(&prev_value
))
if (get_number(&v
, 'u', prev_value
)) {
if (get_number(&v
, 'u')) {
warning(WARN_DELIM
, "closing delimiter does not match");
void set_number_reg(symbol nm
, units n
)
reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
number_reg_dictionary
.define(nm
, r
);
reg
*lookup_number_reg(symbol nm
)
reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
warning(WARN_REG
, "number register `%1' not defined", nm
.contents());
number_reg_dictionary
.define(nm
, r
);
reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
number_reg_dictionary
.define(nm
, r
);
} while (csdigit(tok
.ch()));
else if (c
== 'i' || c
== 'I' || c
== 'a' || c
== 'A')
else if (tok
.newline() || tok
.eof())
warning(WARN_MISSING
, "missing number register format");
error("bad number register format (got %1)", tok
.description());
number_reg_dictionary
.remove(s
);
if (!number_reg_dictionary
.alias(s1
, s2
))
warning(WARN_REG
, "number register `%1' not defined", s2
.contents());
number_reg_dictionary
.rename(s1
, s2
);
object_dictionary_iterator
iter(number_reg_dictionary
);
while (iter
.get(&s
, (object
**)&r
)) {
errprint("%1\t", s
.contents());
const char *p
= r
->get_string();
init_request("rr", remove_reg
);
init_request("nr", define_number_reg
);
init_request("af", alter_format
);
init_request("aln", alias_reg
);
init_request("rnn", rename_reg
);
init_request("pnr", print_number_regs
);