groff: update vendor branch to v1.20.1
[dragonfly.git] / contrib / groff / src / libs / libgroff / nametoindex.cpp
CommitLineData
92d0a6a6 1// -*- C++ -*-
4d3e9548
JL
2/* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004, 2006,
3 2008, 2009
92d0a6a6
JR
4 Free Software Foundation, Inc.
5 Written by James Clark (jjc@jclark.com)
6
7This file is part of groff.
8
9groff is free software; you can redistribute it and/or modify it under
10the terms of the GNU General Public License as published by the Free
4d3e9548
JL
11Software Foundation, either version 3 of the License, or
12(at your option) any later version.
92d0a6a6
JR
13
14groff is distributed in the hope that it will be useful, but WITHOUT ANY
15WARRANTY; without even the implied warranty of MERCHANTABILITY or
16FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17for more details.
18
4d3e9548
JL
19You should have received a copy of the GNU General Public License
20along with this program. If not, see <http://www.gnu.org/licenses/>. */
92d0a6a6
JR
21
22#include "lib.h"
23
24#include <ctype.h>
25#include <assert.h>
26#include <stdlib.h>
27#include "errarg.h"
28#include "error.h"
29#include "font.h"
30#include "ptable.h"
4d3e9548 31#include "itable.h"
92d0a6a6 32
4d3e9548
JL
33// Every glyphinfo is actually a charinfo.
34class charinfo : glyph {
35public:
36 const char *name; // The glyph name, or NULL.
37 friend class character_indexer;
38};
39
40// PTABLE(charinfo) is a hash table mapping `const char *' to `charinfo *'.
41declare_ptable(charinfo)
42implement_ptable(charinfo)
92d0a6a6 43
4d3e9548
JL
44// ITABLE(charinfo) is a hash table mapping `int >= 0' to `charinfo *'.
45declare_itable(charinfo)
46implement_itable(charinfo)
47
48// This class is as a registry storing all named and numbered glyphs known
49// so far, and assigns a unique index to each glyph.
92d0a6a6
JR
50class character_indexer {
51public:
52 character_indexer();
53 ~character_indexer();
4d3e9548
JL
54 // --------------------- Lookup or creation of a glyph.
55 glyph *ascii_char_glyph(unsigned char);
56 glyph *named_char_glyph(const char *);
57 glyph *numbered_char_glyph(int);
92d0a6a6 58private:
4d3e9548
JL
59 int next_index; // Number of glyphs already allocated.
60 PTABLE(charinfo) table; // Table mapping name to glyph.
61 glyph *ascii_glyph[256]; // Shorthand table for looking up "charNNN"
62 // glyphs.
63 ITABLE(charinfo) ntable; // Table mapping number to glyph.
92d0a6a6 64 enum { NSMALL = 256 };
4d3e9548
JL
65 glyph *small_number_glyph[NSMALL]; // Shorthand table for looking up
66 // numbered glyphs with small numbers.
92d0a6a6
JR
67};
68
69character_indexer::character_indexer()
70: next_index(0)
71{
72 int i;
73 for (i = 0; i < 256; i++)
4d3e9548 74 ascii_glyph[i] = UNDEFINED_GLYPH;
92d0a6a6 75 for (i = 0; i < NSMALL; i++)
4d3e9548 76 small_number_glyph[i] = UNDEFINED_GLYPH;
92d0a6a6
JR
77}
78
79character_indexer::~character_indexer()
80{
81}
82
4d3e9548 83glyph *character_indexer::ascii_char_glyph(unsigned char c)
92d0a6a6 84{
4d3e9548
JL
85 if (ascii_glyph[c] == UNDEFINED_GLYPH) {
86 char buf[4+3+1];
87 memcpy(buf, "char", 4);
88 strcpy(buf + 4, i_to_a(c));
89 charinfo *ci = new charinfo;
90 ci->index = next_index++;
91 ci->number = -1;
92 ci->name = strsave(buf);
93 ascii_glyph[c] = ci;
94 }
95 return ascii_glyph[c];
92d0a6a6
JR
96}
97
4d3e9548 98inline glyph *character_indexer::named_char_glyph(const char *s)
92d0a6a6 99{
4d3e9548
JL
100 // Glyphs with name `charNNN' are only stored in ascii_glyph[], not
101 // in the table. Therefore treat them specially here.
102 if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') {
103 char *val;
104 long n = strtol(s + 4, &val, 10);
105 if (val != s + 4 && *val == '\0' && n >= 0 && n < 256)
106 return ascii_char_glyph((unsigned char)n);
107 }
108 charinfo *ci = table.lookupassoc(&s);
109 if (ci == NULL) {
110 ci = new charinfo[1];
111 ci->index = next_index++;
112 ci->number = -1;
113 ci->name = table.define(s, ci);
92d0a6a6 114 }
4d3e9548 115 return ci;
92d0a6a6
JR
116}
117
4d3e9548 118inline glyph *character_indexer::numbered_char_glyph(int n)
92d0a6a6 119{
4d3e9548
JL
120 if (n >= 0 && n < NSMALL) {
121 if (small_number_glyph[n] == UNDEFINED_GLYPH) {
122 charinfo *ci = new charinfo;
123 ci->index = next_index++;
124 ci->number = n;
125 ci->name = NULL;
126 small_number_glyph[n] = ci;
127 }
128 return small_number_glyph[n];
129 }
130 charinfo *ci = ntable.lookup(n);
131 if (ci == NULL) {
132 ci = new charinfo[1];
133 ci->index = next_index++;
134 ci->number = n;
135 ci->name = NULL;
136 ntable.define(n, ci);
92d0a6a6 137 }
4d3e9548 138 return ci;
92d0a6a6
JR
139}
140
141static character_indexer indexer;
142
4d3e9548 143glyph *number_to_glyph(int n)
92d0a6a6 144{
4d3e9548 145 return indexer.numbered_char_glyph(n);
92d0a6a6
JR
146}
147
4d3e9548
JL
148// troff overrides this function with its own version.
149
150glyph *name_to_glyph(const char *s)
92d0a6a6
JR
151{
152 assert(s != 0 && s[0] != '\0' && s[0] != ' ');
153 if (s[1] == '\0')
4d3e9548
JL
154 // \200 and char128 are synonyms
155 return indexer.ascii_char_glyph(s[0]);
156 return indexer.named_char_glyph(s);
92d0a6a6
JR
157}
158
4d3e9548
JL
159const char *glyph_to_name(glyph *g)
160{
161 charinfo *ci = (charinfo *)g; // Every glyph is actually a charinfo.
162 return ci->name;
163}