1 /* $NetBSD: nametoindex.cpp,v 1.1.1.1 2016/01/13 18:41:48 christos Exp $ */ 2 3 // -*- C++ -*- 4 /* Copyright (C) 1989, 1990, 1991, 1992, 2000, 2001, 2002, 2003, 2004 5 Free Software Foundation, Inc. 6 Written by James Clark (jjc@jclark.com) 7 8 This file is part of groff. 9 10 groff is free software; you can redistribute it and/or modify it under 11 the terms of the GNU General Public License as published by the Free 12 Software Foundation; either version 2, or (at your option) any later 13 version. 14 15 groff is distributed in the hope that it will be useful, but WITHOUT ANY 16 WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18 for more details. 19 20 You should have received a copy of the GNU General Public License along 21 with groff; see the file COPYING. If not, write to the Free Software 22 Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 23 24 #include "lib.h" 25 26 #include <ctype.h> 27 #include <assert.h> 28 #include <stdlib.h> 29 #include "errarg.h" 30 #include "error.h" 31 #include "font.h" 32 #include "ptable.h" 33 34 declare_ptable(int) 35 implement_ptable(int) 36 37 class character_indexer { 38 public: 39 character_indexer(); 40 ~character_indexer(); 41 int ascii_char_index(unsigned char); 42 int named_char_index(const char *); 43 int numbered_char_index(int); 44 private: 45 enum { NSMALL = 256 }; 46 int next_index; 47 int ascii_index[256]; 48 int small_number_index[NSMALL]; 49 PTABLE(int) table; 50 }; 51 52 character_indexer::character_indexer() 53 : next_index(0) 54 { 55 int i; 56 for (i = 0; i < 256; i++) 57 ascii_index[i] = -1; 58 for (i = 0; i < NSMALL; i++) 59 small_number_index[i] = -1; 60 } 61 62 character_indexer::~character_indexer() 63 { 64 } 65 66 int character_indexer::ascii_char_index(unsigned char c) 67 { 68 if (ascii_index[c] < 0) 69 ascii_index[c] = next_index++; 70 return ascii_index[c]; 71 } 72 73 int character_indexer::numbered_char_index(int n) 74 { 75 if (n >= 0 && n < NSMALL) { 76 if (small_number_index[n] < 0) 77 small_number_index[n] = next_index++; 78 return small_number_index[n]; 79 } 80 // Not the most efficient possible implementation. 81 char buf[INT_DIGITS + 3]; 82 buf[0] = ' '; 83 strcpy(buf + 1, i_to_a(n)); 84 return named_char_index(buf); 85 } 86 87 int character_indexer::named_char_index(const char *s) 88 { 89 int *np = table.lookup(s); 90 if (!np) { 91 np = new int[1]; 92 *np = next_index++; 93 table.define(s, np); 94 } 95 return *np; 96 } 97 98 static character_indexer indexer; 99 100 int font::number_to_index(int n) 101 { 102 return indexer.numbered_char_index(n); 103 } 104 105 int font::name_to_index(const char *s) 106 { 107 assert(s != 0 && s[0] != '\0' && s[0] != ' '); 108 if (s[1] == '\0') 109 return indexer.ascii_char_index(s[0]); 110 /* char128 and \200 are synonyms */ 111 if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') { 112 char *val; 113 long n = strtol(s + 4, &val, 10); 114 if (val != s + 4 && *val == '\0' && n >= 0 && n < 256) 115 return indexer.ascii_char_index((unsigned char)n); 116 } 117 return indexer.named_char_index(s); 118 } 119 120