2 /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001
3 Free Software Foundation, Inc.
4 Written by James Clark (jjc@jclark.com)
6 This file is part of groff.
8 groff is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 2, or (at your option) any later
13 groff is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License along
19 with groff; see the file COPYING. If not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
24 #include "dictionary.h"
29 object_dictionary
number_reg_dictionary(101);
31 int reg::get_value(units
* /*d*/)
38 error("can't increment read-only register");
43 error("can't decrement read-only register");
46 void reg::set_increment(units
/*n*/)
48 error("can't auto increment read-only register");
51 void reg::alter_format(char /*f*/, int /*w*/)
53 error("can't alter format of read-only register");
56 const char *reg::get_format()
61 void reg::set_value(units
/*n*/)
63 error("can't write read-only register");
66 general_reg::general_reg() : format('1'), width(0), inc(0)
70 static char uppercase_array
[] = {
71 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
72 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
73 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
77 static char lowercase_array
[] = {
78 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
79 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
80 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
84 static const char *number_value_to_ascii(int value
, char format
, int width
)
86 static char buf
[128]; // must be at least 21
91 else if (width
> int(sizeof(buf
) - 2))
92 sprintf(buf
, "%.*d", int(sizeof(buf
) - 2), int(value
));
94 sprintf(buf
, "%.*d", width
, int(value
));
100 // troff uses z and w to represent 10000 and 5000 in Roman
101 // numerals; I can find no historical basis for this usage
102 const char *s
= format
== 'i' ? "zwmdclxvi" : "ZWMDCLXVI";
104 if (n
>= 40000 || n
<= -40000) {
105 error("magnitude of `%1' too big for i or I format", n
);
121 for (int i
= 1000; i
> 0; i
/= 10, s
+= 2) {
178 // this is a bit tricky
185 *p
++ = format
== 'a' ? lowercase_array
[d
- 1] :
186 uppercase_array
[d
- 1];
189 char *q
= buf
[0] == '-' ? buf
+ 1 : buf
;
207 const char *general_reg::get_string()
212 return number_value_to_ascii(n
, format
, width
);
216 void general_reg::increment()
223 void general_reg::decrement()
230 void general_reg::set_increment(units n
)
235 void general_reg::alter_format(char f
, int w
)
241 static const char *number_format_to_ascii(char format
, int width
)
247 if (n
> int(sizeof(buf
)) - 1)
248 n
= int(sizeof(buf
)) - 1;
249 sprintf(buf
, "%.*d", n
, 0);
262 const char *general_reg::get_format()
264 return number_format_to_ascii(format
, width
);
267 class number_reg
: public general_reg
{
271 int get_value(units
*);
272 void set_value(units
);
275 number_reg::number_reg() : value(0)
279 int number_reg::get_value(units
*res
)
285 void number_reg::set_value(units n
)
290 variable_reg::variable_reg(units
*p
) : ptr(p
)
294 void variable_reg::set_value(units n
)
299 int variable_reg::get_value(units
*res
)
305 void define_number_reg()
307 symbol nm
= get_name(1);
312 reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
315 if (!r
|| !r
->get_value(&prev_value
))
317 if (get_number(&v
, 'u', prev_value
)) {
320 number_reg_dictionary
.define(nm
, r
);
323 if (tok
.space() && has_arg() && get_number(&v
, 'u'))
330 void inline_define_reg()
334 if (!start
.delimiter(1))
337 symbol nm
= get_name(1);
340 reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
343 number_reg_dictionary
.define(nm
, r
);
347 if (!r
->get_value(&prev_value
))
349 if (get_number(&v
, 'u', prev_value
)) {
352 if (get_number(&v
, 'u')) {
355 warning(WARN_DELIM
, "closing delimiter does not match");
362 void set_number_reg(symbol nm
, units n
)
364 reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
367 number_reg_dictionary
.define(nm
, r
);
372 reg
*lookup_number_reg(symbol nm
)
374 reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
376 warning(WARN_REG
, "number register `%1' not defined", nm
.contents());
378 number_reg_dictionary
.define(nm
, r
);
385 symbol nm
= get_name(1);
390 reg
*r
= (reg
*)number_reg_dictionary
.lookup(nm
);
393 number_reg_dictionary
.define(nm
, r
);
402 } while (csdigit(tok
.ch()));
403 r
->alter_format('1', n
);
405 else if (c
== 'i' || c
== 'I' || c
== 'a' || c
== 'A')
407 else if (tok
.newline() || tok
.eof())
408 warning(WARN_MISSING
, "missing number register format");
410 error("bad number register format (got %1)", tok
.description());
417 symbol s
= get_name();
420 number_reg_dictionary
.remove(s
);
427 symbol s1
= get_name(1);
429 symbol s2
= get_name(1);
431 if (!number_reg_dictionary
.alias(s1
, s2
))
432 warning(WARN_REG
, "number register `%1' not defined", s2
.contents());
440 symbol s1
= get_name(1);
442 symbol s2
= get_name(1);
444 number_reg_dictionary
.rename(s1
, s2
);
449 void print_number_regs()
451 object_dictionary_iterator
iter(number_reg_dictionary
);
454 while (iter
.get(&s
, (object
**)&r
)) {
455 assert(!s
.is_null());
456 errprint("%1\t", s
.contents());
457 const char *p
= r
->get_string();
466 void init_reg_requests()
468 init_request("rr", remove_reg
);
469 init_request("nr", define_number_reg
);
470 init_request("af", alter_format
);
471 init_request("aln", alias_reg
);
472 init_request("rnn", rename_reg
);
473 init_request("pnr", print_number_regs
);