diff options
Diffstat (limited to 'src/libs/libgroff')
62 files changed, 12224 insertions, 0 deletions
diff --git a/src/libs/libgroff/assert.cpp b/src/libs/libgroff/assert.cpp new file mode 100644 index 0000000..9da3d46 --- /dev/null +++ b/src/libs/libgroff/assert.cpp @@ -0,0 +1,38 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +extern "C" const char *program_name; + +void assertion_failed(int lineno, const char *filename, + const char *function, const char *msg) +{ + if (program_name != 0) + fprintf(stderr, "%s: ", program_name); + fprintf(stderr, "%s:%d: %s(): assertion failed: '%s'\n", filename, + lineno, function, msg); + fflush(stderr); + abort(); +} diff --git a/src/libs/libgroff/change_lf.cpp b/src/libs/libgroff/change_lf.cpp new file mode 100644 index 0000000..eb98766 --- /dev/null +++ b/src/libs/libgroff/change_lf.cpp @@ -0,0 +1,37 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <string.h> + +extern char *strsave(const char *); + +extern const char *current_filename; +extern int current_lineno; + +void change_filename(const char *f) +{ + if (current_filename != 0 && strcmp(current_filename, f) == 0) + return; + current_filename = strsave(f); +} + +void change_lineno(int ln) +{ + current_lineno = ln; +} diff --git a/src/libs/libgroff/cmap.cpp b/src/libs/libgroff/cmap.cpp new file mode 100644 index 0000000..3f2c0c3 --- /dev/null +++ b/src/libs/libgroff/cmap.cpp @@ -0,0 +1,56 @@ +// -*- C++ -*- +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <ctype.h> +#include "cmap.h" + +cmap cmlower(CMAP_BUILTIN); +cmap cmupper(CMAP_BUILTIN); + +#ifdef isascii +#define ISASCII(c) isascii(c) +#else +#define ISASCII(c) (1) +#endif + +cmap::cmap() +{ + unsigned char *p = v; + for (int i = 0; i <= UCHAR_MAX; i++) + p[i] = i; +} + +cmap::cmap(cmap_builtin) +{ + // these are initialised by cmap_init::cmap_init() +} + +int cmap_init::initialised = 0; + +cmap_init::cmap_init() +{ + if (initialised) + return; + initialised = 1; + for (int i = 0; i <= UCHAR_MAX; i++) { + cmupper.v[i] = ISASCII(i) && islower(i) ? toupper(i) : i; + cmlower.v[i] = ISASCII(i) && isupper(i) ? tolower(i) : i; + } +} diff --git a/src/libs/libgroff/color.cpp b/src/libs/libgroff/color.cpp new file mode 100644 index 0000000..388c2ee --- /dev/null +++ b/src/libs/libgroff/color.cpp @@ -0,0 +1,404 @@ +/* Copyright (C) 2001-2020 Free Software Foundation, Inc. + Written by Gaius Mulley <gaius@glam.ac.uk> + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" +#include "color.h" +#include "cset.h" + +#include <assert.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include "errarg.h" +#include "error.h" + +static inline unsigned int +min(const unsigned int a, const unsigned int b) +{ + if (a < b) + return a; + else + return b; +} + + +color::color(const color * const c) +{ + nm = c->nm; + scheme = c->scheme; + components[0] = c->components[0]; + components[1] = c->components[1]; + components[2] = c->components[2]; + components[3] = c->components[3]; +} + +color::~color() +{ +} + +int color::operator==(const color & c) const +{ + if (scheme != c.scheme) + return 0; + switch (scheme) { + case DEFAULT: + break; + case RGB: + if (Red != c.Red || Green != c.Green || Blue != c.Blue) + return 0; + break; + case CMYK: + if (Cyan != c.Cyan || Magenta != c.Magenta + || Yellow != c.Yellow || Black != c.Black) + return 0; + break; + case GRAY: + if (Gray != c.Gray) + return 0; + break; + case CMY: + if (Cyan != c.Cyan || Magenta != c.Magenta || Yellow != c.Yellow) + return 0; + break; + } + return 1; +} + +int color::operator!=(const color & c) const +{ + return !(*this == c); +} + +color_scheme color::get_components(unsigned int *c) const +{ +#if 0 + if (sizeof (c) < sizeof (unsigned int) * 4) + fatal("argument is not big enough to store 4 color components"); +#endif + c[0] = components[0]; + c[1] = components[1]; + c[2] = components[2]; + c[3] = components[3]; + return scheme; +} + +void color::set_default() +{ + scheme = DEFAULT; +} + +// (0, 0, 0) is black + +void color::set_rgb(const unsigned int r, const unsigned int g, + const unsigned int b) +{ + scheme = RGB; + Red = min(MAX_COLOR_VAL, r); + Green = min(MAX_COLOR_VAL, g); + Blue = min(MAX_COLOR_VAL, b); +} + +// (0, 0, 0) is white + +void color::set_cmy(const unsigned int c, const unsigned int m, + const unsigned int y) +{ + scheme = CMY; + Cyan = min(MAX_COLOR_VAL, c); + Magenta = min(MAX_COLOR_VAL, m); + Yellow = min(MAX_COLOR_VAL, y); +} + +// (0, 0, 0, 0) is white + +void color::set_cmyk(const unsigned int c, const unsigned int m, + const unsigned int y, const unsigned int k) +{ + scheme = CMYK; + Cyan = min(MAX_COLOR_VAL, c); + Magenta = min(MAX_COLOR_VAL, m); + Yellow = min(MAX_COLOR_VAL, y); + Black = min(MAX_COLOR_VAL, k); +} + +// (0) is black + +void color::set_gray(const unsigned int g) +{ + scheme = GRAY; + Gray = min(MAX_COLOR_VAL, g); +} + +/* + * atoh - computes the decimal value of a hexadecimal number string. + * 'length' characters of 's' are read. Returns 1 if successful. + */ + +static int atoh(unsigned int *result, + const char * const s, const size_t length) +{ + size_t i = 0; + unsigned int val = 0; + while ((i < length) && csxdigit(s[i])) { + if (csdigit(s[i])) + val = val*0x10 + (s[i]-'0'); + else if (csupper(s[i])) + val = val*0x10 + (s[i]-'A') + 10; + else + val = val*0x10 + (s[i]-'a') + 10; + i++; + } + if (i != length) + return 0; + *result = val; + return 1; +} + +/* + * read_encoding - set color from a hexadecimal color string. + * + * Use color scheme 'cs' to parse 'n' color components from string 's'. + * Returns 1 if successful. + */ + +int color::read_encoding(const color_scheme cs, const char * const s, + const size_t n) +{ + size_t hex_length = 2; + scheme = cs; + char *p = (char *) s; + p++; + if (*p == '#') { + hex_length = 4; + p++; + } + for (size_t i = 0; i < n; i++) { + if (!atoh(&(components[i]), p, hex_length)) + return 0; + if (hex_length == 2) + components[i] *= 0x101; // scale up -- 0xff should become 0xffff + p += hex_length; + } + return 1; +} + +int color::read_rgb(const char * const s) +{ + return read_encoding(RGB, s, 3); +} + +int color::read_cmy(const char * const s) +{ + return read_encoding(CMY, s, 3); +} + +int color::read_cmyk(const char * const s) +{ + return read_encoding(CMYK, s, 4); +} + +int color::read_gray(const char * const s) +{ + return read_encoding(GRAY, s, 1); +} + +void +color::get_rgb(unsigned int *r, unsigned int *g, unsigned int *b) const +{ + switch (scheme) { + case RGB: + *r = Red; + *g = Green; + *b = Blue; + break; + case CMY: + *r = MAX_COLOR_VAL - Cyan; + *g = MAX_COLOR_VAL - Magenta; + *b = MAX_COLOR_VAL - Yellow; + break; + case CMYK: + *r = MAX_COLOR_VAL + - min(MAX_COLOR_VAL, + Cyan * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black); + *g = MAX_COLOR_VAL + - min(MAX_COLOR_VAL, + Magenta * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black); + *b = MAX_COLOR_VAL + - min(MAX_COLOR_VAL, + Yellow * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black); + break; + case GRAY: + *r = *g = *b = Gray; + break; + default: + assert(0); + break; + } +} + +void +color::get_cmy(unsigned int *c, unsigned int *m, unsigned int *y) const +{ + switch (scheme) { + case RGB: + *c = MAX_COLOR_VAL - Red; + *m = MAX_COLOR_VAL - Green; + *y = MAX_COLOR_VAL - Blue; + break; + case CMY: + *c = Cyan; + *m = Magenta; + *y = Yellow; + break; + case CMYK: + *c = min(MAX_COLOR_VAL, + Cyan * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black); + *m = min(MAX_COLOR_VAL, + Magenta * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black); + *y = min(MAX_COLOR_VAL, + Yellow * (MAX_COLOR_VAL - Black) / MAX_COLOR_VAL + Black); + break; + case GRAY: + *c = *m = *y = MAX_COLOR_VAL - Gray; + break; + default: + assert(0); + break; + } +} + +void color::get_cmyk(unsigned int *c, unsigned int *m, + unsigned int *y, unsigned int *k) const +{ + switch (scheme) { + case RGB: + *k = min(MAX_COLOR_VAL - Red, + min(MAX_COLOR_VAL - Green, MAX_COLOR_VAL - Blue)); + if (MAX_COLOR_VAL == *k) { + *c = MAX_COLOR_VAL; + *m = MAX_COLOR_VAL; + *y = MAX_COLOR_VAL; + } + else { + *c = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Red - *k)) + / (MAX_COLOR_VAL - *k); + *m = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Green - *k)) + / (MAX_COLOR_VAL - *k); + *y = (MAX_COLOR_VAL * (MAX_COLOR_VAL - Blue - *k)) + / (MAX_COLOR_VAL - *k); + } + break; + case CMY: + *k = min(Cyan, min(Magenta, Yellow)); + if (MAX_COLOR_VAL == *k) { + *c = MAX_COLOR_VAL; + *m = MAX_COLOR_VAL; + *y = MAX_COLOR_VAL; + } + else { + *c = (MAX_COLOR_VAL * (Cyan - *k)) / (MAX_COLOR_VAL - *k); + *m = (MAX_COLOR_VAL * (Magenta - *k)) / (MAX_COLOR_VAL - *k); + *y = (MAX_COLOR_VAL * (Yellow - *k)) / (MAX_COLOR_VAL - *k); + } + break; + case CMYK: + *c = Cyan; + *m = Magenta; + *y = Yellow; + *k = Black; + break; + case GRAY: + *c = *m = *y = 0; + *k = MAX_COLOR_VAL - Gray; + break; + default: + assert(0); + break; + } +} + +// we use '0.222r + 0.707g + 0.071b' (this is the ITU standard) +// as an approximation for gray + +void color::get_gray(unsigned int *g) const +{ + switch (scheme) { + case RGB: + *g = (222*Red + 707*Green + 71*Blue) / 1000; + break; + case CMY: + *g = MAX_COLOR_VAL - (222*Cyan + 707*Magenta + 71*Yellow) / 1000; + break; + case CMYK: + *g = (MAX_COLOR_VAL - (222*Cyan + 707*Magenta + 71*Yellow) / 1000) + * (MAX_COLOR_VAL - Black); + break; + case GRAY: + *g = Gray; + break; + default: + assert(0); + break; + } +} + +char *color::print_color() +{ + char *s = new char[30]; + switch (scheme) { + case DEFAULT: + sprintf(s, "default"); + break; + case RGB: + sprintf(s, "rgb %.2ff %.2ff %.2ff", + double(Red) / double(MAX_COLOR_VAL), + double(Green) / double(MAX_COLOR_VAL), + double(Blue) / double(MAX_COLOR_VAL)); + break; + case CMY: + sprintf(s, "cmy %.2ff %.2ff %.2ff", + double(Cyan) / double(MAX_COLOR_VAL), + double(Magenta) / double(MAX_COLOR_VAL), + double(Yellow) / double(MAX_COLOR_VAL)); + break; + case CMYK: + sprintf(s, "cmyk %.2ff %.2ff %.2ff %.2ff", + double(Cyan) / double(MAX_COLOR_VAL), + double(Magenta) / double(MAX_COLOR_VAL), + double(Yellow) / double(MAX_COLOR_VAL), + double(Black) / double(MAX_COLOR_VAL)); + break; + case GRAY: + sprintf(s, "gray %.2ff", + double(Gray) / double(MAX_COLOR_VAL)); + break; + } + return s; +} + +color default_color; + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/config.charset b/src/libs/libgroff/config.charset new file mode 100755 index 0000000..8fca485 --- /dev/null +++ b/src/libs/libgroff/config.charset @@ -0,0 +1,684 @@ +#! /bin/sh +# Output a system dependent table of character encoding aliases. +# +# Copyright (C) 2000-2020 Free Software Foundation, Inc. +# +# This program 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 2, or (at your option) +# any later version. +# +# This program 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 for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, see <http://www.gnu.org/licenses/>. +# +# The table consists of lines of the form +# ALIAS CANONICAL +# +# ALIAS is the (system dependent) result of "nl_langinfo (CODESET)". +# ALIAS is compared in a case sensitive way. +# +# CANONICAL is the GNU canonical name for this character encoding. +# It must be an encoding supported by libiconv. Support by GNU libc is +# also desirable. CANONICAL is case insensitive. Usually an upper case +# MIME charset name is preferred. +# The current list of GNU canonical charset names is as follows. +# +# name MIME? used by which systems +# (darwin = Mac OS X, woe32 = native Windows) +# +# ASCII, ANSI_X3.4-1968 glibc solaris freebsd netbsd darwin cygwin +# ISO-8859-1 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin +# ISO-8859-2 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin +# ISO-8859-3 Y glibc solaris cygwin +# ISO-8859-4 Y osf solaris freebsd netbsd openbsd darwin +# ISO-8859-5 Y glibc aix hpux irix osf solaris freebsd netbsd openbsd darwin cygwin +# ISO-8859-6 Y glibc aix hpux solaris cygwin +# ISO-8859-7 Y glibc aix hpux irix osf solaris netbsd openbsd darwin cygwin +# ISO-8859-8 Y glibc aix hpux osf solaris cygwin +# ISO-8859-9 Y glibc aix hpux irix osf solaris darwin cygwin +# ISO-8859-13 glibc netbsd openbsd darwin cygwin +# ISO-8859-14 glibc cygwin +# ISO-8859-15 glibc aix osf solaris freebsd netbsd openbsd darwin cygwin +# KOI8-R Y glibc solaris freebsd netbsd openbsd darwin +# KOI8-U Y glibc freebsd netbsd openbsd darwin cygwin +# KOI8-T glibc +# CP437 dos +# CP775 dos +# CP850 aix osf dos +# CP852 dos +# CP855 dos +# CP856 aix +# CP857 dos +# CP861 dos +# CP862 dos +# CP864 dos +# CP865 dos +# CP866 freebsd netbsd openbsd darwin dos +# CP869 dos +# CP874 woe32 dos +# CP922 aix +# CP932 aix cygwin woe32 dos +# CP943 aix +# CP949 osf darwin woe32 dos +# CP950 woe32 dos +# CP1046 aix +# CP1124 aix +# CP1125 dos +# CP1129 aix +# CP1131 darwin +# CP1250 woe32 +# CP1251 glibc solaris netbsd openbsd darwin cygwin woe32 +# CP1252 aix woe32 +# CP1253 woe32 +# CP1254 woe32 +# CP1255 glibc woe32 +# CP1256 woe32 +# CP1257 woe32 +# GB2312 Y glibc aix hpux irix solaris freebsd netbsd darwin +# EUC-JP Y glibc aix hpux irix osf solaris freebsd netbsd darwin +# EUC-KR Y glibc aix hpux irix osf solaris freebsd netbsd darwin cygwin +# EUC-TW glibc aix hpux irix osf solaris netbsd +# BIG5 Y glibc aix hpux osf solaris freebsd netbsd darwin cygwin +# BIG5-HKSCS glibc solaris darwin +# GBK glibc aix osf solaris darwin cygwin woe32 dos +# GB18030 glibc solaris netbsd darwin +# SHIFT_JIS Y hpux osf solaris freebsd netbsd darwin +# JOHAB glibc solaris woe32 +# TIS-620 glibc aix hpux osf solaris cygwin +# VISCII Y glibc +# TCVN5712-1 glibc +# ARMSCII-8 glibc darwin +# GEORGIAN-PS glibc cygwin +# PT154 glibc +# HP-ROMAN8 hpux +# HP-ARABIC8 hpux +# HP-GREEK8 hpux +# HP-HEBREW8 hpux +# HP-TURKISH8 hpux +# HP-KANA8 hpux +# DEC-KANJI osf +# DEC-HANYU osf +# UTF-8 Y glibc aix hpux osf solaris netbsd darwin cygwin +# +# Note: Names which are not marked as being a MIME name should not be used in +# Internet protocols for information interchange (mail, news, etc.). +# +# Note: ASCII and ANSI_X3.4-1968 are synonymous canonical names. Applications +# must understand both names and treat them as equivalent. +# +# The first argument passed to this file is the canonical host specification, +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM + +host="$1" +os=`echo "$host" | sed -e 's/^[^-]*-[^-]*-\(.*\)$/\1/'` +echo "# This file contains a table of character encoding aliases," +echo "# suitable for operating system '${os}'." +echo "# It was automatically generated from config.charset." +# List of references, updated during installation: +echo "# Packages using this file: " +case "$os" in + linux-gnulibc1*) + # Linux libc5 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + echo "C ASCII" + echo "POSIX ASCII" + for l in af af_ZA ca ca_ES da da_DK de de_AT de_BE de_CH de_DE de_LU \ + en en_AU en_BW en_CA en_DK en_GB en_IE en_NZ en_US en_ZA \ + en_ZW es es_AR es_BO es_CL es_CO es_DO es_EC es_ES es_GT \ + es_HN es_MX es_PA es_PE es_PY es_SV es_US es_UY es_VE et \ + et_EE eu eu_ES fi fi_FI fo fo_FO fr fr_BE fr_CA fr_CH fr_FR \ + fr_LU ga ga_IE gl gl_ES id id_ID in in_ID is is_IS it it_CH \ + it_IT kl kl_GL nl nl_BE nl_NL no no_NO pt pt_BR pt_PT sv \ + sv_FI sv_SE; do + echo "$l ISO-8859-1" + echo "$l.iso-8859-1 ISO-8859-1" + echo "$l.iso-8859-15 ISO-8859-15" + echo "$l.iso-8859-15@euro ISO-8859-15" + echo "$l@euro ISO-8859-15" + echo "$l.cp-437 CP437" + echo "$l.cp-850 CP850" + echo "$l.cp-1252 CP1252" + echo "$l.cp-1252@euro CP1252" + #echo "$l.atari-st ATARI-ST" # not a commonly used encoding + echo "$l.utf-8 UTF-8" + echo "$l.utf-8@euro UTF-8" + done + for l in cs cs_CZ hr hr_HR hu hu_HU pl pl_PL ro ro_RO sk sk_SK sl \ + sl_SI sr sr_CS sr_YU; do + echo "$l ISO-8859-2" + echo "$l.iso-8859-2 ISO-8859-2" + echo "$l.cp-852 CP852" + echo "$l.cp-1250 CP1250" + echo "$l.utf-8 UTF-8" + done + for l in mk mk_MK ru ru_RU; do + echo "$l ISO-8859-5" + echo "$l.iso-8859-5 ISO-8859-5" + echo "$l.koi8-r KOI8-R" + echo "$l.cp-866 CP866" + echo "$l.cp-1251 CP1251" + echo "$l.utf-8 UTF-8" + done + for l in ar ar_SA; do + echo "$l ISO-8859-6" + echo "$l.iso-8859-6 ISO-8859-6" + echo "$l.cp-864 CP864" + #echo "$l.cp-868 CP868" # not a commonly used encoding + echo "$l.cp-1256 CP1256" + echo "$l.utf-8 UTF-8" + done + for l in el el_GR gr gr_GR; do + echo "$l ISO-8859-7" + echo "$l.iso-8859-7 ISO-8859-7" + echo "$l.cp-869 CP869" + echo "$l.cp-1253 CP1253" + echo "$l.cp-1253@euro CP1253" + echo "$l.utf-8 UTF-8" + echo "$l.utf-8@euro UTF-8" + done + for l in he he_IL iw iw_IL; do + echo "$l ISO-8859-8" + echo "$l.iso-8859-8 ISO-8859-8" + echo "$l.cp-862 CP862" + echo "$l.cp-1255 CP1255" + echo "$l.utf-8 UTF-8" + done + for l in tr tr_TR; do + echo "$l ISO-8859-9" + echo "$l.iso-8859-9 ISO-8859-9" + echo "$l.cp-857 CP857" + echo "$l.cp-1254 CP1254" + echo "$l.utf-8 UTF-8" + done + for l in lt lt_LT lv lv_LV; do + #echo "$l BALTIC" # not a commonly used encoding, wrong encoding name + echo "$l ISO-8859-13" + done + for l in ru_UA uk uk_UA; do + echo "$l KOI8-U" + done + for l in zh zh_CN; do + #echo "$l GB_2312-80" # not a commonly used encoding, wrong encoding name + echo "$l GB2312" + done + for l in ja ja_JP ja_JP.EUC; do + echo "$l EUC-JP" + done + for l in ko ko_KR; do + echo "$l EUC-KR" + done + for l in th th_TH; do + echo "$l TIS-620" + done + for l in fa fa_IR; do + #echo "$l ISIRI-3342" # a broken encoding + echo "$l.utf-8 UTF-8" + done + ;; + linux* | *-gnu*) + # With glibc-2.1 or newer, we don't need any canonicalization, + # because glibc has iconv and both glibc and libiconv support all + # GNU canonical names directly. Therefore, the Makefile does not + # need to install the alias file at all. + # The following applies only to glibc-2.0.x and older libcs. + echo "ISO_646.IRV:1983 ASCII" + ;; + aix*) + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-6 ISO-8859-6" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-8 ISO-8859-8" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-15 ISO-8859-15" + echo "IBM-850 CP850" + echo "IBM-856 CP856" + echo "IBM-921 ISO-8859-13" + echo "IBM-922 CP922" + echo "IBM-932 CP932" + echo "IBM-943 CP943" + echo "IBM-1046 CP1046" + echo "IBM-1124 CP1124" + echo "IBM-1129 CP1129" + echo "IBM-1252 CP1252" + echo "IBM-eucCN GB2312" + echo "IBM-eucJP EUC-JP" + echo "IBM-eucKR EUC-KR" + echo "IBM-eucTW EUC-TW" + echo "big5 BIG5" + echo "GBK GBK" + echo "TIS-620 TIS-620" + echo "UTF-8 UTF-8" + ;; + hpux*) + echo "iso88591 ISO-8859-1" + echo "iso88592 ISO-8859-2" + echo "iso88595 ISO-8859-5" + echo "iso88596 ISO-8859-6" + echo "iso88597 ISO-8859-7" + echo "iso88598 ISO-8859-8" + echo "iso88599 ISO-8859-9" + echo "iso885915 ISO-8859-15" + echo "roman8 HP-ROMAN8" + echo "arabic8 HP-ARABIC8" + echo "greek8 HP-GREEK8" + echo "hebrew8 HP-HEBREW8" + echo "turkish8 HP-TURKISH8" + echo "kana8 HP-KANA8" + echo "tis620 TIS-620" + echo "big5 BIG5" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + echo "hp15CN GB2312" + #echo "ccdc ?" # what is this? + echo "SJIS SHIFT_JIS" + echo "utf8 UTF-8" + ;; + irix*) + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-9 ISO-8859-9" + echo "eucCN GB2312" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + ;; + osf*) + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-8 ISO-8859-8" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-15 ISO-8859-15" + echo "cp850 CP850" + echo "big5 BIG5" + echo "dechanyu DEC-HANYU" + echo "dechanzi GB2312" + echo "deckanji DEC-KANJI" + echo "deckorean EUC-KR" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + echo "GBK GBK" + echo "KSC5601 CP949" + echo "sdeckanji EUC-JP" + echo "SJIS SHIFT_JIS" + echo "TACTIS TIS-620" + echo "UTF-8 UTF-8" + ;; + solaris*) + echo "646 ASCII" + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-3 ISO-8859-3" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-6 ISO-8859-6" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-8 ISO-8859-8" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-15 ISO-8859-15" + echo "koi8-r KOI8-R" + echo "ansi-1251 CP1251" + echo "BIG5 BIG5" + echo "Big5-HKSCS BIG5-HKSCS" + echo "gb2312 GB2312" + echo "GBK GBK" + echo "GB18030 GB18030" + echo "cns11643 EUC-TW" + echo "5601 EUC-KR" + echo "ko_KR.johap92 JOHAB" + echo "eucJP EUC-JP" + echo "PCK SHIFT_JIS" + echo "TIS620.2533 TIS-620" + #echo "sun_eu_greek ?" # what is this? + echo "UTF-8 UTF-8" + ;; + freebsd* | os2*) + # FreeBSD 4.2 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + # Likewise for OS/2. OS/2 has XFree86 just like FreeBSD. Just + # reuse FreeBSD's locale data for OS/2. + echo "C ASCII" + echo "US-ASCII ASCII" + for l in la_LN lt_LN; do + echo "$l.ASCII ASCII" + done + for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ + fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT la_LN \ + lt_LN nl_BE nl_NL no_NO pt_PT sv_SE; do + echo "$l.ISO_8859-1 ISO-8859-1" + echo "$l.DIS_8859-15 ISO-8859-15" + done + for l in cs_CZ hr_HR hu_HU la_LN lt_LN pl_PL sl_SI; do + echo "$l.ISO_8859-2 ISO-8859-2" + done + for l in la_LN lt_LT; do + echo "$l.ISO_8859-4 ISO-8859-4" + done + for l in ru_RU ru_SU; do + echo "$l.KOI8-R KOI8-R" + echo "$l.ISO_8859-5 ISO-8859-5" + echo "$l.CP866 CP866" + done + echo "uk_UA.KOI8-U KOI8-U" + echo "zh_TW.BIG5 BIG5" + echo "zh_TW.Big5 BIG5" + echo "zh_CN.EUC GB2312" + echo "ja_JP.EUC EUC-JP" + echo "ja_JP.SJIS SHIFT_JIS" + echo "ja_JP.Shift_JIS SHIFT_JIS" + echo "ko_KR.EUC EUC-KR" + ;; + netbsd*) + echo "646 ASCII" + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-13 ISO-8859-13" + echo "ISO8859-15 ISO-8859-15" + echo "eucCN GB2312" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "eucTW EUC-TW" + echo "BIG5 BIG5" + echo "SJIS SHIFT_JIS" + ;; + openbsd*) + echo "646 ASCII" + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-13 ISO-8859-13" + echo "ISO8859-15 ISO-8859-15" + ;; + darwin[56]*) + # Darwin 6.8 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + echo "C ASCII" + for l in en_AU en_CA en_GB en_US la_LN; do + echo "$l.US-ASCII ASCII" + done + for l in da_DK de_AT de_CH de_DE en_AU en_CA en_GB en_US es_ES \ + fi_FI fr_BE fr_CA fr_CH fr_FR is_IS it_CH it_IT nl_BE \ + nl_NL no_NO pt_PT sv_SE; do + echo "$l ISO-8859-1" + echo "$l.ISO8859-1 ISO-8859-1" + echo "$l.ISO8859-15 ISO-8859-15" + done + for l in la_LN; do + echo "$l.ISO8859-1 ISO-8859-1" + echo "$l.ISO8859-15 ISO-8859-15" + done + for l in cs_CZ hr_HR hu_HU la_LN pl_PL sl_SI; do + echo "$l.ISO8859-2 ISO-8859-2" + done + for l in la_LN lt_LT; do + echo "$l.ISO8859-4 ISO-8859-4" + done + for l in ru_RU; do + echo "$l.KOI8-R KOI8-R" + echo "$l.ISO8859-5 ISO-8859-5" + echo "$l.CP866 CP866" + done + for l in bg_BG; do + echo "$l.CP1251 CP1251" + done + echo "uk_UA.KOI8-U KOI8-U" + echo "zh_TW.BIG5 BIG5" + echo "zh_TW.Big5 BIG5" + echo "zh_CN.EUC GB2312" + echo "ja_JP.EUC EUC-JP" + echo "ja_JP.SJIS SHIFT_JIS" + echo "ko_KR.EUC EUC-KR" + ;; + darwin*) + # Darwin 7.5 has nl_langinfo(CODESET), but sometimes its value is + # useless: + # - It returns the empty string when LANG is set to a locale of the + # form ll_CC, although ll_CC/LC_CTYPE is a symlink to an UTF-8 + # LC_CTYPE file. + # - The environment variables LANG, LC_CTYPE, LC_ALL are not set by + # the system; nl_langinfo(CODESET) returns "US-ASCII" in this case. + # - The documentation says: + # "... all code that calls BSD system routines should ensure + # that the const *char parameters of these routines are in UTF-8 + # encoding. All BSD system functions expect their string + # parameters to be in UTF-8 encoding and nothing else." + # It also says + # "An additional caveat is that string parameters for files, + # paths, and other file-system entities must be in canonical + # UTF-8. In a canonical UTF-8 Unicode string, all decomposable + # characters are decomposed ..." + # but this is not true: You can pass non-decomposed UTF-8 strings + # to file system functions, and it is the OS which will convert + # them to decomposed UTF-8 before accessing the file system. + # - The Apple Terminal application displays UTF-8 by default. + # - However, other applications are free to use different encodings: + # - xterm uses ISO-8859-1 by default. + # - TextEdit uses MacRoman by default. + # We prefer UTF-8 over decomposed UTF-8-MAC because one should + # minimize the use of decomposed Unicode. Unfortunately, through the + # Darwin file system, decomposed UTF-8 strings are leaked into user + # space nevertheless. + # Then there are also the locales with encodings other than US-ASCII + # and UTF-8. These locales can be occasionally useful to users (e.g. + # when grepping through ISO-8859-1 encoded text files), when all their + # file names are in US-ASCII. + echo "ISO8859-1 ISO-8859-1" + echo "ISO8859-2 ISO-8859-2" + echo "ISO8859-4 ISO-8859-4" + echo "ISO8859-5 ISO-8859-5" + echo "ISO8859-7 ISO-8859-7" + echo "ISO8859-9 ISO-8859-9" + echo "ISO8859-13 ISO-8859-13" + echo "ISO8859-15 ISO-8859-15" + echo "KOI8-R KOI8-R" + echo "KOI8-U KOI8-U" + echo "CP866 CP866" + echo "CP949 CP949" + echo "CP1131 CP1131" + echo "CP1251 CP1251" + echo "eucCN GB2312" + echo "GB2312 GB2312" + echo "eucJP EUC-JP" + echo "eucKR EUC-KR" + echo "Big5 BIG5" + echo "Big5HKSCS BIG5-HKSCS" + echo "GBK GBK" + echo "GB18030 GB18030" + echo "SJIS SHIFT_JIS" + echo "ARMSCII-8 ARMSCII-8" + echo "PT154 PT154" + #echo "ISCII-DEV ?" + echo "* UTF-8" + ;; + beos* | haiku*) + # BeOS and Haiku have a single locale, and it has UTF-8 encoding. + echo "* UTF-8" + ;; + msdosdjgpp*) + # DJGPP 2.03 doesn't have nl_langinfo(CODESET); therefore + # localcharset.c falls back to using the full locale name + # from the environment variables. + echo "#" + echo "# The encodings given here may not all be correct." + echo "# If you find that the encoding given for your language and" + echo "# country is not the one your DOS machine actually uses, just" + echo "# correct it in this file, and send a mail to" + echo "# Juan Manuel Guerrero <juan.guerrero@gmx.de>" + echo "# and Bruno Haible <bruno@clisp.org>." + echo "#" + echo "C ASCII" + # ISO-8859-1 languages + echo "ca CP850" + echo "ca_ES CP850" + echo "da CP865" # not CP850 ?? + echo "da_DK CP865" # not CP850 ?? + echo "de CP850" + echo "de_AT CP850" + echo "de_CH CP850" + echo "de_DE CP850" + echo "en CP850" + echo "en_AU CP850" # not CP437 ?? + echo "en_CA CP850" + echo "en_GB CP850" + echo "en_NZ CP437" + echo "en_US CP437" + echo "en_ZA CP850" # not CP437 ?? + echo "es CP850" + echo "es_AR CP850" + echo "es_BO CP850" + echo "es_CL CP850" + echo "es_CO CP850" + echo "es_CR CP850" + echo "es_CU CP850" + echo "es_DO CP850" + echo "es_EC CP850" + echo "es_ES CP850" + echo "es_GT CP850" + echo "es_HN CP850" + echo "es_MX CP850" + echo "es_NI CP850" + echo "es_PA CP850" + echo "es_PY CP850" + echo "es_PE CP850" + echo "es_SV CP850" + echo "es_UY CP850" + echo "es_VE CP850" + echo "et CP850" + echo "et_EE CP850" + echo "eu CP850" + echo "eu_ES CP850" + echo "fi CP850" + echo "fi_FI CP850" + echo "fr CP850" + echo "fr_BE CP850" + echo "fr_CA CP850" + echo "fr_CH CP850" + echo "fr_FR CP850" + echo "ga CP850" + echo "ga_IE CP850" + echo "gd CP850" + echo "gd_GB CP850" + echo "gl CP850" + echo "gl_ES CP850" + echo "id CP850" # not CP437 ?? + echo "id_ID CP850" # not CP437 ?? + echo "is CP861" # not CP850 ?? + echo "is_IS CP861" # not CP850 ?? + echo "it CP850" + echo "it_CH CP850" + echo "it_IT CP850" + echo "lt CP775" + echo "lt_LT CP775" + echo "lv CP775" + echo "lv_LV CP775" + echo "nb CP865" # not CP850 ?? + echo "nb_NO CP865" # not CP850 ?? + echo "nl CP850" + echo "nl_BE CP850" + echo "nl_NL CP850" + echo "nn CP865" # not CP850 ?? + echo "nn_NO CP865" # not CP850 ?? + echo "no CP865" # not CP850 ?? + echo "no_NO CP865" # not CP850 ?? + echo "pt CP850" + echo "pt_BR CP850" + echo "pt_PT CP850" + echo "sv CP850" + echo "sv_SE CP850" + # ISO-8859-2 languages + echo "cs CP852" + echo "cs_CZ CP852" + echo "hr CP852" + echo "hr_HR CP852" + echo "hu CP852" + echo "hu_HU CP852" + echo "pl CP852" + echo "pl_PL CP852" + echo "ro CP852" + echo "ro_RO CP852" + echo "sk CP852" + echo "sk_SK CP852" + echo "sl CP852" + echo "sl_SI CP852" + echo "sq CP852" + echo "sq_AL CP852" + echo "sr CP852" # CP852 or CP866 or CP855 ?? + echo "sr_CS CP852" # CP852 or CP866 or CP855 ?? + echo "sr_YU CP852" # CP852 or CP866 or CP855 ?? + # ISO-8859-3 languages + echo "mt CP850" + echo "mt_MT CP850" + # ISO-8859-5 languages + echo "be CP866" + echo "be_BE CP866" + echo "bg CP866" # not CP855 ?? + echo "bg_BG CP866" # not CP855 ?? + echo "mk CP866" # not CP855 ?? + echo "mk_MK CP866" # not CP855 ?? + echo "ru CP866" + echo "ru_RU CP866" + echo "uk CP1125" + echo "uk_UA CP1125" + # ISO-8859-6 languages + echo "ar CP864" + echo "ar_AE CP864" + echo "ar_DZ CP864" + echo "ar_EG CP864" + echo "ar_IQ CP864" + echo "ar_IR CP864" + echo "ar_JO CP864" + echo "ar_KW CP864" + echo "ar_MA CP864" + echo "ar_OM CP864" + echo "ar_QA CP864" + echo "ar_SA CP864" + echo "ar_SY CP864" + # ISO-8859-7 languages + echo "el CP869" + echo "el_GR CP869" + # ISO-8859-8 languages + echo "he CP862" + echo "he_IL CP862" + # ISO-8859-9 languages + echo "tr CP857" + echo "tr_TR CP857" + # Japanese + echo "ja CP932" + echo "ja_JP CP932" + # Chinese + echo "zh_CN GBK" + echo "zh_TW CP950" # not CP938 ?? + # Korean + echo "kr CP949" # not CP934 ?? + echo "kr_KR CP949" # not CP934 ?? + # Thai + echo "th CP874" + echo "th_TH CP874" + # Other + echo "eo CP850" + echo "eo_EO CP850" + ;; +esac diff --git a/src/libs/libgroff/cset.cpp b/src/libs/libgroff/cset.cpp new file mode 100644 index 0000000..6702237 --- /dev/null +++ b/src/libs/libgroff/cset.cpp @@ -0,0 +1,104 @@ +// -*- C++ -*- +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <ctype.h> + +#include "lib.h" +#include "cset.h" + +cset csalpha(CSET_BUILTIN); +cset csupper(CSET_BUILTIN); +cset cslower(CSET_BUILTIN); +cset csdigit(CSET_BUILTIN); +cset csxdigit(CSET_BUILTIN); +cset csspace(CSET_BUILTIN); +cset cspunct(CSET_BUILTIN); +cset csalnum(CSET_BUILTIN); +cset csprint(CSET_BUILTIN); +cset csgraph(CSET_BUILTIN); +cset cscntrl(CSET_BUILTIN); + +#ifdef isascii +#define ISASCII(c) isascii(c) +#else +#define ISASCII(c) (1) +#endif + +void cset::clear() +{ + char *p = v; + for (int i = 0; i <= UCHAR_MAX; i++) + p[i] = 0; +} + +cset::cset() +{ + clear(); +} + +cset::cset(const char *s) +{ + clear(); + while (*s) + v[(unsigned char)*s++] = 1; +} + +cset::cset(const unsigned char *s) +{ + clear(); + while (*s) + v[*s++] = 1; +} + +cset::cset(cset_builtin) +{ + // these are initialised by cset_init::cset_init() +} + +cset &cset::operator|=(const cset &cs) +{ + for (int i = 0; i <= UCHAR_MAX; i++) + if (cs.v[i]) + v[i] = 1; + return *this; +} + + +int cset_init::initialised = 0; + +cset_init::cset_init() +{ + if (initialised) + return; + initialised = 1; + for (int i = 0; i <= UCHAR_MAX; i++) { + csalpha.v[i] = ISASCII(i) && isalpha(i); + csupper.v[i] = ISASCII(i) && isupper(i); + cslower.v[i] = ISASCII(i) && islower(i); + csdigit.v[i] = ISASCII(i) && isdigit(i); + csxdigit.v[i] = ISASCII(i) && isxdigit(i); + csspace.v[i] = ISASCII(i) && isspace(i); + cspunct.v[i] = ISASCII(i) && ispunct(i); + csalnum.v[i] = ISASCII(i) && isalnum(i); + csprint.v[i] = ISASCII(i) && isprint(i); + csgraph.v[i] = ISASCII(i) && isgraph(i); + cscntrl.v[i] = ISASCII(i) && iscntrl(i); + } +} diff --git a/src/libs/libgroff/curtime.cpp b/src/libs/libgroff/curtime.cpp new file mode 100644 index 0000000..34dbc5c --- /dev/null +++ b/src/libs/libgroff/curtime.cpp @@ -0,0 +1,55 @@ +/* Copyright (C) 2015-2020 Free Software Foundation, Inc. + +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 2 of the License, or +(at your option) any later version. + +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 +for more details. + +The GNU General Public License version 2 (GPL2) is available in the +internet at <http://www.gnu.org/licenses/gpl-2.0.txt>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "errarg.h" +#include "error.h" + +#ifdef LONG_FOR_TIME_T +long +#else +time_t +#endif +current_time() +{ + char *source_date_epoch = getenv("SOURCE_DATE_EPOCH"); + + if (source_date_epoch) { + errno = 0; + char *endptr; + long epoch = strtol(source_date_epoch, &endptr, 10); + + if ((errno == ERANGE && (epoch == LONG_MAX || epoch == LONG_MIN)) || + (errno != 0 && epoch == 0)) + fatal("$SOURCE_DATE_EPOCH: strtol: %1", strerror(errno)); + if (endptr == source_date_epoch) + fatal("$SOURCE_DATE_EPOCH: no digits found: '%1'", endptr); + if (*endptr != '\0') + fatal("$SOURCE_DATE_EPOCH: trailing garbage: '%1'", endptr); + return epoch; + } else + return time(0); +} diff --git a/src/libs/libgroff/device.cpp b/src/libs/libgroff/device.cpp new file mode 100644 index 0000000..6caeb8e --- /dev/null +++ b/src/libs/libgroff/device.cpp @@ -0,0 +1,39 @@ +// -*- C++ -*- +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include "device.h" +#include "defs.h" + +const char *device = DEVICE; + +struct device_init { + device_init(); +} _device_init; + +device_init::device_init() +{ + char *tem = getenv("GROFF_TYPESETTER"); + if (tem && tem[0]) + device = tem; +} diff --git a/src/libs/libgroff/errarg.cpp b/src/libs/libgroff/errarg.cpp new file mode 100644 index 0000000..99fc0fa --- /dev/null +++ b/src/libs/libgroff/errarg.cpp @@ -0,0 +1,136 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <assert.h> +#include <stdio.h> + +#include "errarg.h" + +errarg::errarg(const char *p) : type(STRING) +{ + s = p ? p : "(null)"; +} + +errarg::errarg() : type(EMPTY) +{ +} + +errarg::errarg(int nn) : type(INTEGER) +{ + n = nn; +} + +errarg::errarg(unsigned int uu) : type(UNSIGNED_INTEGER) +{ + u = uu; +} + +errarg::errarg(char cc) : type(CHAR) +{ + c = cc; +} + +errarg::errarg(unsigned char cc) : type(CHAR) +{ + c = cc; +} + +errarg::errarg(double dd) : type(DOUBLE) +{ + d = dd; +} + +int errarg::empty() const +{ + return type == EMPTY; +} + +extern "C" { + const char *i_to_a(int); + const char *ui_to_a(unsigned int); +} + +void errarg::print() const +{ + switch (type) { + case INTEGER: + fputs(i_to_a(n), stderr); + break; + case UNSIGNED_INTEGER: + fputs(ui_to_a(u), stderr); + break; + case CHAR: + putc(c, stderr); + break; + case STRING: + fputs(s, stderr); + break; + case DOUBLE: + fprintf(stderr, "%g", d); + break; + case EMPTY: + break; + } +} + +errarg empty_errarg; + +void errprint(const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + assert(format != 0); + char c; + while ((c = *format++) != '\0') { + if (c == '%') { + c = *format++; + switch(c) { + case '%': + fputc('%', stderr); + break; + case '1': + assert(!arg1.empty()); + arg1.print(); + break; + case '2': + assert(!arg2.empty()); + arg2.print(); + break; + case '3': + assert(!arg3.empty()); + arg3.print(); + break; + default: + assert(0 == "unsupported argument conversion (not in [%123])"); + } + } + else + putc(c, stderr); + } +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/error.cpp b/src/libs/libgroff/error.cpp new file mode 100644 index 0000000..b1a4e61 --- /dev/null +++ b/src/libs/libgroff/error.cpp @@ -0,0 +1,185 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "errarg.h" +#include "error.h" + +extern void fatal_error_exit(); + +enum error_type { DEBUG, WARNING, ERROR, FATAL }; + +static void do_error_with_file_and_line(const char *filename, + const char *source_filename, + int lineno, + error_type type, + const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + bool need_space = false; + if (program_name != 0 /* nullptr */) { + fputs(program_name, stderr); + fputc(':', stderr); + need_space = true; + } + if (filename != 0 /* nullptr */) { + if (strcmp(filename, "-") == 0) + filename = "<standard input>"; + fputs(filename, stderr); + if (source_filename != 0 /* nullptr */) { + fputs(":(", stderr); + fputs(source_filename, stderr); + fputc(')', stderr); + } + if (lineno > 0) { + fputc(':', stderr); + errprint("%1", lineno); + } + fputc(':', stderr); + need_space = true; + } + if (need_space) + fputc(' ', stderr); + switch (type) { + case FATAL: + fputs("fatal error", stderr); + break; + case ERROR: + fputs("error", stderr); + break; + case WARNING: + fputs("warning", stderr); + break; + case DEBUG: + fputs("debug", stderr); + break; + } + fputs(": ", stderr); + errprint(format, arg1, arg2, arg3); + fputc('\n', stderr); + fflush(stderr); + if (type == FATAL) + fatal_error_exit(); +} + +static void do_error(error_type type, + const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + do_error_with_file_and_line(current_filename, current_source_filename, + current_lineno, type, format, arg1, arg2, + arg3); +} + +void debug(const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + do_error(DEBUG, format, arg1, arg2, arg3); +} + +void error(const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + do_error(ERROR, format, arg1, arg2, arg3); +} + +void warning(const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + do_error(WARNING, format, arg1, arg2, arg3); +} + +void fatal(const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + do_error(FATAL, format, arg1, arg2, arg3); +} + +// Use the functions below when it's more costly to save and restore the +// globals current_filename, current_source_filename, and current_lineno +// than to specify additional arguments. For instance, a function that +// would need to temporarily change their values and has multiple return +// paths might prefer these to the simpler variants above. + +void debug_with_file_and_line(const char *filename, + int lineno, + const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + do_error_with_file_and_line(filename, 0 /* nullptr */, lineno, + DEBUG, format, arg1, arg2, arg3); +} + +void error_with_file_and_line(const char *filename, + int lineno, + const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + do_error_with_file_and_line(filename, 0 /* nullptr */, lineno, + ERROR, format, arg1, arg2, arg3); +} + +void warning_with_file_and_line(const char *filename, + int lineno, + const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + do_error_with_file_and_line(filename, 0 /* nullptr */, lineno, + WARNING, format, arg1, arg2, arg3); +} + +void fatal_with_file_and_line(const char *filename, + int lineno, + const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + do_error_with_file_and_line(filename, 0 /* nullptr */, lineno, + FATAL, format, arg1, arg2, arg3); +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/fatal.cpp b/src/libs/libgroff/fatal.cpp new file mode 100644 index 0000000..1cbf3ef --- /dev/null +++ b/src/libs/libgroff/fatal.cpp @@ -0,0 +1,30 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> + +#define FATAL_ERROR_EXIT_CODE 3 + +void fatal_error_exit() +{ + exit(FATAL_ERROR_EXIT_CODE); +} diff --git a/src/libs/libgroff/filename.cpp b/src/libs/libgroff/filename.cpp new file mode 100644 index 0000000..ded9738 --- /dev/null +++ b/src/libs/libgroff/filename.cpp @@ -0,0 +1,31 @@ +/* Copyright (C) 2014-2022 Free Software Foundation, Inc. + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +// This global stores the name of the input file being processed by +// troff, an output driver, or other program. +const char *current_filename = 0 /* nullptr */; + +// This global stores the name of the troff input file corresponding to +// the part of a device-independent troff output being processed; it is +// used only by output drivers. +const char *current_source_filename = 0 /* nullptr */; + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/fmod.c b/src/libs/libgroff/fmod.c new file mode 100644 index 0000000..45278f9 --- /dev/null +++ b/src/libs/libgroff/fmod.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <math.h> + +double fmod(x, y) + double x, y; +{ + double quot = x/y; + return x - (quot < 0.0 ? ceil(quot) : floor(quot)) * y; +} diff --git a/src/libs/libgroff/font.cpp b/src/libs/libgroff/font.cpp new file mode 100644 index 0000000..c1af12c --- /dev/null +++ b/src/libs/libgroff/font.cpp @@ -0,0 +1,1321 @@ +/* Copyright (C) 1989-2021 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#include <assert.h> +#include <ctype.h> +#include <math.h> +#include <stdlib.h> +#include <wchar.h> + +#include "errarg.h" +#include "error.h" +#include "cset.h" +#include "font.h" +#include "unicode.h" +#include "paper.h" + +const char *const WS = " \t\n\r"; + +struct font_char_metric { + char type; + int code; + int width; + int height; + int depth; + int pre_math_space; + int italic_correction; + int subscript_correction; + char *special_device_coding; +}; + +struct font_kern_list { + glyph *glyph1; + glyph *glyph2; + int amount; + font_kern_list *next; + + font_kern_list(glyph *, glyph *, int, font_kern_list * = 0); +}; + +struct font_widths_cache { + font_widths_cache *next; + int point_size; + int *width; + + font_widths_cache(int, int, font_widths_cache * = 0); + ~font_widths_cache(); +}; + +/* text_file */ + +struct text_file { + FILE *fp; + char *path; + int lineno; + int linebufsize; + bool recognize_comments; + bool silent; + char *buf; + text_file(FILE *fp, char *p); + ~text_file(); + bool next_line(); + void error(const char *format, + const errarg &arg1 = empty_errarg, + const errarg &arg2 = empty_errarg, + const errarg &arg3 = empty_errarg); + void fatal(const char *format, + const errarg &arg1 = empty_errarg, + const errarg &arg2 = empty_errarg, + const errarg &arg3 = empty_errarg); +}; + +text_file::text_file(FILE *p, char *s) : fp(p), path(s), lineno(0), + linebufsize(128), recognize_comments(true), silent(false), buf(0) +{ +} + +text_file::~text_file() +{ + delete[] buf; + free(path); + if (fp) + fclose(fp); +} + +bool text_file::next_line() +{ + if (fp == 0) + return false; + if (buf == 0) + buf = new char[linebufsize]; + for (;;) { + lineno++; + int length = 0; + for (;;) { + int c = getc(fp); + if (c == EOF) + break; + if (is_invalid_input_char(c)) + error("invalid input character code %1", int(c)); + else { + if (length + 1 >= linebufsize) { + char *old_buf = buf; + buf = new char[linebufsize * 2]; + memcpy(buf, old_buf, linebufsize); + delete[] old_buf; + linebufsize *= 2; + } + buf[length++] = c; + if (c == '\n') + break; + } + } + if (length == 0) + break; + buf[length] = '\0'; + char *ptr = buf; + while (csspace(*ptr)) + ptr++; + if (*ptr != 0 && (!recognize_comments || *ptr != '#')) + return true; + } + return false; +} + +void text_file::error(const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + if (!silent) + error_with_file_and_line(path, lineno, format, arg1, arg2, arg3); +} + +void text_file::fatal(const char *format, + const errarg &arg1, + const errarg &arg2, + const errarg &arg3) +{ + if (!silent) + fatal_with_file_and_line(path, lineno, format, arg1, arg2, arg3); +} + +int glyph_to_unicode(glyph *g) +{ + const char *nm = glyph_to_name(g); + if (nm != 0) { + // ASCII character? + if (nm[0] == 'c' && nm[1] == 'h' && nm[2] == 'a' && nm[3] == 'r' + && (nm[4] >= '0' && nm[4] <= '9')) { + int n = (nm[4] - '0'); + if (nm[5] == '\0') + return n; + if (n > 0 && (nm[5] >= '0' && nm[5] <= '9')) { + n = 10*n + (nm[5] - '0'); + if (nm[6] == '\0') + return n; + if (nm[6] >= '0' && nm[6] <= '9') { + n = 10*n + (nm[6] - '0'); + if (nm[7] == '\0' && n < 128) + return n; + } + } + } + // Unicode character? + if (check_unicode_name(nm)) { + char *ignore; + return (int)strtol(nm + 1, &ignore, 16); + } + // If 'nm' is a single letter 'x', the glyph name is '\x'. + char buf[] = { '\\', '\0', '\0' }; + if (nm[1] == '\0') { + buf[1] = nm[0]; + nm = buf; + } + // groff glyphs that map to Unicode? + const char *unicode = glyph_name_to_unicode(nm); + if (unicode != 0 && strchr(unicode, '_') == 0) { + char *ignore; + return (int)strtol(unicode, &ignore, 16); + } + } + return -1; +} + +/* font functions */ + +font::font(const char *s) : ligatures(0), kern_hash_table(0), + space_width(0), special(false), internalname(0), slant(0.0), zoom(0), + ch_index(0), nindices(0), ch(0), ch_used(0), ch_size(0), + widths_cache(0) +{ + name = new char[strlen(s) + 1]; + strcpy(name, s); +} + +font::~font() +{ + for (int i = 0; i < ch_used; i++) + if (ch[i].special_device_coding) + delete[] ch[i].special_device_coding; + delete[] ch; + delete[] ch_index; + if (kern_hash_table) { + for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++) { + font_kern_list *kerns = kern_hash_table[i]; + while (kerns) { + font_kern_list *tem = kerns; + kerns = kerns->next; + delete tem; + } + } + delete[] kern_hash_table; + } + delete[] name; + delete[] internalname; + while (widths_cache) { + font_widths_cache *tem = widths_cache; + widths_cache = widths_cache->next; + delete tem; + } +} + +static int scale_round(int n, int x, int y) +{ + assert(x >= 0 && y > 0); + int y2 = y/2; + if (x == 0) + return 0; + if (n >= 0) { + if (n <= (INT_MAX - y2) / x) + return (n * x + y2) / y; + return int(n * double(x) / double(y) + .5); + } + else { + if (-(unsigned)n <= (-(unsigned)INT_MIN - y2) / x) + return (n * x - y2) / y; + return int(n * double(x) / double(y) - .5); + } +} + +static int scale_round(int n, int x, int y, int z) +{ + assert(x >= 0 && y > 0 && z > 0); + if (x == 0) + return 0; + if (n >= 0) + return int((n * double(x) / double(y)) * (double(z) / 1000.0) + .5); + else + return int((n * double(x) / double(y)) * (double(z) / 1000.0) - .5); +} + +inline int font::scale(int w, int sz) +{ + if (zoom) + return scale_round(w, sz, unitwidth, zoom); + else + return sz == unitwidth ? w : scale_round(w, sz, unitwidth); +} + +// Returns whether scaling by arguments was successful. Used for paper +// size conversions. +bool font::unit_scale(double *value, char unit) +{ + // Paper sizes are handled in inches. + double divisor = 0; + switch (unit) { + case 'i': + divisor = 1; + break; + case 'p': + divisor = 72; + break; + case 'P': + divisor = 6; + break; + case 'c': + divisor = 2.54; + break; + default: + assert(0 == "unit not in [cipP]"); + break; + } + if (divisor) { + *value /= divisor; + return true; + } + return false; +} + +int font::get_skew(glyph *g, int point_size, int sl) +{ + int h = get_height(g, point_size); + return int(h * tan((slant + sl) * PI / 180.0) + .5); +} + +bool font::contains(glyph *g) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + // Explicitly enumerated glyph? + if (idx < nindices && ch_index[idx] >= 0) + return true; + if (is_unicode) { + // Unicode font + // ASCII or Unicode character, or groff glyph name that maps to Unicode? + if (glyph_to_unicode(g) >= 0) + return true; + // Numbered character? + if (glyph_to_number(g) >= 0) + return true; + } + return false; +} + +bool font::is_special() +{ + return special; +} + +font_widths_cache::font_widths_cache(int ps, int ch_size, + font_widths_cache *p) +: next(p), point_size(ps) +{ + width = new int[ch_size]; + for (int i = 0; i < ch_size; i++) + width[i] = -1; +} + +font_widths_cache::~font_widths_cache() +{ + delete[] width; +} + +int font::get_width(glyph *g, int point_size) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + int real_size; + if (zoom == 0) // 0 means "don't zoom" + real_size = point_size; + else + { + if (point_size <= (INT_MAX - 500) / zoom) + real_size = (point_size * zoom + 500) / 1000; + else + real_size = int(point_size * double(zoom) / 1000.0 + .5); + } + if (idx < nindices && ch_index[idx] >= 0) { + // Explicitly enumerated glyph + int i = ch_index[idx]; + if (real_size == unitwidth || font::use_unscaled_charwidths) + return ch[i].width; + + if (!widths_cache) + widths_cache = new font_widths_cache(real_size, ch_size); + else if (widths_cache->point_size != real_size) { + font_widths_cache **p; + for (p = &widths_cache; *p; p = &(*p)->next) + if ((*p)->point_size == real_size) + break; + if (*p) { + font_widths_cache *tem = *p; + *p = (*p)->next; + tem->next = widths_cache; + widths_cache = tem; + } + else + widths_cache = new font_widths_cache(real_size, ch_size, + widths_cache); + } + int &w = widths_cache->width[i]; + if (w < 0) + w = scale(ch[i].width, point_size); + return w; + } + if (is_unicode) { + // Unicode font + int width = 24; // XXX: Add a request to override this. + int w = wcwidth(get_code(g)); + if (w > 1) + width *= w; + if (real_size == unitwidth || font::use_unscaled_charwidths) + return width; + else + return scale(width, point_size); + } + assert(0 == "glyph is not indexed and device lacks Unicode support"); + abort(); // -Wreturn-type +} + +int font::get_height(glyph *g, int point_size) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + if (idx < nindices && ch_index[idx] >= 0) { + // Explicitly enumerated glyph + return scale(ch[ch_index[idx]].height, point_size); + } + if (is_unicode) { + // Unicode font + return 0; + } + assert(0 == "glyph is not indexed and device lacks Unicode support"); + abort(); // -Wreturn-type +} + +int font::get_depth(glyph *g, int point_size) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + if (idx < nindices && ch_index[idx] >= 0) { + // Explicitly enumerated glyph + return scale(ch[ch_index[idx]].depth, point_size); + } + if (is_unicode) { + // Unicode font + return 0; + } + assert(0 == "glyph is not indexed and device lacks Unicode support"); + abort(); // -Wreturn-type +} + +int font::get_italic_correction(glyph *g, int point_size) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + if (idx < nindices && ch_index[idx] >= 0) { + // Explicitly enumerated glyph + return scale(ch[ch_index[idx]].italic_correction, point_size); + } + if (is_unicode) { + // Unicode font + return 0; + } + assert(0 == "glyph is not indexed and device lacks Unicode support"); + abort(); // -Wreturn-type +} + +int font::get_left_italic_correction(glyph *g, int point_size) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + if (idx < nindices && ch_index[idx] >= 0) { + // Explicitly enumerated glyph + return scale(ch[ch_index[idx]].pre_math_space, point_size); + } + if (is_unicode) { + // Unicode font + return 0; + } + assert(0 == "glyph is not indexed and device lacks Unicode support"); + abort(); // -Wreturn-type +} + +int font::get_subscript_correction(glyph *g, int point_size) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + if (idx < nindices && ch_index[idx] >= 0) { + // Explicitly enumerated glyph + return scale(ch[ch_index[idx]].subscript_correction, point_size); + } + if (is_unicode) { + // Unicode font + return 0; + } + assert(0 == "glyph is not indexed and device lacks Unicode support"); + abort(); // -Wreturn-type +} + +void font::set_zoom(int factor) +{ + assert(factor >= 0); + if (factor == 1000) + zoom = 0; + else + zoom = factor; +} + +int font::get_zoom() +{ + return zoom; +} + +int font::get_space_width(int point_size) +{ + return scale(space_width, point_size); +} + +font_kern_list::font_kern_list(glyph *g1, glyph *g2, int n, font_kern_list *p) +: glyph1(g1), glyph2(g2), amount(n), next(p) +{ +} + +inline int font::hash_kern(glyph *g1, glyph *g2) +{ + int n = ((glyph_to_index(g1) << 10) + glyph_to_index(g2)) + % KERN_HASH_TABLE_SIZE; + return n < 0 ? -n : n; +} + +void font::add_kern(glyph *g1, glyph *g2, int amount) +{ + if (!kern_hash_table) { + kern_hash_table = new font_kern_list *[int(KERN_HASH_TABLE_SIZE)]; + for (int i = 0; i < KERN_HASH_TABLE_SIZE; i++) + kern_hash_table[i] = 0; + } + font_kern_list **p = kern_hash_table + hash_kern(g1, g2); + *p = new font_kern_list(g1, g2, amount, *p); +} + +int font::get_kern(glyph *g1, glyph *g2, int point_size) +{ + if (kern_hash_table) { + for (font_kern_list *p = kern_hash_table[hash_kern(g1, g2)]; p; + p = p->next) + if (g1 == p->glyph1 && g2 == p->glyph2) + return scale(p->amount, point_size); + } + return 0; +} + +bool font::has_ligature(int mask) +{ + return (bool) (mask & ligatures); +} + +int font::get_character_type(glyph *g) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + if (idx < nindices && ch_index[idx] >= 0) { + // Explicitly enumerated glyph + return ch[ch_index[idx]].type; + } + if (is_unicode) { + // Unicode font + return 0; + } + assert(0 == "glyph is not indexed and device lacks Unicode support"); + abort(); // -Wreturn-type +} + +int font::get_code(glyph *g) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + if (idx < nindices && ch_index[idx] >= 0) { + // Explicitly enumerated glyph + return ch[ch_index[idx]].code; + } + if (is_unicode) { + // Unicode font + // ASCII or Unicode character, or groff glyph name that maps to Unicode? + int uni = glyph_to_unicode(g); + if (uni >= 0) + return uni; + // Numbered character? + int n = glyph_to_number(g); + if (n >= 0) + return n; + } + // The caller must check 'contains(g)' before calling get_code(g). + assert(0 == "glyph is not indexed and device lacks Unicode support"); + abort(); // -Wreturn-type +} + +const char *font::get_name() +{ + return name; +} + +const char *font::get_internal_name() +{ + return internalname; +} + +const char *font::get_special_device_encoding(glyph *g) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + if (idx < nindices && ch_index[idx] >= 0) { + // Explicitly enumerated glyph + return ch[ch_index[idx]].special_device_coding; + } + if (is_unicode) { + // Unicode font + return 0; + } + assert(0 == "glyph is not indexed and device lacks Unicode support"); + abort(); // -Wreturn-type +} + +const char *font::get_image_generator() +{ + return image_generator; +} + +void font::alloc_ch_index(int idx) +{ + if (nindices == 0) { + nindices = 128; + if (idx >= nindices) + nindices = idx + 10; + ch_index = new int[nindices]; + for (int i = 0; i < nindices; i++) + ch_index[i] = -1; + } + else { + int old_nindices = nindices; + nindices *= 2; + if (idx >= nindices) + nindices = idx + 10; + int *old_ch_index = ch_index; + ch_index = new int[nindices]; + memcpy(ch_index, old_ch_index, sizeof(int) * old_nindices); + for (int i = old_nindices; i < nindices; i++) + ch_index[i] = -1; + delete[] old_ch_index; + } +} + +void font::extend_ch() +{ + if (ch == 0) + ch = new font_char_metric[ch_size = 16]; + else { + int old_ch_size = ch_size; + ch_size *= 2; + font_char_metric *old_ch = ch; + ch = new font_char_metric[ch_size]; + memcpy(ch, old_ch, old_ch_size * sizeof(font_char_metric)); + delete[] old_ch; + } +} + +void font::compact() +{ + int i; + for (i = nindices - 1; i >= 0; i--) + if (ch_index[i] >= 0) + break; + i++; + if (i < nindices) { + int *old_ch_index = ch_index; + ch_index = new int[i]; + memcpy(ch_index, old_ch_index, i*sizeof(int)); + delete[] old_ch_index; + nindices = i; + } + if (ch_used < ch_size) { + font_char_metric *old_ch = ch; + ch = new font_char_metric[ch_used]; + memcpy(ch, old_ch, ch_used*sizeof(font_char_metric)); + delete[] old_ch; + ch_size = ch_used; + } +} + +void font::add_entry(glyph *g, const font_char_metric &metric) +{ + int idx = glyph_to_index(g); + assert(idx >= 0); + if (idx >= nindices) + alloc_ch_index(idx); + assert(idx < nindices); + if (ch_used + 1 >= ch_size) + extend_ch(); + assert(ch_used + 1 < ch_size); + ch_index[idx] = ch_used; + ch[ch_used++] = metric; +} + +void font::copy_entry(glyph *new_glyph, glyph *old_glyph) +{ + int new_index = glyph_to_index(new_glyph); + int old_index = glyph_to_index(old_glyph); + assert(new_index >= 0 && old_index >= 0 && old_index < nindices); + if (new_index >= nindices) + alloc_ch_index(new_index); + ch_index[new_index] = ch_index[old_index]; +} + +font *font::load_font(const char *s, bool load_header_only) +{ + font *f = new font(s); + if (!f->load(load_header_only)) { + delete f; + return 0; + } + return f; +} + +static char *trim_arg(char *p) +{ + if (0 == p) + return 0; + while (csspace(*p)) + p++; + char *q = strchr(p, '\0'); + while (q > p && csspace(q[-1])) + q--; + *q = '\0'; + return p; +} + +bool font::scan_papersize(const char *p, const char **size, + double *length, double *width) +{ + double l, w; + char lu[2], wu[2]; + const char *pp = p; + bool attempt_file_open = true; + char line[255]; +again: + if (csdigit(*pp)) { + if (sscanf(pp, "%lf%1[ipPc],%lf%1[ipPc]", &l, lu, &w, wu) == 4 + && l > 0 && w > 0 + && unit_scale(&l, lu[0]) && unit_scale(&w, wu[0])) { + if (length) + *length = l; + if (width) + *width = w; + if (size) + *size = "custom"; + return true; + } + } + else { + int i; + for (i = 0; i < NUM_PAPERSIZES; i++) + if (strcasecmp(papersizes[i].name, pp) == 0) { + if (length) + *length = papersizes[i].length; + if (width) + *width = papersizes[i].width; + if (size) + *size = papersizes[i].name; + return true; + } + if (attempt_file_open) { + FILE *fp = fopen(p, "r"); + if (fp != 0) { + if (fgets(line, 254, fp)) { + // Don't recurse on file names. + attempt_file_open = false; + char *linep = strchr(line, '\0'); + // skip final newline, if any + if (*(--linep) == '\n') + *linep = '\0'; + pp = line; + } + fclose(fp); + goto again; + } + } + } + return false; +} + +bool font::load(bool load_header_only) +{ + FILE *fp; + char *path; + if ((fp = open_file(name, &path)) == 0) + return false; + text_file t(fp, path); + t.silent = load_header_only; + char *p = 0; + bool saw_name_directive = false; + while (t.next_line()) { + p = strtok(t.buf, WS); + if (strcmp(p, "name") == 0) { + p = strtok(0, WS); + if (0 == p) { + t.error("'name' directive requires an argument"); + return false; + } + if (strcmp(p, name) != 0) { + t.error("font description file name '%1' does not match 'name'" + " argument '%2'", name, p); + return false; + } + saw_name_directive = true; + } + else if (strcmp(p, "spacewidth") == 0) { + p = strtok(0, WS); + int n; + if (0 == p) { + t.error("missing argument to 'spacewidth' directive"); + return false; + } + if (sscanf(p, "%d", &n) != 1) { + t.error("invalid argument '%1' to 'spacewidth' directive", p); + return false; + } + if (n <= 0) { + t.error("'spacewidth' argument '%1' out of range", n); + return false; + } + space_width = n; + } + else if (strcmp(p, "slant") == 0) { + p = strtok(0, WS); + double n; + if (0 == p) { + t.error("missing argument to 'slant' directive"); + return false; + } + if (sscanf(p, "%lf", &n) != 1) { + t.error("invalid argument '%1' to 'slant' directive", p); + return false; + } + if (n >= 90.0 || n <= -90.0) { + t.error("'slant' directive argument '%1' out of range", n); + return false; + } + slant = n; + } + else if (strcmp(p, "ligatures") == 0) { + for (;;) { + p = strtok(0, WS); + if (0 == p || strcmp(p, "0") == 0) + break; + if (strcmp(p, "ff") == 0) + ligatures |= LIG_ff; + else if (strcmp(p, "fi") == 0) + ligatures |= LIG_fi; + else if (strcmp(p, "fl") == 0) + ligatures |= LIG_fl; + else if (strcmp(p, "ffi") == 0) + ligatures |= LIG_ffi; + else if (strcmp(p, "ffl") == 0) + ligatures |= LIG_ffl; + else { + t.error("unrecognized ligature '%1'", p); + return false; + } + } + } + else if (strcmp(p, "internalname") == 0) { + p = strtok(0, WS); + if (0 == p) { + t.error("missing argument to 'internalname' directive"); + return false; + } + internalname = new char[strlen(p) + 1]; + strcpy(internalname, p); + } + else if (strcmp(p, "special") == 0) { + special = true; + } + else if (strcmp(p, "kernpairs") != 0 && strcmp(p, "charset") != 0) { + char *directive = p; + p = strtok(0, "\n"); + handle_unknown_font_command(directive, trim_arg(p), t.path, + t.lineno); + } + else + break; + } + bool saw_charset_directive = false; + char *directive = p; + t.recognize_comments = false; + while (directive) { + if (strcmp(directive, "kernpairs") == 0) { + if (load_header_only) + return true; + for (;;) { + if (!t.next_line()) { + directive = 0; + break; + } + char *c1 = strtok(t.buf, WS); + if (0 == c1) + continue; + char *c2 = strtok(0, WS); + if (0 == c2) { + directive = c1; + break; + } + p = strtok(0, WS); + if (0 == p) { + t.error("missing kern amount for kerning pair '%1 %2'", c1, + c2); + return false; + } + int n; + if (sscanf(p, "%d", &n) != 1) { + t.error("invalid kern amount '%1' for kerning pair '%2 %3'", + p, c1, c2); + return false; + } + glyph *g1 = name_to_glyph(c1); + glyph *g2 = name_to_glyph(c2); + add_kern(g1, g2, n); + } + } + else if (strcmp(directive, "charset") == 0) { + if (load_header_only) + return true; + saw_charset_directive = true; + glyph *last_glyph = 0; + for (;;) { + if (!t.next_line()) { + directive = 0; + break; + } + char *nm = strtok(t.buf, WS); + assert(nm != 0); + p = strtok(0, WS); + if (0 == p) { + directive = nm; + break; + } + if (p[0] == '"') { + if (last_glyph == 0) { + t.error("the first entry ('%1') in 'charset' subsection" + " cannot be an alias", nm); + return false; + } + if (strcmp(nm, "---") == 0) { + t.error("an unnamed character ('---') cannot be an alias"); + return false; + } + glyph *g = name_to_glyph(nm); + copy_entry(g, last_glyph); + } + else { + font_char_metric metric; + metric.height = 0; + metric.depth = 0; + metric.pre_math_space = 0; + metric.italic_correction = 0; + metric.subscript_correction = 0; + int nparms = sscanf(p, "%d,%d,%d,%d,%d,%d", + &metric.width, &metric.height, + &metric.depth, + &metric.italic_correction, + &metric.pre_math_space, + &metric.subscript_correction); + if (nparms < 1) { + t.error("missing or invalid width for glyph '%1'", nm); + return false; + } + p = strtok(0, WS); + if (0 == p) { + t.error("missing character type for '%1'", nm); + return false; + } + int type; + if (sscanf(p, "%d", &type) != 1) { + t.error("invalid character type for '%1'", nm); + return false; + } + if (type < 0 || type > 255) { + t.error("character type '%1' out of range for '%2'", type, + nm); + return false; + } + metric.type = type; + p = strtok(0, WS); + if (0 == p) { + t.error("missing code for '%1'", nm); + return false; + } + char *ptr; + metric.code = (int)strtol(p, &ptr, 0); + if (metric.code == 0 && ptr == p) { + t.error("invalid code '%1' for character '%2'", p, nm); + return false; + } + if (is_unicode) { + int w = wcwidth(metric.code); + if (w > 1) + metric.width *= w; + } + p = strtok(0, WS); + if ((0 == p) || (strcmp(p, "--") == 0)) { + metric.special_device_coding = 0; + } + else { + char *nam = new char[strlen(p) + 1]; + strcpy(nam, p); + metric.special_device_coding = nam; + } + if (strcmp(nm, "---") == 0) { + last_glyph = number_to_glyph(metric.code); + add_entry(last_glyph, metric); + } + else { + last_glyph = name_to_glyph(nm); + add_entry(last_glyph, metric); + copy_entry(number_to_glyph(metric.code), last_glyph); + } + } + } + if (0 == last_glyph) { + t.error("no glyphs defined in font description"); + return false; + } + } + else { + t.error("unrecognized font description directive '%1' (missing" + " 'kernpairs' or 'charset'?)", directive); + return false; + } + } + compact(); + t.lineno = 0; + if (!saw_name_directive) { + t.error("font description 'name' directive missing"); + return false; + } + if (!is_unicode && !saw_charset_directive) { + t.error("font description 'charset' subsection missing"); + return false; + } + if (space_width == 0) { + t.error("font description 'spacewidth' directive missing"); + // _Don't_ return false; compute a typical one for Western glyphs. + if (zoom) + space_width = scale_round(unitwidth, res, 72 * 3 * sizescale, + zoom); + else + space_width = scale_round(unitwidth, res, 72 * 3 * sizescale); + } + return true; +} + +static struct { + const char *numeric_directive; + int *ptr; +} table[] = { + { "res", &font::res }, + { "hor", &font::hor }, + { "vert", &font::vert }, + { "unitwidth", &font::unitwidth }, + { "paperwidth", &font::paperwidth }, + { "paperlength", &font::paperlength }, + { "spare1", &font::biggestfont }, + { "biggestfont", &font::biggestfont }, + { "spare2", &font::spare2 }, + { "sizescale", &font::sizescale }, + }; + +// Return file specification of DESC file for selected output device if +// it can be located and is valid, and a null pointer otherwise. +const char *font::load_desc() +{ + int nfonts = 0; + FILE *fp; + char *path; + if ((fp = open_file("DESC", &path)) == 0) + return 0 /* nullptr */; + text_file t(fp, path); + while (t.next_line()) { + char *p = strtok(t.buf, WS); + assert(p != 0); + bool numeric_directive_found = false; + unsigned int idx; + for (idx = 0; !numeric_directive_found + && idx < sizeof(table) / sizeof(table[0]); idx++) + if (strcmp(table[idx].numeric_directive, p) == 0) + numeric_directive_found = true; + if (numeric_directive_found) { + char *q = strtok(0, WS); + if (0 == q) { + t.error("missing value for directive '%1'", p); + return 0 /* nullptr */; + } + int val; + if (sscanf(q, "%d", &val) != 1) { + t.error("'%1' directive given invalid number '%2'", p, q); + return 0 /* nullptr */; + } + if ((strcmp(p, "res") == 0 + || strcmp(p, "hor") == 0 + || strcmp(p, "vert") == 0 + || strcmp(p, "unitwidth") == 0 + || strcmp(p, "paperwidth") == 0 + || strcmp(p, "paperlength") == 0 + || strcmp(p, "sizescale") == 0) + && val < 1) { + t.error("expected argument to '%1' directive to be a" + " positive number, got '%2'", p, val); + return 0 /* nullptr */; + } + *(table[idx-1].ptr) = val; + } + else if (strcmp("family", p) == 0) { + p = strtok(0, WS); + if (0 == p) { + t.error("'family' directive requires an argument"); + return 0 /* nullptr */; + } + char *tem = new char[strlen(p)+1]; + strcpy(tem, p); + family = tem; + } + else if (strcmp("fonts", p) == 0) { + p = strtok(0, WS); + if (0 == p) { + t.error("'fonts' directive requires arguments"); + return 0 /* nullptr */; + } + if (sscanf(p, "%d", &nfonts) != 1 || nfonts <= 0) { + t.error("expected first argument to 'fonts' directive to be a" + " non-negative number, got '%1'", p); + return 0 /* nullptr */; + } + font_name_table = (const char **)new char *[nfonts+1]; + for (int i = 0; i < nfonts; i++) { + p = strtok(0, WS); + while (0 == p) { + if (!t.next_line()) { + t.error("unexpected end of file while reading font list"); + return 0 /* nullptr */; + } + p = strtok(t.buf, WS); + } + char *temp = new char[strlen(p)+1]; + strcpy(temp, p); + font_name_table[i] = temp; + } + p = strtok(0, WS); + if (p != 0) { + t.error("font count does not match declared number of fonts" + " ('%1')", nfonts); + return 0 /* nullptr */; + } + font_name_table[nfonts] = 0; + } + else if (strcmp("papersize", p) == 0) { + if (0 == res) { + t.error("'res' directive must precede 'papersize' in device" + " description file"); + return 0 /* nullptr */; + } + p = strtok(0, WS); + if (0 == p) { + t.error("'papersize' directive requires an argument"); + return 0 /* nullptr */; + } + bool found_paper = false; + char *savedp = strdup(p); + if (0 == savedp) + t.fatal("memory allocation failure while processing 'papersize'" + " directive"); + while (p) { + double unscaled_paperwidth, unscaled_paperlength; + if (scan_papersize(p, &papersize, &unscaled_paperlength, + &unscaled_paperwidth)) { + paperwidth = int(unscaled_paperwidth * res + 0.5); + paperlength = int(unscaled_paperlength * res + 0.5); + found_paper = true; + break; + } + p = strtok(0, WS); + } + assert(savedp != 0); + if (!found_paper) { + t.error("unable to determine a paper format from '%1'", savedp); + free(savedp); + return 0 /* nullptr */; + } + free(savedp); + } + else if (strcmp("unscaled_charwidths", p) == 0) + use_unscaled_charwidths = true; + else if (strcmp("pass_filenames", p) == 0) + pass_filenames = true; + else if (strcmp("sizes", p) == 0) { + int n = 16; + sizes = new int[n]; + int i = 0; + for (;;) { + p = strtok(0, WS); + while (0 == p) { + if (!t.next_line()) { + t.error("list of sizes must be terminated by '0'"); + return 0 /* nullptr */; + } + p = strtok(t.buf, WS); + } + int lower, upper; + switch (sscanf(p, "%d-%d", &lower, &upper)) { + case 1: + upper = lower; + // fall through + case 2: + if (lower <= upper && lower >= 0) + break; + // fall through + default: + t.error("invalid size range '%1'", p); + return 0 /* nullptr */; + } + if (i + 2 > n) { + int *old_sizes = sizes; + sizes = new int[n*2]; + memcpy(sizes, old_sizes, n*sizeof(int)); + n *= 2; + delete[] old_sizes; + } + sizes[i++] = lower; + if (lower == 0) + break; + sizes[i++] = upper; + } + if (i == 1) { + t.error("must have some sizes"); + return 0 /* nullptr */; + } + } + else if (strcmp("styles", p) == 0) { + int style_table_size = 5; + style_table = (const char **)new char *[style_table_size]; + int j; + for (j = 0; j < style_table_size; j++) + style_table[j] = 0; + int i = 0; + for (;;) { + p = strtok(0, WS); + if (0 == p) + break; + // leave room for terminating 0 + if (i + 1 >= style_table_size) { + const char **old_style_table = style_table; + style_table_size *= 2; + style_table = (const char **)new char*[style_table_size]; + for (j = 0; j < i; j++) + style_table[j] = old_style_table[j]; + for (; j < style_table_size; j++) + style_table[j] = 0; + delete[] old_style_table; + } + char *tem = new char[strlen(p) + 1]; + strcpy(tem, p); + style_table[i++] = tem; + } + } + else if (strcmp("tcommand", p) == 0) + has_tcommand = true; + else if (strcmp("use_charnames_in_special", p) == 0) + use_charnames_in_special = true; + else if (strcmp("unicode", p) == 0) + is_unicode = true; + else if (strcmp("image_generator", p) == 0) { + p = strtok(0, WS); + if (0 == p) { + t.error("'image_generator' directive requires an argument"); + return 0 /* nullptr */; + } + image_generator = strsave(p); + } + else if (strcmp("charset", p) == 0) + break; + else if (unknown_desc_command_handler) { + char *directive = p; + p = strtok(0, "\n"); + (*unknown_desc_command_handler)(directive, trim_arg(p), t.path, + t.lineno); + } + } + t.lineno = 0; + if (res == 0) { + t.error("device description file missing 'res' directive"); + return 0 /* nullptr */; + } + if (unitwidth == 0) { + t.error("device description file missing 'unitwidth' directive"); + return 0 /* nullptr */; + } + if (font_name_table == 0) { + t.error("device description file missing 'fonts' directive"); + return 0 /* nullptr */; + } + if (sizes == 0) { + t.error("device description file missing 'sizes' directive"); + return 0 /* nullptr */; + } + return path; +} + +void font::handle_unknown_font_command(const char *, const char *, + const char *, int) +{ +} + +FONT_COMMAND_HANDLER +font::set_unknown_desc_command_handler(FONT_COMMAND_HANDLER func) +{ + FONT_COMMAND_HANDLER prev = unknown_desc_command_handler; + unknown_desc_command_handler = func; + return prev; +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/fontfile.cpp b/src/libs/libgroff/fontfile.cpp new file mode 100644 index 0000000..8987971 --- /dev/null +++ b/src/libs/libgroff/fontfile.cpp @@ -0,0 +1,80 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#include <stdlib.h> +#include <errno.h> +#include "font.h" +#include "searchpath.h" +#include "device.h" +#include "defs.h" + +const char *const FONT_ENV_VAR = "GROFF_FONT_PATH"; + +static search_path font_path(FONT_ENV_VAR, FONTPATH, 0, 0); + +int font::res = 0; +int font::hor = 1; +int font::vert = 1; +int font::unitwidth = 0; +int font::paperwidth = 0; +int font::paperlength = 0; +const char *font::papersize = 0; +int font::biggestfont = 0; +int font::spare2 = 0; +int font::sizescale = 1; +bool font::has_tcommand = false; +bool font::pass_filenames = false; +bool font::use_unscaled_charwidths = false; +bool font::use_charnames_in_special = false; +bool font::is_unicode = false; +const char *font::image_generator = 0; +const char **font::font_name_table = 0; +int *font::sizes = 0; +const char *font::family = 0; +const char **font::style_table = 0; +FONT_COMMAND_HANDLER font::unknown_desc_command_handler = 0; + +void font::command_line_font_dir(const char *dir) +{ + font_path.command_line_dir(dir); +} + +FILE *font::open_file(const char *nm, char **pathp) +{ + FILE *fp = 0 /* nullptr */; + // Do not traverse user-specified directories; Savannah #61424. + if (0 /* nullptr */ == strchr(nm, '/')) { + // Allocate enough for nm + device + 'dev' '/' '\0'. + int expected_size = strlen(nm) + strlen(device) + 5; + char *filename = new char[expected_size]; + const int actual_size = sprintf(filename, "dev%s/%s", device, nm); + expected_size--; // sprintf() doesn't count the null terminator. + if (actual_size == expected_size) + fp = font_path.open_file(filename, pathp); + delete[] filename; + } + return fp; +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/geometry.cpp b/src/libs/libgroff/geometry.cpp new file mode 100644 index 0000000..c4665c4 --- /dev/null +++ b/src/libs/libgroff/geometry.cpp @@ -0,0 +1,180 @@ +// -*- C++ -*- +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by Gaius Mulley <gaius@glam.ac.uk> + using adjust_arc_center() from printer.cpp, written by James Clark. + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <math.h> + +#undef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#undef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + + +// This utility function adjusts the specified center of the +// arc so that it is equidistant between the specified start +// and end points. (p[0], p[1]) is a vector from the current +// point to the center; (p[2], p[3]) is a vector from the +// center to the end point. If the center can be adjusted, +// a vector from the current point to the adjusted center is +// stored in c[0], c[1] and 1 is returned. Otherwise 0 is +// returned. + +#if 1 +int adjust_arc_center(const int *p, double *c) +{ + // We move the center along a line parallel to the line between + // the specified start point and end point so that the center + // is equidistant between the start and end point. + // It can be proved (using Lagrange multipliers) that this will + // give the point nearest to the specified center that is equidistant + // between the start and end point. + + double x = p[0] + p[2]; // (x, y) is the end point + double y = p[1] + p[3]; + double n = x*x + y*y; + if (n != 0) { + c[0]= double(p[0]); + c[1] = double(p[1]); + double k = .5 - (c[0]*x + c[1]*y)/n; + c[0] += k*x; + c[1] += k*y; + return 1; + } + else + return 0; +} +#else +int printer::adjust_arc_center(const int *p, double *c) +{ + int x = p[0] + p[2]; // (x, y) is the end point + int y = p[1] + p[3]; + // Start at the current point; go in the direction of the specified + // center point until we reach a point that is equidistant between + // the specified starting point and the specified end point. Place + // the center of the arc there. + double n = p[0]*double(x) + p[1]*double(y); + if (n > 0) { + double k = (double(x)*x + double(y)*y)/(2.0*n); + // (cx, cy) is our chosen center + c[0] = k*p[0]; + c[1] = k*p[1]; + return 1; + } + else { + // We would never reach such a point. So instead start at the + // specified end point of the arc. Go towards the specified + // center point until we reach a point that is equidistant between + // the specified start point and specified end point. Place + // the center of the arc there. + n = p[2]*double(x) + p[3]*double(y); + if (n > 0) { + double k = 1 - (double(x)*x + double(y)*y)/(2.0*n); + // (c[0], c[1]) is our chosen center + c[0] = p[0] + k*p[2]; + c[1] = p[1] + k*p[3]; + return 1; + } + else + return 0; + } +} +#endif + + +/* + * check_output_arc_limits - works out the smallest box that will encompass + * an arc defined by an origin (x, y) and two + * vectors (p0, p1) and (p2, p3). + * (x1, y1) -> start of arc + * (x1, y1) + (xv1, yv1) -> center of circle + * (x1, y1) + (xv1, yv1) + (xv2, yv2) -> end of arc + * + * Works out in which quadrant the arc starts and + * stops, and from this it determines the x, y + * max/min limits. The arc is drawn clockwise. + */ + +void check_output_arc_limits(int x_1, int y_1, + int xv_1, int yv_1, + int xv_2, int yv_2, + double c_0, double c_1, + int *minx, int *maxx, + int *miny, int *maxy) +{ + int radius = (int)sqrt(c_0 * c_0 + c_1 * c_1); + // clockwise direction + int xcenter = x_1 + xv_1; + int ycenter = y_1 + yv_1; + int xend = xcenter + xv_2; + int yend = ycenter + yv_2; + // for convenience, transform to counterclockwise direction, + // centered at the origin + int xs = xend - xcenter; + int ys = yend - ycenter; + int xe = x_1 - xcenter; + int ye = y_1 - ycenter; + *minx = *maxx = xs; + *miny = *maxy = ys; + if (xe > *maxx) + *maxx = xe; + else if (xe < *minx) + *minx = xe; + if (ye > *maxy) + *maxy = ye; + else if (ye < *miny) + *miny = ye; + int qs, qe; // quadrants 0..3 + if (xs >= 0) + qs = (ys >= 0) ? 0 : 3; + else + qs = (ys >= 0) ? 1 : 2; + if (xe >= 0) + qe = (ye >= 0) ? 0 : 3; + else + qe = (ye >= 0) ? 1 : 2; + // make qs always smaller than qe + if ((qs > qe) + || ((qs == qe) && (double(xs) * ye < double(xe) * ys))) + qe += 4; + for (int i = qs; i < qe; i++) + switch (i % 4) { + case 0: + *maxy = radius; + break; + case 1: + *minx = -radius; + break; + case 2: + *miny = -radius; + break; + case 3: + *maxx = radius; + break; + } + *minx += xcenter; + *maxx += xcenter; + *miny += ycenter; + *maxy += ycenter; +} diff --git a/src/libs/libgroff/getcwd.c b/src/libs/libgroff/getcwd.c new file mode 100644 index 0000000..dd8b578 --- /dev/null +++ b/src/libs/libgroff/getcwd.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2000-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Partial emulation of getcwd in terms of getwd. */ + +#include <config.h> +#include <sys/param.h> +#include <string.h> +#include <errno.h> + +char *getwd(); + +char *getcwd(buf, size) + char *buf; + int size; /* POSIX says this should be size_t */ +{ + if (size <= 0) { + errno = EINVAL; + return 0; + } + else { + char mybuf[MAXPATHLEN]; + int saved_errno = errno; + + errno = 0; + if (!getwd(mybuf)) { + if (errno == 0) + ; /* what to do? */ + return 0; + } + errno = saved_errno; + if (strlen(mybuf) + 1 > size) { + errno = ERANGE; + return 0; + } + strcpy(buf, mybuf); + return buf; + } +} diff --git a/src/libs/libgroff/getopt.c b/src/libs/libgroff/getopt.c new file mode 100644 index 0000000..6efa529 --- /dev/null +++ b/src/libs/libgroff/getopt.c @@ -0,0 +1,1241 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to drepper@gnu.org + before changing it! + Copyright (C) 1987-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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 3 of the License, or + (at your option) any later version. + + This program 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 for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. + Ditto for AIX 3.2 and <stdlib.h>. */ +#ifndef _NO_PROTO +# define _NO_PROTO +#endif + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdio.h> + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +# include <stdlib.h> +# include <unistd.h> +#endif /* GNU C library. */ + +#include <string.h> + +#ifdef VMS +# include <unixlib.h> +#endif + +#ifdef _LIBC +# include <libintl.h> +#else +# include "gettext.h" +# define _(msgid) gettext (msgid) +#endif + +#if defined _LIBC && defined USE_IN_LIBIO +# include <wchar.h> +#endif + +#ifndef attribute_hidden +# define attribute_hidden +#endif + +/* Unlike standard Unix 'getopt', functions like 'getopt_long' + let the user intersperse the options with the other arguments. + + As 'getopt_long' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Using 'getopt' or setting the environment variable POSIXLY_CORRECT + disables permutation. + Then the application's behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" +#include "getopt_int.h" + +/* For communication from 'getopt' to the caller. + When 'getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when 'ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to 'getopt'. + + On entry to 'getopt', zero means this is the first call; initialize. + + When 'getopt' returns -1, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, 'optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* 1003.2 says this must be 1 before any call. */ +int optind = 1; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Keep a global copy of all internal members of getopt_data. */ + +static struct _getopt_data getopt_data; + + +#ifndef __GNU_LIBRARY__ + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +#ifndef getenv +extern char *getenv (); +#endif + +#endif /* not __GNU_LIBRARY__ */ + +#ifdef _LIBC +/* Stored original parameters. + XXX This is no good solution. We should rather copy the args so + that we can compare them later. But we must not use malloc(3). */ +extern int __libc_argc; +extern char **__libc_argv; + +/* Bash 2.0 gives us an environment variable containing flags + indicating ARGV elements that should not be considered arguments. */ + +# ifdef USE_NONOPTION_FLAGS +/* Defined in getopt_init.c */ +extern char *__getopt_nonoption_flags; +# endif + +# ifdef USE_NONOPTION_FLAGS +# define SWAP_FLAGS(ch1, ch2) \ + if (d->__nonoption_flags_len > 0) \ + { \ + char __tmp = __getopt_nonoption_flags[ch1]; \ + __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ + __getopt_nonoption_flags[ch2] = __tmp; \ + } +# else +# define SWAP_FLAGS(ch1, ch2) +# endif +#else /* !_LIBC */ +# define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + 'first_nonopt' and 'last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (char **argv, struct _getopt_data *d) +{ + int bottom = d->__first_nonopt; + int middle = d->__last_nonopt; + int top = d->optind; + char *tem; + + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + /* First make sure the handling of the '__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (d->__nonoption_flags_len > 0 && top >= d->__nonoption_flags_max_len) + { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc (top + 1); + if (new_str == NULL) + d->__nonoption_flags_len = d->__nonoption_flags_max_len = 0; + else + { + memset (__mempcpy (new_str, __getopt_nonoption_flags, + d->__nonoption_flags_max_len), + '\0', top + 1 - d->__nonoption_flags_max_len); + d->__nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } + } +#endif + + while (top > middle && middle > bottom) + { + if (top - middle > middle - bottom) + { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } + else + { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) + { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS (bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } + } + + /* Update records for the slots the non-options now occupy. */ + + d->__first_nonopt += (d->optind - d->__last_nonopt); + d->__last_nonopt = d->optind; +} + +/* Initialize the internal data when the first call is made. */ + +static const char * +_getopt_initialize (__attribute__((__unused__)) int argc, + __attribute__((__unused__)) char **argv, + const char *optstring, int posixly_correct, + struct _getopt_data *d) +{ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + d->__first_nonopt = d->__last_nonopt = d->optind; + + d->__nextchar = NULL; + + d->__posixly_correct = posixly_correct || !!getenv ("POSIXLY_CORRECT"); + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + d->__ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + d->__ordering = REQUIRE_ORDER; + ++optstring; + } + else if (d->__posixly_correct) + d->__ordering = REQUIRE_ORDER; + else + d->__ordering = PERMUTE; + +#if defined _LIBC && defined USE_NONOPTION_FLAGS + if (!d->__posixly_correct + && argc == __libc_argc && argv == __libc_argv) + { + if (d->__nonoption_flags_max_len == 0) + { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + d->__nonoption_flags_max_len = -1; + else + { + const char *orig_str = __getopt_nonoption_flags; + int len = d->__nonoption_flags_max_len = strlen (orig_str); + if (d->__nonoption_flags_max_len < argc) + d->__nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *) malloc (d->__nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + d->__nonoption_flags_max_len = -1; + else + memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), + '\0', d->__nonoption_flags_max_len - len); + } + } + d->__nonoption_flags_len = d->__nonoption_flags_max_len; + } + else + d->__nonoption_flags_len = 0; +#endif + + return optstring; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If 'getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If 'getopt' finds another option character, it returns that character, + updating 'optind' and 'nextchar' so that the next call to 'getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, 'getopt' returns -1. + Then 'optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set 'opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in 'optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in 'optarg', otherwise 'optarg' is set to zero. + + If OPTSTRING starts with '-' or '+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with '--' instead of '-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a '=', or else the in next ARGV-element. + When 'getopt' finds a long-named option, it returns 0 if that option's + 'flag' field is nonzero, the value of the option's 'val' field + if the 'flag' field is zero. + + LONGOPTS is a vector of 'struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. + + If POSIXLY_CORRECT is nonzero, behave as if the POSIXLY_CORRECT + environment variable were set. */ + +int +_getopt_internal_r (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, int posixly_correct, struct _getopt_data *d) +{ + int print_errors = d->opterr; + if (optstring[0] == ':') + print_errors = 0; + + if (argc < 1) + return -1; + + d->optarg = NULL; + + if (d->optind == 0 || !d->__initialized) + { + if (d->optind == 0) + d->optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize (argc, argv, optstring, + posixly_correct, d); + d->__initialized = 1; + } + + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ +#if defined _LIBC && defined USE_NONOPTION_FLAGS +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0' \ + || (d->optind < d->__nonoption_flags_len \ + && __getopt_nonoption_flags[d->optind] == '1')) +#else +# define NONOPTION_P (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0') +#endif + + if (d->__nextchar == NULL || *d->__nextchar == '\0') + { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (d->__last_nonopt > d->optind) + d->__last_nonopt = d->optind; + if (d->__first_nonopt > d->optind) + d->__first_nonopt = d->optind; + + if (d->__ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__last_nonopt != d->optind) + d->__first_nonopt = d->optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (d->optind < argc && NONOPTION_P) + d->optind++; + d->__last_nonopt = d->optind; + } + + /* The special ARGV-element '--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (d->optind != argc && !strcmp (argv[d->optind], "--")) + { + d->optind++; + + if (d->__first_nonopt != d->__last_nonopt + && d->__last_nonopt != d->optind) + exchange ((char **) argv, d); + else if (d->__first_nonopt == d->__last_nonopt) + d->__first_nonopt = d->optind; + d->__last_nonopt = argc; + + d->optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (d->optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (d->__first_nonopt != d->__last_nonopt) + d->optind = d->__first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) + { + if (d->__ordering == REQUIRE_ORDER) + return -1; + d->optarg = argv[d->optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + d->__nextchar = (argv[d->optind] + 1 + + (longopts != NULL && argv[d->optind][1] == '-')); + } + + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[d->optind][1] == '-' + || (long_only && (argv[d->optind][2] + || !strchr (optstring, argv[d->optind][1]))))) + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) + { + if ((unsigned int) (nameend - d->__nextchar) + == (unsigned int) strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag + || pfound->val != p->val) + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("%s: option '%s' is ambiguous\n"), + argv[0], argv[d->optind]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option '%s' is ambiguous\n"), + argv[0], argv[d->optind]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; + d->optopt = 0; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + d->optind++; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind - 1][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option '--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#else + fprintf (stderr, _("\ +%s: option '--%s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("\ +%s: option '%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#else + fprintf (stderr, _("\ +%s: option '%c%s' doesn't allow an argument\n"), + argv[0], argv[d->optind - 1][0], + pfound->name); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + + d->__nextchar += strlen (d->__nextchar); + + d->optopt = pfound->val; + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option '%s' requires an argument\n"), + argv[0], argv[d->optind - 1]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option '%s' requires an argument\n"), + argv[0], argv[d->optind - 1]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + d->__nextchar += strlen (d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[d->optind][1] == '-' + || strchr (optstring, *d->__nextchar) == NULL) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (argv[d->optind][1] == '-') + { + /* --option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option '--%s'\n"), + argv[0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option '--%s'\n"), + argv[0], d->__nextchar); +#endif + } + else + { + /* +option or -option */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: unrecognized option '%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#else + fprintf (stderr, _("%s: unrecognized option '%c%s'\n"), + argv[0], argv[d->optind][0], d->__nextchar); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + d->__nextchar = (char *) ""; + d->optind++; + d->optopt = 0; + return '?'; + } + } + + /* Look at and handle the next short option-character. */ + + { + char c = *d->__nextchar++; + char *temp = strchr (optstring, c); + + /* Increment 'optind' when we start to process its last character. */ + if (*d->__nextchar == '\0') + ++d->optind; + + if (temp == NULL || c == ':') + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + int n; +#endif + + if (d->__posixly_correct) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: illegal option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); +#endif + } + else + { +#if defined _LIBC && defined USE_IN_LIBIO + n = __asprintf (&buf, _("%s: invalid option -- %c\n"), + argv[0], c); +#else + fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); +#endif + } + +#if defined _LIBC && defined USE_IN_LIBIO + if (n >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#endif + } + d->optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') + { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, + _("%s: option requires an argument -- %c\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } + else + /* We already incremented 'd->optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; + nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp (p->name, d->__nextchar, nameend - d->__nextchar)) + { + if ((unsigned int) (nameend - d->__nextchar) == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("%s: option '-W %s' is ambiguous\n"), + argv[0], argv[d->optind]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("%s: option '-W %s' is ambiguous\n"), + argv[0], argv[d->optind]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + d->optind++; + return '?'; + } + if (pfound != NULL) + { + option_index = indfound; + if (*nameend) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + d->optarg = nameend + 1; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option '-W %s' doesn't allow an argument\n"), + argv[0], pfound->name) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, _("\ +%s: option '-W %s' doesn't allow an argument\n"), + argv[0], pfound->name); +#endif + } + + d->__nextchar += strlen (d->__nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (d->optind < argc) + d->optarg = argv[d->optind++]; + else + { + if (print_errors) + { +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option '%s' requires an argument\n"), + argv[0], argv[d->optind - 1]) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 + |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option '%s' requires an argument\n"), + argv[0], argv[d->optind - 1]); +#endif + } + d->__nextchar += strlen (d->__nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + d->__nextchar += strlen (d->__nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + d->__nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + d->optind++; + } + else + d->optarg = NULL; + d->__nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*d->__nextchar != '\0') + { + d->optarg = d->__nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + d->optind++; + } + else if (d->optind == argc) + { + if (print_errors) + { + /* 1003.2 specifies the format of this message. */ +#if defined _LIBC && defined USE_IN_LIBIO + char *buf; + + if (__asprintf (&buf, _("\ +%s: option requires an argument -- %c\n"), + argv[0], c) >= 0) + { + _IO_flockfile (stderr); + + int old_flags2 = ((_IO_FILE *) stderr)->_flags2; + ((_IO_FILE *) stderr)->_flags2 |= _IO_FLAGS2_NOTCANCEL; + + if (_IO_fwide (stderr, 0) > 0) + __fwprintf (stderr, L"%s", buf); + else + fputs (buf, stderr); + + ((_IO_FILE *) stderr)->_flags2 = old_flags2; + _IO_funlockfile (stderr); + + free (buf); + } +#else + fprintf (stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); +#endif + } + d->optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented 'optind' once; + increment it again when taking next ARGV-elt as argument. */ + d->optarg = argv[d->optind++]; + d->__nextchar = NULL; + } + } + return c; + } +} + +int +_getopt_internal (int argc, char **argv, const char *optstring, + const struct option *longopts, int *longind, + int long_only, int posixly_correct) +{ + int result; + + getopt_data.optind = optind; + getopt_data.opterr = opterr; + + result = _getopt_internal_r (argc, argv, optstring, longopts, longind, + long_only, posixly_correct, &getopt_data); + + optind = getopt_data.optind; + optarg = getopt_data.optarg; + optopt = getopt_data.optopt; + + return result; +} + +/* glibc gets a LSB-compliant getopt. + Standalone applications get a POSIX-compliant getopt. */ +#if _LIBC +enum { POSIXLY_CORRECT = 0 }; +#else +enum { POSIXLY_CORRECT = 1 }; +#endif + +int +getopt (int argc, char *const *argv, const char *optstring) +{ + return _getopt_internal (argc, (char **) argv, optstring, NULL, NULL, 0, + POSIXLY_CORRECT); +} + + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of 'getopt'. */ + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/src/libs/libgroff/getopt1.c b/src/libs/libgroff/getopt1.c new file mode 100644 index 0000000..374b3ce --- /dev/null +++ b/src/libs/libgroff/getopt1.c @@ -0,0 +1,172 @@ +/* getopt_long and getopt_long_only entry points for GNU getopt. + Copyright (C) 1987-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program 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 3 of the License, or + (at your option) any later version. + + This program 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 for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef _LIBC +# include <getopt.h> +#else +# include "getopt.h" +#endif +#include "getopt_int.h" + +#include <stdio.h> + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#include <stdlib.h> +#endif + +#ifndef NULL +#define NULL 0 +#endif + +int +getopt_long (int argc, char *__getopt_argv_const *argv, const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 0, 0); +} + +int +_getopt_long_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 0, 0, d); +} + +/* Like getopt_long, but '-' as well as '--' can indicate a long option. + If an option that starts with '-' (not '--') doesn't match a long option, + but does match a short option, it is parsed as a short option + instead. */ + +int +getopt_long_only (int argc, char *__getopt_argv_const *argv, + const char *options, + const struct option *long_options, int *opt_index) +{ + return _getopt_internal (argc, (char **) argv, options, long_options, + opt_index, 1, 0); +} + +int +_getopt_long_only_r (int argc, char **argv, const char *options, + const struct option *long_options, int *opt_index, + struct _getopt_data *d) +{ + return _getopt_internal_r (argc, argv, options, long_options, opt_index, + 1, 0, d); +} + + +#ifdef TEST + +#include <stdio.h> + +int +main (int argc, char **argv) +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = + { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long (argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) + { + case 0: + printf ("option %s", long_options[option_index].name); + if (optarg) + printf (" with arg %s", optarg); + printf ("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value '%s'\n", optarg); + break; + + case 'd': + printf ("option d with value '%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/src/libs/libgroff/glyphuni.cpp b/src/libs/libgroff/glyphuni.cpp new file mode 100644 index 0000000..0d5a217 --- /dev/null +++ b/src/libs/libgroff/glyphuni.cpp @@ -0,0 +1,523 @@ +// -*- C++ -*- +/* Copyright (C) 2002-2020 Free Software Foundation, Inc. + Written by Werner Lemberg <wl@gnu.org> + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" +#include "stringclass.h" +#include "ptable.h" + +#include "unicode.h" + +struct glyph_to_unicode { + char *value; +}; + +declare_ptable(glyph_to_unicode) +implement_ptable(glyph_to_unicode) + +PTABLE(glyph_to_unicode) glyph_to_unicode_table; + +// The entries commented out in the table below can't be used in glyph +// names. + +struct S { + const char *key; + const char *value; +} glyph_to_unicode_list[] = { + { "!", "0021" }, + { "\"", "0022" }, + { "dq", "0022" }, + { "#", "0023" }, + { "sh", "0023" }, + { "$", "0024" }, + { "Do", "0024" }, + { "%", "0025" }, + { "&", "0026" }, + { "aq", "0027" }, + { "(", "0028" }, + { ")", "0029" }, + { "*", "002A" }, + { "+", "002B" }, + { "pl", "002B" }, + { ",", "002C" }, + { ".", "002E" }, + { "/", "002F" }, + { "sl", "002F" }, + { "0", "0030" }, + { "1", "0031" }, + { "2", "0032" }, + { "3", "0033" }, + { "4", "0034" }, + { "5", "0035" }, + { "6", "0036" }, + { "7", "0037" }, + { "8", "0038" }, + { "9", "0039" }, + { ":", "003A" }, + { ";", "003B" }, + { "<", "003C" }, + { "=", "003D" }, + { "eq", "003D" }, + { ">", "003E" }, + { "?", "003F" }, + { "@", "0040" }, + { "at", "0040" }, + { "A", "0041" }, + { "B", "0042" }, + { "C", "0043" }, + { "D", "0044" }, + { "E", "0045" }, + { "F", "0046" }, + { "G", "0047" }, + { "H", "0048" }, + { "I", "0049" }, + { "J", "004A" }, + { "K", "004B" }, + { "L", "004C" }, + { "M", "004D" }, + { "N", "004E" }, + { "O", "004F" }, + { "P", "0050" }, + { "Q", "0051" }, + { "R", "0052" }, + { "S", "0053" }, + { "T", "0054" }, + { "U", "0055" }, + { "V", "0056" }, + { "W", "0057" }, + { "X", "0058" }, + { "Y", "0059" }, + { "Z", "005A" }, +//{ "[", "005B" }, + { "lB", "005B" }, +//{ "\\", "005C" }, + { "rs", "005C" }, +//{ "]", "005D" }, + { "rB", "005D" }, + { "a^", "005E" }, + { "^", "005E" }, + { "ha", "005E" }, + { "_", "005F" }, + { "ru", "005F" }, + { "ul", "005F" }, + { "ga", "0060" }, + { "a", "0061" }, + { "b", "0062" }, + { "c", "0063" }, + { "d", "0064" }, + { "e", "0065" }, + { "f", "0066" }, + { "ff", "0066_0066" }, + { "Fi", "0066_0066_0069" }, + { "Fl", "0066_0066_006C" }, + { "fi", "0066_0069" }, + { "fl", "0066_006C" }, + { "g", "0067" }, + { "h", "0068" }, + { "i", "0069" }, + { "j", "006A" }, + { "k", "006B" }, + { "l", "006C" }, + { "m", "006D" }, + { "n", "006E" }, + { "o", "006F" }, + { "p", "0070" }, + { "q", "0071" }, + { "r", "0072" }, + { "s", "0073" }, + { "t", "0074" }, + { "u", "0075" }, + { "v", "0076" }, + { "w", "0077" }, + { "x", "0078" }, + { "y", "0079" }, + { "z", "007A" }, + { "lC", "007B" }, + { "{", "007B" }, + { "ba", "007C" }, + { "or", "007C" }, + { "|", "007C" }, + { "rC", "007D" }, + { "}", "007D" }, + { "a~", "007E" }, + { "~", "007E" }, + { "ti", "007E" }, + { "r!", "00A1" }, + { "ct", "00A2" }, + { "Po", "00A3" }, + { "Cs", "00A4" }, + { "Ye", "00A5" }, + { "bb", "00A6" }, + { "sc", "00A7" }, + { "ad", "00A8" }, + { "co", "00A9" }, + { "Of", "00AA" }, + { "Fo", "00AB" }, + { "no", "00AC" }, + { "tno", "00AC" }, + // The soft hyphen U+00AD is meaningful only in the input file, + // not in the output. + { "rg", "00AE" }, + { "a-", "00AF" }, + { "de", "00B0" }, + { "+-", "00B1" }, + { "t+-", "00B1" }, + { "S2", "00B2" }, + { "S3", "00B3" }, + { "aa", "00B4" }, + { "mc", "00B5" }, + { "ps", "00B6" }, + { "pc", "00B7" }, + { "ac", "00B8" }, + { "S1", "00B9" }, + { "Om", "00BA" }, + { "Fc", "00BB" }, + { "14", "00BC" }, + { "12", "00BD" }, + { "34", "00BE" }, + { "r?", "00BF" }, + { "`A", "00C0" }, + { "'A", "00C1" }, + { "^A", "00C2" }, + { "~A", "00C3" }, + { ":A", "00C4" }, + { "oA", "00C5" }, + { "AE", "00C6" }, + { ",C", "00C7" }, + { "`E", "00C8" }, + { "'E", "00C9" }, + { "^E", "00CA" }, + { ":E", "00CB" }, + { "`I", "00CC" }, + { "'I", "00CD" }, + { "^I", "00CE" }, + { ":I", "00CF" }, + { "-D", "00D0" }, + { "~N", "00D1" }, + { "`O", "00D2" }, + { "'O", "00D3" }, + { "^O", "00D4" }, + { "~O", "00D5" }, + { ":O", "00D6" }, + { "mu", "00D7" }, + { "tmu", "00D7" }, + { "/O", "00D8" }, + { "`U", "00D9" }, + { "'U", "00DA" }, + { "^U", "00DB" }, + { ":U", "00DC" }, + { "'Y", "00DD" }, + { "TP", "00DE" }, + { "ss", "00DF" }, + { "`a", "00E0" }, + { "'a", "00E1" }, + { "^a", "00E2" }, + { "~a", "00E3" }, + { ":a", "00E4" }, + { "oa", "00E5" }, + { "ae", "00E6" }, + { ",c", "00E7" }, + { "`e", "00E8" }, + { "'e", "00E9" }, + { "^e", "00EA" }, + { ":e", "00EB" }, + { "`i", "00EC" }, + { "'i", "00ED" }, + { "^i", "00EE" }, + { ":i", "00EF" }, + { "Sd", "00F0" }, + { "~n", "00F1" }, + { "`o", "00F2" }, + { "'o", "00F3" }, + { "^o", "00F4" }, + { "~o", "00F5" }, + { ":o", "00F6" }, + { "di", "00F7" }, + { "tdi", "00F7" }, + { "/o", "00F8" }, + { "`u", "00F9" }, + { "'u", "00FA" }, + { "^u", "00FB" }, + { ":u", "00FC" }, + { "'y", "00FD" }, + { "Tp", "00FE" }, + { ":y", "00FF" }, + { "'C", "0106" }, + { "'c", "0107" }, + { ".i", "0131" }, + { "IJ", "0132" }, + { "ij", "0133" }, + { "/L", "0141" }, + { "/l", "0142" }, + { "OE", "0152" }, + { "oe", "0153" }, + { "vS", "0160" }, + { "vs", "0161" }, + { ":Y", "0178" }, + { "vZ", "017D" }, + { "vz", "017E" }, + { "Fn", "0192" }, + { ".j", "0237" }, + { "ah", "02C7" }, + { "ab", "02D8" }, + { "a.", "02D9" }, + { "ao", "02DA" }, + { "ho", "02DB" }, + { "a\"", "02DD" }, + { "*A", "0391" }, + { "*B", "0392" }, + { "*G", "0393" }, + { "*D", "0394" }, + { "*E", "0395" }, + { "*Z", "0396" }, + { "*Y", "0397" }, + { "*H", "0398" }, + { "*I", "0399" }, + { "*K", "039A" }, + { "*L", "039B" }, + { "*M", "039C" }, + { "*N", "039D" }, + { "*C", "039E" }, + { "*O", "039F" }, + { "*P", "03A0" }, + { "*R", "03A1" }, + { "*S", "03A3" }, + { "*T", "03A4" }, + { "*U", "03A5" }, + { "*F", "03A6" }, + { "*X", "03A7" }, + { "*Q", "03A8" }, + { "*W", "03A9" }, + { "*a", "03B1" }, + { "*b", "03B2" }, + { "*g", "03B3" }, + { "*d", "03B4" }, + { "*e", "03B5" }, + { "*z", "03B6" }, + { "*y", "03B7" }, + { "*h", "03B8" }, + { "*i", "03B9" }, + { "*k", "03BA" }, + { "*l", "03BB" }, + { "*m", "03BC" }, + { "*n", "03BD" }, + { "*c", "03BE" }, + { "*o", "03BF" }, + { "*p", "03C0" }, + { "*r", "03C1" }, + { "ts", "03C2" }, + { "*s", "03C3" }, + { "*t", "03C4" }, + { "*u", "03C5" }, + // the curly phi variant + { "+f", "03C6" }, + { "*x", "03C7" }, + { "*q", "03C8" }, + { "*w", "03C9" }, + { "+h", "03D1" }, + // the stroked phi variant + { "*f", "03D5" }, + { "+p", "03D6" }, + { "+e", "03F5" }, + // '-' and 'hy' denote a HYPHEN, usually a glyph with a smaller width than + // the MINUS sign. Users who are viewing broken man pages that assume + // that '-' denotes a U+002D character can either fix the broken man pages + // or apply the workaround described in the PROBLEMS file. + { "-", "2010" }, + { "hy", "2010" }, + { "en", "2013" }, + { "em", "2014" }, + { "`", "2018" }, + { "oq", "2018" }, + { "'", "2019" }, + { "cq", "2019" }, + { "bq", "201A" }, + { "lq", "201C" }, + { "rq", "201D" }, + { "Bq", "201E" }, + { "dg", "2020" }, + { "dd", "2021" }, + { "bu", "2022" }, + { "%0", "2030" }, + { "fm", "2032" }, + { "sd", "2033" }, + { "fo", "2039" }, + { "fc", "203A" }, + { "rn", "203E" }, + { "f/", "2044" }, + { "eu", "20AC" }, + { "Eu", "20AC" }, + { "-h", "210F" }, + { "hbar", "210F" }, + { "Im", "2111" }, + { "wp", "2118" }, + { "Re", "211C" }, + { "tm", "2122" }, + { "Ah", "2135" }, + { "18", "215B" }, + { "38", "215C" }, + { "58", "215D" }, + { "78", "215E" }, + { "<-", "2190" }, + { "ua", "2191" }, + { "->", "2192" }, + { "da", "2193" }, + { "<>", "2194" }, + { "va", "2195" }, + { "CR", "21B5" }, + { "lA", "21D0" }, + { "uA", "21D1" }, + { "rA", "21D2" }, + { "dA", "21D3" }, + { "hA", "21D4" }, + { "vA", "21D5" }, + { "fa", "2200" }, + { "pd", "2202" }, + { "te", "2203" }, + { "es", "2205" }, + { "gr", "2207" }, + { "mo", "2208" }, + { "nm", "2209" }, + { "st", "220B" }, + { "product", "220F" }, + { "coproduct", "2210" }, + { "sum", "2211" }, + // 'mi' and '\-' represent a MINUS sign. But it is used in many man pages + // to denote the U+002D character that introduces a command-line option. + // For devices that support copy&paste, such as devhtml and devutf8, the + // user can apply the workaround described in the PROBLEMS file. + { "\\-", "2212" }, + { "mi", "2212" }, + { "-+", "2213" }, + { "**", "2217" }, + { "sqrt", "221A" }, + { "sr", "221A" }, + { "pt", "221D" }, + { "if", "221E" }, + { "/_", "2220" }, + { "AN", "2227" }, + { "OR", "2228" }, + { "ca", "2229" }, + { "cu", "222A" }, + { "is", "222B" }, + { "integral", "222B" }, + { "tf", "2234" }, + { "3d", "2234" }, + { "ap", "223C" }, + { "|=", "2243" }, + { "=~", "2245" }, + { "~~", "2248" }, + { "~=", "2248" }, + { "!=", "2260" }, + { "==", "2261" }, + { "ne", "2262" }, + { "<=", "2264" }, + { ">=", "2265" }, + { "<<", "226A" }, + { ">>", "226B" }, + { "sb", "2282" }, + { "sp", "2283" }, + { "nb", "2284" }, + { "nc", "2285" }, + { "ib", "2286" }, + { "ip", "2287" }, + { "c+", "2295" }, + { "c*", "2297" }, + { "pp", "22A5" }, + { "md", "22C5" }, + { "lc", "2308" }, + { "rc", "2309" }, + { "lf", "230A" }, + { "rf", "230B" }, + { "parenlefttp", "239B" }, + { "parenleftex", "239C" }, + { "parenleftbt", "239D" }, + { "parenrighttp", "239E" }, + { "parenrightex", "239F" }, + { "parenrightbt", "23A0" }, + { "bracketlefttp", "23A1" }, + { "bracketleftex", "23A2" }, + { "bracketleftbt", "23A3" }, + { "bracketrighttp", "23A4" }, + { "bracketrightex", "23A5" }, + { "bracketrightbt", "23A6" }, + { "lt", "23A7" }, + { "bracelefttp", "23A7" }, + { "lk", "23A8" }, + { "braceleftmid", "23A8" }, + { "lb", "23A9" }, + { "braceleftbt", "23A9" }, + { "bv", "23AA" }, + { "braceex", "23AA" }, + { "braceleftex", "23AA" }, + { "bracerightex", "23AA" }, + { "rt", "23AB" }, + { "bracerighttp", "23AB" }, + { "rk", "23AC" }, + { "bracerightmid", "23AC" }, + { "rb", "23AD" }, + { "bracerightbt", "23AD" }, + { "an", "23AF" }, + { "br", "2502" }, + { "sq", "25A1" }, + { "lz", "25CA" }, + { "ci", "25CB" }, + { "lh", "261C" }, + { "rh", "261E" }, + { "SP", "2660" }, + { "CL", "2663" }, + { "HE", "2665" }, + { "DI", "2666" }, + { "OK", "2713" }, + // The 'left angle bracket' and 'right angle bracket' could be mapped to + // either U+2329,U+232A or U+3008,U+3009 or U+27E8,U+27E9. But the first + // and second possibility are double-width characters (see Unicode's + // 'DerivedEastAsianWidth.txt' file) and are therefore not suitable for + // general use, whereas the third possibility is single-width. + // + // The devhtml device overrides this mapping, because + // + // http://www.w3.org/TR/html401/sgml/entities.html + // + // says that in HTML, '⟨' and '⟩' are U+2329,U+232A, + // respectively. + { "la", "27E8" }, + { "ra", "27E9" }, +}; + +// global constructor +static struct glyph_to_unicode_init { + glyph_to_unicode_init(); +} _glyph_to_unicode_init; + +glyph_to_unicode_init::glyph_to_unicode_init() +{ + for (unsigned int i = 0; + i < sizeof(glyph_to_unicode_list)/sizeof(glyph_to_unicode_list[0]); + i++) { + glyph_to_unicode *gtu = new glyph_to_unicode[1]; + gtu->value = (char *)glyph_to_unicode_list[i].value; + glyph_to_unicode_table.define(glyph_to_unicode_list[i].key, gtu); + } +} + +const char *glyph_name_to_unicode(const char *s) +{ + glyph_to_unicode *result = glyph_to_unicode_table.lookup(s); + return result ? result->value : 0; +} diff --git a/src/libs/libgroff/htmlhint.cpp b/src/libs/libgroff/htmlhint.cpp new file mode 100644 index 0000000..8ebb84e --- /dev/null +++ b/src/libs/libgroff/htmlhint.cpp @@ -0,0 +1,60 @@ +/* Copyright (C) 2000-2020 Free Software Foundation, Inc. + Written by Gaius Mulley (gaius@glam.ac.uk) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#include <stddef.h> +#include <stdlib.h> + +#include "nonposix.h" +#include "stringclass.h" +#include "html-strings.h" + +/* + * This file contains a very simple set of routines which might + * be shared by preprocessors. It allows a preprocessor to indicate + * when an inline image should be created. + * This string is intercepted by pre-grohtml and substituted for + * the image name and suppression escapes. + * + * pre-html runs troff twice, once with -Thtml (or -Txhtml) and once + * with -Tps. 'troff -Thtml' (and 'troff -Txhtml') emits a + * <src='image'.png> tag and the postscript device driver works out + * the min/max limits of the graphic region. These region limits are + * read by pre-html and an image is generated via + * + * troff -Tps -> gs -> png + */ + +/* + * html_begin_suppress - emit a start of image tag which will be seen + * by pre-html. + */ +void html_begin_suppress() +{ + put_string(HTML_IMAGE_INLINE_BEGIN, stdout); +} + +/* + * html_end_suppress - emit an end of image tag which will be seen + * by pre-html. + */ +void html_end_suppress() +{ + put_string(HTML_IMAGE_INLINE_END, stdout); +} diff --git a/src/libs/libgroff/hypot.cpp b/src/libs/libgroff/hypot.cpp new file mode 100644 index 0000000..fa0977d --- /dev/null +++ b/src/libs/libgroff/hypot.cpp @@ -0,0 +1,34 @@ +/* Copyright (C) 2005-2020 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <math.h> + +double groff_hypot(double x, double y) +{ + double result = hypot(x, y); + +#ifdef __INTERIX + /* hypot() on Interix is broken */ + if (isnan(result) && !isnan(x) && !isnan(y)) + return 0.0; +#endif + + return result; +} diff --git a/src/libs/libgroff/iftoa.c b/src/libs/libgroff/iftoa.c new file mode 100644 index 0000000..87aec58 --- /dev/null +++ b/src/libs/libgroff/iftoa.c @@ -0,0 +1,76 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +const char *if_to_a(int i, int decimal_point) +{ + static char buf[INT_DIGITS + 3]; // INT_DIGITS + '-', '.', '\0' + char *p = buf + INT_DIGITS + 2; + int point = 0; + buf[INT_DIGITS + 2] = '\0'; + /* assert(decimal_point <= INT_DIGITS); */ + if (i >= 0) { + do { + *--p = '0' + (i % 10); + i /= 10; + if (++point == decimal_point) + *--p = '.'; + } while (i != 0 || point < decimal_point); + } + else { /* i < 0 */ + do { + *--p = '0' - (i % 10); + i /= 10; + if (++point == decimal_point) + *--p = '.'; + } while (i != 0 || point < decimal_point); + *--p = '-'; + } + if (decimal_point > 0) { + char *q; + /* there must be a dot, so this will terminate */ + for (q = buf + INT_DIGITS + 2; q[-1] == '0'; --q) + ; + if (q[-1] == '.') { + if (q - 1 == p) { + q[-1] = '0'; + q[0] = '\0'; + } + else + q[-1] = '\0'; + } + else + *q = '\0'; + } + return p; +} + +#ifdef __cplusplus +} +#endif + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/invalid.cpp b/src/libs/libgroff/invalid.cpp new file mode 100644 index 0000000..59e4619 --- /dev/null +++ b/src/libs/libgroff/invalid.cpp @@ -0,0 +1,59 @@ +/* Copyright (C) 2000-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +// Table of invalid input characters. + +char invalid_char_table[256]= { +#ifndef IS_EBCDIC_HOST + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +#else + 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +#endif +}; diff --git a/src/libs/libgroff/itoa.c b/src/libs/libgroff/itoa.c new file mode 100644 index 0000000..a573b2c --- /dev/null +++ b/src/libs/libgroff/itoa.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +const char *i_to_a(int i) +{ + /* Room for INT_DIGITS digits, - and '\0' */ + static char buf[INT_DIGITS + 2]; + char *p = buf + INT_DIGITS + 1; /* points to terminating '\0' */ + if (i >= 0) { + do { + *--p = '0' + (i % 10); + i /= 10; + } while (i != 0); + return p; + } + else { /* i < 0 */ + do { + *--p = '0' - (i % 10); + i /= 10; + } while (i != 0); + *--p = '-'; + } + return p; +} + +const char *ui_to_a(unsigned int i) +{ + /* Room for UINT_DIGITS digits and '\0' */ + static char buf[UINT_DIGITS + 1]; + char *p = buf + UINT_DIGITS; /* points to terminating '\0' */ + do { + *--p = '0' + (i % 10); + i /= 10; + } while (i != 0); + return p; +} + +#ifdef __cplusplus +} +#endif + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/lf.cpp b/src/libs/libgroff/lf.cpp new file mode 100644 index 0000000..9c255fb --- /dev/null +++ b/src/libs/libgroff/lf.cpp @@ -0,0 +1,78 @@ +// -*- C++ -*- +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" +#include "cset.h" +#include "stringclass.h" +#include "lf.h" + +#include <ctype.h> + +extern void change_filename(const char *); +extern void change_lineno(int); + +int interpret_lf_args(const char *p) +{ + while (*p == ' ') + p++; + if (!csdigit(*p)) + return 0; + int ln = 0; + do { + ln *= 10; + ln += *p++ - '0'; + } while (csdigit(*p)); + if (*p != ' ' && *p != '\n' && *p != '\0') + return 0; + while (*p == ' ') + p++; + if (*p == '\0' || *p == '\n') { + change_lineno(ln); + return 1; + } + const char *q; + for (q = p; + *q != '\0' && *q != ' ' && *q != '\n' && *q != '\\'; + q++) + ; + string tem(p, q - p); + while (*q == ' ') + q++; + if (*q != '\n' && *q != '\0') + return 0; + tem += '\0'; + change_filename(tem.contents()); + change_lineno(ln); + return 1; +} + +#if defined(__MSDOS__) || (defined(_WIN32) && !defined(__CYGWIN__)) +void normalize_for_lf (string &fn) +{ + int fnlen = fn.length(); + for (int i = 0; i < fnlen; i++) { + if (fn[i] == '\\') + fn[i] = '/'; + } +} +#else +void normalize_for_lf (string &) +{ +} +#endif diff --git a/src/libs/libgroff/libgroff.am b/src/libs/libgroff/libgroff.am new file mode 100644 index 0000000..be6d9e2 --- /dev/null +++ b/src/libs/libgroff/libgroff.am @@ -0,0 +1,182 @@ +# Copyright (C) 2014-2020 Free Software Foundation, Inc. +# +# 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 3 of the License, or (at your +# option) any later version. +# +# 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 +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +libgroff_srcdir = $(top_srcdir)/src/libs/libgroff +noinst_LIBRARIES += libgroff.a +libgroff_a_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + -D__GETOPT_PREFIX=groff_ \ + -DENABLE_RELOCATABLE=1 \ + -DLIBDIR=\"$(libdir)\" + +# Build from OBJS +libgroff_a_SOURCES = \ + src/libs/libgroff/assert.cpp \ + src/libs/libgroff/change_lf.cpp \ + src/libs/libgroff/cmap.cpp \ + src/libs/libgroff/color.cpp \ + src/libs/libgroff/cset.cpp\ + src/libs/libgroff/curtime.cpp \ + src/libs/libgroff/device.cpp \ + src/libs/libgroff/errarg.cpp \ + src/libs/libgroff/error.cpp \ + src/libs/libgroff/fatal.cpp \ + src/libs/libgroff/filename.cpp \ + src/libs/libgroff/font.cpp \ + src/libs/libgroff/fontfile.cpp \ + src/libs/libgroff/geometry.cpp \ + src/libs/libgroff/getopt.c \ + src/libs/libgroff/getopt1.c \ + src/libs/libgroff/glyphuni.cpp \ + src/libs/libgroff/htmlhint.cpp \ + src/libs/libgroff/hypot.cpp \ + src/libs/libgroff/iftoa.c \ + src/libs/libgroff/invalid.cpp \ + src/libs/libgroff/itoa.c \ + src/libs/libgroff/lf.cpp \ + src/libs/libgroff/lineno.cpp \ + src/libs/libgroff/localcharset.c \ + src/libs/libgroff/macropath.cpp \ + src/libs/libgroff/matherr.c \ + src/libs/libgroff/maxfilename.cpp \ + src/libs/libgroff/maxpathname.cpp \ + src/libs/libgroff/mksdir.cpp \ + src/libs/libgroff/nametoindex.cpp \ + src/libs/libgroff/paper.cpp \ + src/libs/libgroff/prime.cpp \ + src/libs/libgroff/progname.c \ + src/libs/libgroff/ptable.cpp \ + src/libs/libgroff/quotearg.c \ + src/libs/libgroff/relocate.cpp \ + src/libs/libgroff/searchpath.cpp \ + src/libs/libgroff/spawnvp.c \ + src/libs/libgroff/string.cpp \ + src/libs/libgroff/strsave.cpp \ + src/libs/libgroff/symbol.cpp \ + src/libs/libgroff/tmpfile.cpp \ + src/libs/libgroff/tmpname.cpp \ + src/libs/libgroff/unicode.cpp \ + src/libs/libgroff/uniglyph.cpp \ + src/libs/libgroff/uniuni.cpp \ + src/libs/libgroff/relocatable.h +if USE_GROFF_ALLOCATOR +libgroff_a_SOURCES += \ + src/libs/libgroff/new.cpp +endif +nodist_libgroff_a_SOURCES = src/libs/libgroff/version.cpp + +# TODO: these .c files could be removed (use gnulib instead). +EXTRA_DIST += \ + src/libs/libgroff/mkstemp.cpp \ + src/libs/libgroff/fmod.c \ + src/libs/libgroff/getcwd.c \ + src/libs/libgroff/putenv.c \ + src/libs/libgroff/strcasecmp.c \ + src/libs/libgroff/strerror.c \ + src/libs/libgroff/strncasecmp.c \ + src/libs/libgroff/strtol.c \ + src/libs/libgroff/config.charset \ + src/libs/libgroff/ref-add.sin \ + src/libs/libgroff/ref-del.sin \ + src/libs/libgroff/make-uniuni + +CLEANFILES += \ + src/libs/libgroff/version.cpp \ + charset.alias \ + ref-add.sed \ + ref-del.sed + +# .o files have a 'libgroff_a-' prefix because we set +# libgroff_a_CPPFLAGS. +src/libs/libgroff/libgroff_a-device.$(OBJEXT): defs.h +src/libs/libgroff/libgroff_a-fontfile.$(OBJEXT): defs.h +src/libs/libgroff/libgroff_a-macropath.$(OBJEXT): defs.h +src/libs/libgroff/libgroff_a-relocate.$(OBJEXT): defs.h + +src/libs/libgroff/version.cpp: $(top_srcdir)/.version + $(AM_V_at)printf 'const char *version_string = "%s.%s";\n' \ + $(MAJOR_VERSION) $(MINOR_VERSION) > $@.tmp + $(AM_V_at)printf 'const char *revision_string = "%s";\n' \ + $(REVISION) >> $@.tmp + $(AM_V_at)printf \ + 'extern "C" {\nconst char *Version_string = "%s";\n}\n' \ + $(VERSION) >> $@.tmp + $(AM_V_GEN)mv $@.tmp $@ + +# Data for localcharset.c. Taken from libiconv/libcharset. + +LIBGROFF_PACKAGE = groff + +all: charset.alias ref-add.sed ref-del.sed + +charset.alias: $(libgroff_srcdir)/config.charset + $(AM_V_GEN)$(SHELL) $(libgroff_srcdir)/config.charset \ + '$(HOST)' > t-$@ \ + && mv t-$@ $@ + +ref-add.sed: $(libgroff_srcdir)/ref-add.sin + $(AM_V_GEN)sed -e '/^#/d' \ + -e 's/@''PACKAGE''@/$(LIBGROFF_PACKAGE)/g' \ + $(libgroff_srcdir)/ref-add.sin > t-$@ \ + && mv t-$@ $@ + +ref-del.sed: $(libgroff_srcdir)/ref-del.sin + $(AM_V_GEN)sed -e '/^#/d' \ + -e 's/@''PACKAGE''@/$(LIBGROFF_PACKAGE)/g' \ + $(libgroff_srcdir)/ref-del.sin > t-$@ \ + && mv t-$@ $@ + +install-data-local: install_charset_data +install_charset_data: + -test $(GLIBC21) != no || $(mkinstalldirs) $(DESTDIR)$(libdir) + if test -f $(DESTDIR)$(libdir)/charset.alias; then \ + sed -f ref-add.sed $(DESTDIR)$(libdir)/charset.alias \ + > $(DESTDIR)$(libdir)/t-charset.alias; \ + $(INSTALL_DATA) $(DESTDIR)$(libdir)/t-charset.alias \ + $(DESTDIR)$(libdir)/charset.alias; \ + rm -f $(DESTDIR)$(libdir)/t-charset.alias; \ + else \ + if test $(GLIBC21) = no; then \ + sed -f ref-add.sed charset.alias \ + > $(DESTDIR)$(libdir)/t-charset.alias; \ + $(INSTALL_DATA) $(DESTDIR)$(libdir)/t-charset.alias \ + $(DESTDIR)$(libdir)/charset.alias; \ + rm -f $(DESTDIR)$(libdir)/t-charset.alias; \ + fi; \ + fi + +uninstall-local: uninstall_charset_data +uninstall_charset_data: + -if test -f $(DESTDIR)$(libdir)/charset.alias; then \ + sed -f ref-del.sed $(DESTDIR)$(libdir)/charset.alias \ + > $(DESTDIR)$(libdir)/t-charset.alias; \ + if grep '^# Packages using this file: $$' \ + $(DESTDIR)$(libdir)/t-charset.alias > /dev/null; then \ + rm -f $(DESTDIR)$(libdir)/charset.alias; \ + else \ + $(INSTALL_DATA) $(DESTDIR)$(libdir)/t-charset.alias \ + $(DESTDIR)$(libdir)/charset.alias; \ + fi; \ + rm -f $(DESTDIR)$(libdir)/t-charset.alias; \ + fi + + +# Local Variables: +# mode: makefile-automake +# fill-column: 72 +# End: +# vim: set autoindent filetype=automake textwidth=72: diff --git a/src/libs/libgroff/lineno.cpp b/src/libs/libgroff/lineno.cpp new file mode 100644 index 0000000..6e356c7 --- /dev/null +++ b/src/libs/libgroff/lineno.cpp @@ -0,0 +1,20 @@ +/* Copyright (C) 2014-2020 Free Software Foundation, Inc. + +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 2 of the License, or +(at your option) any later version. + +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 +for more details. + +The GNU General Public License version 2 (GPL2) is available in the +internet at <http://www.gnu.org/licenses/gpl-2.0.txt>. */ + +// This global stores the line number of the input file being +// processed by troff, an output driver, or other program. +int current_lineno = 0; diff --git a/src/libs/libgroff/localcharset.c b/src/libs/libgroff/localcharset.c new file mode 100644 index 0000000..1bc07a4 --- /dev/null +++ b/src/libs/libgroff/localcharset.c @@ -0,0 +1,579 @@ +/* Determine a canonical name for the current locale's character encoding. + + Copyright (C) 2000-2020 Free Software Foundation, Inc. + + This program 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 2, or (at your option) + any later version. + + This program 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 for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>. */ + +#include <config.h> + +/* Specification. */ +#include "localcharset.h" + +#include <fcntl.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#if defined __APPLE__ && defined __MACH__ && HAVE_LANGINFO_CODESET +# define DARWIN7 /* Darwin 7 or newer, i.e. Mac OS X 10.3 or newer */ +#endif + +#if defined _WIN32 || defined __WIN32__ +# define WINDOWS_NATIVE +# include <locale.h> +#endif + +#if defined __EMX__ +/* Assume EMX program runs on OS/2, even if compiled under DOS. */ +# ifndef OS2 +# define OS2 +# endif +#endif + +#if !defined WINDOWS_NATIVE +# include <unistd.h> +# if HAVE_LANGINFO_CODESET +# include <langinfo.h> +# else +# if 0 /* see comment below */ +# include <locale.h> +# endif +# endif +# ifdef __CYGWIN__ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# endif +#elif defined WINDOWS_NATIVE +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +#endif +#if defined OS2 +# define INCL_DOS +# include <os2.h> +#endif + +/* For MB_CUR_MAX_L */ +#if defined DARWIN7 +# include <xlocale.h> +#endif + +#if ENABLE_RELOCATABLE +# include "relocatable.h" +#else +# define relocate(pathname) (pathname) +#endif + +/* Get LIBDIR. */ +#ifndef LIBDIR +# include "configmake.h" +#endif + +/* Define O_NOFOLLOW to 0 on platforms where it does not exist. */ +#ifndef O_NOFOLLOW +# define O_NOFOLLOW 0 +#endif + +#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ + /* Native Windows, Cygwin, OS/2, DOS */ +# define ISSLASH(C) ((C) == '/' || (C) == '\\') +#endif + +#ifndef DIRECTORY_SEPARATOR +# define DIRECTORY_SEPARATOR '/' +#endif + +#ifndef ISSLASH +# define ISSLASH(C) ((C) == DIRECTORY_SEPARATOR) +#endif + +#if HAVE_DECL_GETC_UNLOCKED +# undef getc +# define getc getc_unlocked +#endif + +/* The following static variable is declared 'volatile' to avoid a + possible multithread problem in the function get_charset_aliases. If we + are running in a threaded environment, and if two threads initialize + 'charset_aliases' simultaneously, both will produce the same value, + and everything will be ok if the two assignments to 'charset_aliases' + are atomic. But I don't know what will happen if the two assignments mix. */ +#if __STDC__ != 1 +# define volatile /* empty */ +#endif +/* Pointer to the contents of the charset.alias file, if it has already been + read, else NULL. Its format is: + ALIAS_1 '\0' CANONICAL_1 '\0' ... ALIAS_n '\0' CANONICAL_n '\0' '\0' */ +static const char * volatile charset_aliases; + +/* Return a pointer to the contents of the charset.alias file. */ +static const char * +get_charset_aliases (void) +{ + const char *cp; + + cp = charset_aliases; + if (cp == NULL) + { +#if !(defined DARWIN7 || defined VMS || defined WINDOWS_NATIVE || defined __CYGWIN__) + const char *dir; + const char *base = "charset.alias"; + char *file_name; + + /* Make it possible to override the charset.alias location. This is + necessary for running the testsuite before "make install". */ + dir = getenv ("CHARSETALIASDIR"); + if (dir == NULL || dir[0] == '\0') + dir = relocate (LIBDIR); + + /* Concatenate dir and base into freshly allocated file_name. */ + { + size_t dir_len = strlen (dir); + size_t base_len = strlen (base); + int add_slash = (dir_len > 0 && !ISSLASH (dir[dir_len - 1])); + file_name = (char *) malloc (dir_len + add_slash + base_len + 1); + if (file_name != NULL) + { + memcpy (file_name, dir, dir_len); + if (add_slash) + file_name[dir_len] = DIRECTORY_SEPARATOR; + memcpy (file_name + dir_len + add_slash, base, base_len + 1); + } + } + + if (file_name == NULL) + /* Out of memory. Treat the file as empty. */ + cp = ""; + else + { + int fd; + + /* Open the file. Reject symbolic links on platforms that support + O_NOFOLLOW. This is a security feature. Without it, an attacker + could retrieve parts of the contents (namely, the tail of the + first line that starts with "* ") of an arbitrary file by placing + a symbolic link to that file under the name "charset.alias" in + some writable directory and defining the environment variable + CHARSETALIASDIR to point to that directory. */ + fd = open (file_name, + O_RDONLY | (HAVE_WORKING_O_NOFOLLOW ? O_NOFOLLOW : 0)); + if (fd < 0) + /* File not found. Treat it as empty. */ + cp = ""; + else + { + FILE *fp; + + fp = fdopen (fd, "r"); + if (fp == NULL) + { + /* Out of memory. Treat the file as empty. */ + close (fd); + cp = ""; + } + else + { + /* Parse the file's contents. */ + char *res_ptr = NULL; + size_t res_size = 0; + + for (;;) + { + int c; + char buf1[50+1]; + char buf2[50+1]; + size_t l1, l2; + char *old_res_ptr; + + c = getc (fp); + if (c == EOF) + break; + if (c == '\n' || c == ' ' || c == '\t') + continue; + if (c == '#') + { + /* Skip comment, to end of line. */ + do + c = getc (fp); + while (!(c == EOF || c == '\n')); + if (c == EOF) + break; + continue; + } + ungetc (c, fp); + if (fscanf (fp, "%50s %50s", buf1, buf2) < 2) + break; + l1 = strlen (buf1); + l2 = strlen (buf2); + old_res_ptr = res_ptr; + if (res_size == 0) + { + res_size = l1 + 1 + l2 + 1; + res_ptr = (char *) malloc (res_size + 1); + } + else + { + res_size += l1 + 1 + l2 + 1; + res_ptr = (char *) realloc (res_ptr, res_size + 1); + } + if (res_ptr == NULL) + { + /* Out of memory. */ + res_size = 0; + free (old_res_ptr); + break; + } + strcpy (res_ptr + res_size - (l2 + 1) - (l1 + 1), buf1); + strcpy (res_ptr + res_size - (l2 + 1), buf2); + } + fclose (fp); + if (res_size == 0) + cp = ""; + else + { + *(res_ptr + res_size) = '\0'; + cp = res_ptr; + } + } + } + + free (file_name); + } + +#else + +# if defined DARWIN7 + /* To avoid the trouble of installing a file that is shared by many + GNU packages -- many packaging systems have problems with this --, + simply inline the aliases here. */ + cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" + "ISO8859-2" "\0" "ISO-8859-2" "\0" + "ISO8859-4" "\0" "ISO-8859-4" "\0" + "ISO8859-5" "\0" "ISO-8859-5" "\0" + "ISO8859-7" "\0" "ISO-8859-7" "\0" + "ISO8859-9" "\0" "ISO-8859-9" "\0" + "ISO8859-13" "\0" "ISO-8859-13" "\0" + "ISO8859-15" "\0" "ISO-8859-15" "\0" + "KOI8-R" "\0" "KOI8-R" "\0" + "KOI8-U" "\0" "KOI8-U" "\0" + "CP866" "\0" "CP866" "\0" + "CP949" "\0" "CP949" "\0" + "CP1131" "\0" "CP1131" "\0" + "CP1251" "\0" "CP1251" "\0" + "eucCN" "\0" "GB2312" "\0" + "GB2312" "\0" "GB2312" "\0" + "eucJP" "\0" "EUC-JP" "\0" + "eucKR" "\0" "EUC-KR" "\0" + "Big5" "\0" "BIG5" "\0" + "Big5HKSCS" "\0" "BIG5-HKSCS" "\0" + "GBK" "\0" "GBK" "\0" + "GB18030" "\0" "GB18030" "\0" + "SJIS" "\0" "SHIFT_JIS" "\0" + "ARMSCII-8" "\0" "ARMSCII-8" "\0" + "PT154" "\0" "PT154" "\0" + /*"ISCII-DEV" "\0" "?" "\0"*/ + "*" "\0" "UTF-8" "\0"; +# endif + +# if defined VMS + /* To avoid the troubles of an extra file charset.alias_vms in the + sources of many GNU packages, simply inline the aliases here. */ + /* The list of encodings is taken from the OpenVMS 7.3-1 documentation + "Compaq C Run-Time Library Reference Manual for OpenVMS systems" + section 10.7 "Handling Different Character Sets". */ + cp = "ISO8859-1" "\0" "ISO-8859-1" "\0" + "ISO8859-2" "\0" "ISO-8859-2" "\0" + "ISO8859-5" "\0" "ISO-8859-5" "\0" + "ISO8859-7" "\0" "ISO-8859-7" "\0" + "ISO8859-8" "\0" "ISO-8859-8" "\0" + "ISO8859-9" "\0" "ISO-8859-9" "\0" + /* Japanese */ + "eucJP" "\0" "EUC-JP" "\0" + "SJIS" "\0" "SHIFT_JIS" "\0" + "DECKANJI" "\0" "DEC-KANJI" "\0" + "SDECKANJI" "\0" "EUC-JP" "\0" + /* Chinese */ + "eucTW" "\0" "EUC-TW" "\0" + "DECHANYU" "\0" "DEC-HANYU" "\0" + "DECHANZI" "\0" "GB2312" "\0" + /* Korean */ + "DECKOREAN" "\0" "EUC-KR" "\0"; +# endif + +# if defined WINDOWS_NATIVE || defined __CYGWIN__ + /* To avoid the troubles of installing a separate file in the same + directory as the DLL and of retrieving the DLL's directory at + runtime, simply inline the aliases here. */ + + cp = "CP936" "\0" "GBK" "\0" + "CP1361" "\0" "JOHAB" "\0" + "CP20127" "\0" "ASCII" "\0" + "CP20866" "\0" "KOI8-R" "\0" + "CP20936" "\0" "GB2312" "\0" + "CP21866" "\0" "KOI8-RU" "\0" + "CP28591" "\0" "ISO-8859-1" "\0" + "CP28592" "\0" "ISO-8859-2" "\0" + "CP28593" "\0" "ISO-8859-3" "\0" + "CP28594" "\0" "ISO-8859-4" "\0" + "CP28595" "\0" "ISO-8859-5" "\0" + "CP28596" "\0" "ISO-8859-6" "\0" + "CP28597" "\0" "ISO-8859-7" "\0" + "CP28598" "\0" "ISO-8859-8" "\0" + "CP28599" "\0" "ISO-8859-9" "\0" + "CP28605" "\0" "ISO-8859-15" "\0" + "CP38598" "\0" "ISO-8859-8" "\0" + "CP51932" "\0" "EUC-JP" "\0" + "CP51936" "\0" "GB2312" "\0" + "CP51949" "\0" "EUC-KR" "\0" + "CP51950" "\0" "EUC-TW" "\0" + "CP54936" "\0" "GB18030" "\0" + "CP65001" "\0" "UTF-8" "\0"; +# endif +#endif + + charset_aliases = cp; + } + + return cp; +} + +/* Determine the current locale's character encoding, and canonicalize it + into one of the canonical names listed in config.charset. + The result must not be freed; it is statically allocated. + If the canonical name cannot be determined, the result is a non-canonical + name. */ + +#ifdef STATIC +STATIC +#endif +const char * +locale_charset (void) +{ + const char *codeset; + const char *aliases; + +#if !(defined WINDOWS_NATIVE || defined OS2) + +# if HAVE_LANGINFO_CODESET + + /* Most systems support nl_langinfo (CODESET) nowadays. */ + codeset = nl_langinfo (CODESET); + +# ifdef __CYGWIN__ + /* Cygwin < 1.7 does not have locales. nl_langinfo (CODESET) always + returns "US-ASCII". Return the suffix of the locale name from the + environment variables (if present) or the codepage as a number. */ + if (codeset != NULL && strcmp (codeset, "US-ASCII") == 0) + { + const char *locale; + static char buf[2 + 10 + 1]; + + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + if (locale != NULL && locale[0] != '\0') + { + /* If the locale name contains an encoding after the dot, return + it. */ + const char *dot = strchr (locale, '.'); + + if (dot != NULL) + { + const char *modifier; + + dot++; + /* Look for the possible @... trailer and remove it, if any. */ + modifier = strchr (dot, '@'); + if (modifier == NULL) + return dot; + if (modifier - dot < sizeof (buf)) + { + memcpy (buf, dot, modifier - dot); + buf [modifier - dot] = '\0'; + return buf; + } + } + } + + /* The Windows API has a function returning the locale's codepage as a + number: GetACP(). This encoding is used by Cygwin, unless the user + has set the environment variable CYGWIN=codepage:oem (which very few + people do). + Output directed to console windows needs to be converted (to + GetOEMCP() if the console is using a raster font, or to + GetConsoleOutputCP() if it is using a TrueType font). Cygwin does + this conversion transparently (see winsup/cygwin/fhandler_console.cc), + converting to GetConsoleOutputCP(). This leads to correct results, + except when SetConsoleOutputCP has been called and a raster font is + in use. */ + sprintf (buf, "CP%u", GetACP ()); + codeset = buf; + } +# endif + +# else + + /* On old systems which lack it, use setlocale or getenv. */ + const char *locale = NULL; + + /* But most old systems don't have a complete set of locales. Some + (like SunOS 4 or DJGPP) have only the C locale. Therefore we don't + use setlocale here; it would return "C" when it doesn't support the + locale name the user has set. */ +# if 0 + locale = setlocale (LC_CTYPE, NULL); +# endif + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + } + + /* On some old systems, one used to set locale = "iso8859_1". On others, + you set it to "language_COUNTRY.charset". In any case, we resolve it + through the charset.alias file. */ + codeset = locale; + +# endif + +#elif defined WINDOWS_NATIVE + + static char buf[2 + 10 + 1]; + + /* The Windows API has a function returning the locale's codepage as + a number, but the value doesn't change according to what the + 'setlocale' call specified. So we use it as a last resort, in + case the string returned by 'setlocale' doesn't specify the + codepage. */ + char *current_locale = setlocale (LC_ALL, NULL); + char *pdot; + + /* If they set different locales for different categories, + 'setlocale' will return a semi-colon separated list of locale + values. To make sure we use the correct one, we choose LC_CTYPE. */ + if (strchr (current_locale, ';')) + current_locale = setlocale (LC_CTYPE, NULL); + + pdot = strrchr (current_locale, '.'); + if (pdot) + sprintf (buf, "CP%s", pdot + 1); + else + { + /* The Windows API has a function returning the locale's codepage as a + number: GetACP(). + When the output goes to a console window, it needs to be provided in + GetOEMCP() encoding if the console is using a raster font, or in + GetConsoleOutputCP() encoding if it is using a TrueType font. + But in GUI programs and for output sent to files and pipes, GetACP() + encoding is the best bet. */ + sprintf (buf, "CP%u", GetACP ()); + } + codeset = buf; + +#elif defined OS2 + + const char *locale; + static char buf[2 + 10 + 1]; + ULONG cp[3]; + ULONG cplen; + + /* Allow user to override the codeset, as set in the operating system, + with standard language environment variables. */ + locale = getenv ("LC_ALL"); + if (locale == NULL || locale[0] == '\0') + { + locale = getenv ("LC_CTYPE"); + if (locale == NULL || locale[0] == '\0') + locale = getenv ("LANG"); + } + if (locale != NULL && locale[0] != '\0') + { + /* If the locale name contains an encoding after the dot, return it. */ + const char *dot = strchr (locale, '.'); + + if (dot != NULL) + { + const char *modifier; + + dot++; + /* Look for the possible @... trailer and remove it, if any. */ + modifier = strchr (dot, '@'); + if (modifier == NULL) + return dot; + if (modifier - dot < sizeof (buf)) + { + memcpy (buf, dot, modifier - dot); + buf [modifier - dot] = '\0'; + return buf; + } + } + + /* Resolve through the charset.alias file. */ + codeset = locale; + } + else + { + /* OS/2 has a function returning the locale's codepage as a number. */ + if (DosQueryCp (sizeof (cp), cp, &cplen)) + codeset = ""; + else + { + sprintf (buf, "CP%u", cp[0]); + codeset = buf; + } + } + +#endif + + if (codeset == NULL) + /* The canonical name cannot be determined. */ + codeset = ""; + + /* Resolve alias. */ + for (aliases = get_charset_aliases (); + *aliases != '\0'; + aliases += strlen (aliases) + 1, aliases += strlen (aliases) + 1) + if (strcmp (codeset, aliases) == 0 + || (aliases[0] == '*' && aliases[1] == '\0')) + { + codeset = aliases + strlen (aliases) + 1; + break; + } + + /* Don't return an empty string. GNU libc and GNU libiconv interpret + the empty string as denoting "the locale's character encoding", + thus GNU libiconv would call this function a second time. */ + if (codeset[0] == '\0') + codeset = "ASCII"; + +#ifdef DARWIN7 + /* Mac OS X sets MB_CUR_MAX to 1 when LC_ALL=C, and "UTF-8" + (the default codeset) does not work when MB_CUR_MAX is 1. */ + if (strcmp (codeset, "UTF-8") == 0 && MB_CUR_MAX_L (uselocale (NULL)) <= 1) + codeset = "ASCII"; +#endif + + return codeset; +} diff --git a/src/libs/libgroff/macropath.cpp b/src/libs/libgroff/macropath.cpp new file mode 100644 index 0000000..a9c9b35 --- /dev/null +++ b/src/libs/libgroff/macropath.cpp @@ -0,0 +1,29 @@ +// -*- C++ -*- +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" +#include "searchpath.h" +#include "macropath.h" +#include "defs.h" + +#define MACROPATH_ENVVAR "GROFF_TMAC_PATH" + +search_path macro_path(MACROPATH_ENVVAR, MACROPATH, 1, 1); +search_path safer_macro_path(MACROPATH_ENVVAR, MACROPATH, 1, 0); +search_path config_macro_path(MACROPATH_ENVVAR, MACROPATH, 0, 0); diff --git a/src/libs/libgroff/make-uniuni b/src/libs/libgroff/make-uniuni new file mode 100755 index 0000000..386eacd --- /dev/null +++ b/src/libs/libgroff/make-uniuni @@ -0,0 +1,162 @@ +#! /bin/sh +# +# make-uniuni -- script for creating the file uniuni.cpp +# +# Copyright (C) 2005-2020 Free Software Foundation, Inc. +# Written by Werner Lemberg <wl@gnu.org> +# +# 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 3 of the License, or +# (at your option) any later version. +# +# 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 +# for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# +# usage: +# +# make-uniuni <version-string> < UnicodeData.txt > uniuni.cpp +# +# 'UnicodeData.txt' is the central database file from the Unicode standard. +# Unfortunately, it doesn't contain a version number which must be thus +# provided manually as a parameter to the filter. +# +# This program needs a C preprocessor. +# + +CPP=cpp + +prog="$0" + +if test $# -ne 1; then + echo "usage: $0 <version-string> < UnicodeData.txt > uniuni.cpp" + exit 1 +fi + +version_string="$1" + +# Remove ranges and control characters, +# then extract the decomposition field, +# then remove lines without decomposition, +# then remove all compatibility decompositions. +sed -e '/^[^;]*;</d' \ +| sed -e 's/;[^;]*;[^;]*;[^;]*;[^;]*;\([^;]*\);.*$/;\1/' \ +| sed -e '/^[^;]*;$/d' \ +| sed -e '/^[^;]*;</d' > $$1 + +# Prepare input for running cpp. +cat $$1 \ +| sed -e 's/^\([^;]*\);/#define \1 /' \ + -e 's/ / u/g' > $$2 +cat $$1 \ +| sed -e 's/^\([^;]*\);.*$/\1 u\1/' >> $$2 + +# Run C preprocessor to recursively decompose. +$CPP $$2 $$3 + +# Convert it back to original format. +cat $$3 \ +| sed -e '/#/d' \ + -e '/^$/d' \ + -e 's/ \+/ /g' \ + -e 's/ *$//' \ + -e 's/u//g' \ + -e 's/^\([^ ]*\) /\1;/' > $$4 + +# Write preamble. +cat <<END +// -*- C++ -*- +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + Written by Werner Lemberg <wl@gnu.org> + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +// This code has been algorithmically derived from the file +// UnicodeData.txt, version $version_string, available from unicode.org, +// on `date '+%Y-%m-%d'`. + +#include "lib.h" +#include "stringclass.h" +#include "ptable.h" + +#include "unicode.h" + +struct unicode_decompose { + char *value; +}; + +declare_ptable(unicode_decompose) +implement_ptable(unicode_decompose) + +PTABLE(unicode_decompose) unicode_decompose_table; + +// the first digit in the composite string gives the number of composites + +struct S { + const char *key; + const char *value; +} unicode_decompose_list[] = { +END + +# Emit Unicode data. +cat $$4 \ +| sed -e 's/ /_/g' \ + -e 's/\(.*\);\(.*_.*_.*_.*\)$/ { "\1", "4\2" },/' \ + -e 's/\(.*\);\(.*_.*_.*\)$/ { "\1", "3\2" },/' \ + -e 's/\(.*\);\(.*_.*\)$/ { "\1", "2\2" },/' \ + -e 's/\(.*\);\(.*\)$/ { "\1", "1\2" },/' + +# Write postamble. +cat <<END +}; + +// global constructor + +static struct unicode_decompose_init { + unicode_decompose_init(); +} _unicode_decompose_init; + +unicode_decompose_init::unicode_decompose_init() +{ + for (unsigned int i = 0; + i < sizeof(unicode_decompose_list)/sizeof(unicode_decompose_list[0]); + i++) { + unicode_decompose *dec = new unicode_decompose[1]; + dec->value = (char *)unicode_decompose_list[i].value; + unicode_decompose_table.define(unicode_decompose_list[i].key, dec); + } +} + +const char *decompose_unicode(const char *s) +{ + unicode_decompose *result = unicode_decompose_table.lookup(s); + return result ? result->value : 0; +} +END + + +# Remove temporary files. +rm $$1 $$2 $$3 $$4 + +# EOF diff --git a/src/libs/libgroff/matherr.c b/src/libs/libgroff/matherr.c new file mode 100644 index 0000000..a1adbf8 --- /dev/null +++ b/src/libs/libgroff/matherr.c @@ -0,0 +1,48 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <math.h> +#include <errno.h> + +#ifdef HAVE_STRUCT_EXCEPTION +#ifdef TLOSS + +int matherr(exc) +struct exception *exc; +{ + switch (exc->type) { + case SING: + case DOMAIN: + errno = EDOM; + break; + case OVERFLOW: + case UNDERFLOW: + case TLOSS: + case PLOSS: + errno = ERANGE; + break; + } + return 1; +} + +#endif /* TLOSS */ +#endif /* HAVE_STRUCT_EXCEPTION */ diff --git a/src/libs/libgroff/maxfilename.cpp b/src/libs/libgroff/maxfilename.cpp new file mode 100644 index 0000000..5e1defe --- /dev/null +++ b/src/libs/libgroff/maxfilename.cpp @@ -0,0 +1,75 @@ +// -*- C++ -*- +/* Copyright (C) 1992-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* file_name_max(dir) does the same as pathconf(dir, _PC_NAME_MAX) */ + +#include "lib.h" + +#include <sys/types.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* HAVE_UNISTD_H */ + +#ifdef _POSIX_VERSION + +size_t file_name_max(const char *fname) +{ + return pathconf(fname, _PC_NAME_MAX); +} + +#else /* not _POSIX_VERSION */ + +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#else /* not HAVE_DIRENT_H */ +#ifdef HAVE_SYS_DIR_H +#include <sys/dir.h> +#endif /* HAVE_SYS_DIR_H */ +#endif /* not HAVE_DIRENT_H */ + +#ifndef NAME_MAX +#ifdef MAXNAMLEN +#define NAME_MAX MAXNAMLEN +#endif +#endif + +#ifndef NAME_MAX +#ifdef MAXNAMELEN +#define NAME_MAX MAXNAMELEN +#endif +#endif + +#ifndef NAME_MAX +#include <stdio.h> +#ifdef FILENAME_MAX +#define NAME_MAX FILENAME_MAX +#endif +#endif + +#ifndef NAME_MAX +#define NAME_MAX 14 +#endif + +size_t file_name_max(const char *) +{ + return NAME_MAX; +} + +#endif /* not _POSIX_VERSION */ diff --git a/src/libs/libgroff/maxpathname.cpp b/src/libs/libgroff/maxpathname.cpp new file mode 100644 index 0000000..8041eeb --- /dev/null +++ b/src/libs/libgroff/maxpathname.cpp @@ -0,0 +1,70 @@ +// -*- C++ -*- +/* Copyright (C) 2005-2020 Free Software Foundation, Inc. + Written by Werner Lemberg (wl@gnu.org) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* path_name_max(dir) does the same as pathconf(dir, _PC_PATH_MAX) */ + +#include "lib.h" + +#include <sys/types.h> + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif /* HAVE_UNISTD_H */ + +#ifdef _POSIX_VERSION + +size_t path_name_max() +{ + return pathconf("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf("/",_PC_PATH_MAX); +} + +#else /* not _POSIX_VERSION */ + +#include <stdlib.h> + +#ifdef HAVE_DIRENT_H +# include <dirent.h> +#else /* not HAVE_DIRENT_H */ +# ifdef HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif /* HAVE_SYS_DIR_H */ +#endif /* not HAVE_DIRENT_H */ + +#ifndef PATH_MAX +# ifdef MAXPATHLEN +# define PATH_MAX MAXPATHLEN +# else /* !MAXPATHLEN */ +# ifdef MAX_PATH +# define PATH_MAX MAX_PATH +# else /* !MAX_PATH */ +# ifdef _MAX_PATH +# define PATH_MAX _MAX_PATH +# else /* !_MAX_PATH */ +# define PATH_MAX 255 +# endif /* !_MAX_PATH */ +# endif /* !MAX_PATH */ +# endif /* !MAXPATHLEN */ +#endif /* !PATH_MAX */ + +size_t path_name_max() +{ + return PATH_MAX; +} + +#endif /* not _POSIX_VERSION */ diff --git a/src/libs/libgroff/mksdir.cpp b/src/libs/libgroff/mksdir.cpp new file mode 100644 index 0000000..5fa6d28 --- /dev/null +++ b/src/libs/libgroff/mksdir.cpp @@ -0,0 +1,33 @@ +/* Copyright (C) 2001-2020 Free Software Foundation, Inc. + Written by Werner Lemberg (wl@gnu.org) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* This file is heavily based on the file mkstemp.c which is part of the + fileutils package. */ + + +extern int gen_tempname(char *, int = 0); + +/* Generate a unique temporary directory name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Then open the directory and return a fd. */ +int mksdir(char *tmpl) +{ + return gen_tempname(tmpl, 1); +} diff --git a/src/libs/libgroff/mkstemp.cpp b/src/libs/libgroff/mkstemp.cpp new file mode 100644 index 0000000..089a10a --- /dev/null +++ b/src/libs/libgroff/mkstemp.cpp @@ -0,0 +1,33 @@ +/* Copyright (C) 2001-2020 Free Software Foundation, Inc. + Written by Werner Lemberg (wl@gnu.org) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* This file is heavily based on the file mkstemp.c which is part of the + fileutils package. */ + + +extern int gen_tempname(char *, int); + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Then open the file and return a fd. */ +int mkstemp(char *tmpl) +{ + return gen_tempname(tmpl, 0); +} diff --git a/src/libs/libgroff/nametoindex.cpp b/src/libs/libgroff/nametoindex.cpp new file mode 100644 index 0000000..095a432 --- /dev/null +++ b/src/libs/libgroff/nametoindex.cpp @@ -0,0 +1,167 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#include <assert.h> +#include <ctype.h> +#include <stdlib.h> + +#include "errarg.h" +#include "error.h" +#include "font.h" +#include "ptable.h" +#include "itable.h" + +// Every glyphinfo is actually a charinfo. +class charinfo : glyph { +public: + const char *name; // The glyph name, or a null pointer. + friend class character_indexer; +}; + +// PTABLE(charinfo) is a hash table mapping 'const char *' to 'charinfo *'. +declare_ptable(charinfo) +implement_ptable(charinfo) + +// ITABLE(charinfo) is a hash table mapping 'int >= 0' to 'charinfo *'. +declare_itable(charinfo) +implement_itable(charinfo) + +// This class is as a registry storing all named and numbered glyphs known +// so far, and assigns a unique index to each glyph. +class character_indexer { +public: + character_indexer(); + ~character_indexer(); + // --------------------- Lookup or creation of a glyph. + glyph *ascii_char_glyph(unsigned char); + glyph *named_char_glyph(const char *); + glyph *numbered_char_glyph(int); +private: + int next_index; // Number of glyphs already allocated. + PTABLE(charinfo) table; // Table mapping name to glyph. + glyph *ascii_glyph[256]; // Shorthand table for looking up "charNNN" + // glyphs. + ITABLE(charinfo) ntable; // Table mapping number to glyph. + enum { NSMALL = 256 }; + glyph *small_number_glyph[NSMALL]; // Shorthand table for looking up + // numbered glyphs with small numbers. +}; + +character_indexer::character_indexer() +: next_index(0) +{ + int i; + for (i = 0; i < 256; i++) + ascii_glyph[i] = UNDEFINED_GLYPH; + for (i = 0; i < NSMALL; i++) + small_number_glyph[i] = UNDEFINED_GLYPH; +} + +character_indexer::~character_indexer() +{ +} + +glyph *character_indexer::ascii_char_glyph(unsigned char c) +{ + if (ascii_glyph[c] == UNDEFINED_GLYPH) { + char buf[4+3+1]; + memcpy(buf, "char", 4); + strcpy(buf + 4, i_to_a(c)); + charinfo *ci = new charinfo; + ci->index = next_index++; + ci->number = -1; + ci->name = strsave(buf); + ascii_glyph[c] = ci; + } + return ascii_glyph[c]; +} + +inline glyph *character_indexer::named_char_glyph(const char *s) +{ + // Glyphs with name 'charNNN' are only stored in ascii_glyph[], not + // in the table. Therefore treat them specially here. + if (s[0] == 'c' && s[1] == 'h' && s[2] == 'a' && s[3] == 'r') { + char *val; + long n = strtol(s + 4, &val, 10); + if (val != s + 4 && *val == '\0' && n >= 0 && n < 256) + return ascii_char_glyph((unsigned char)n); + } + charinfo *ci = table.lookupassoc(&s); + if (0 == ci) { + ci = new charinfo[1]; + ci->index = next_index++; + ci->number = -1; + ci->name = table.define(s, ci); + } + return ci; +} + +inline glyph *character_indexer::numbered_char_glyph(int n) +{ + if (n >= 0 && n < NSMALL) { + if (small_number_glyph[n] == UNDEFINED_GLYPH) { + charinfo *ci = new charinfo; + ci->index = next_index++; + ci->number = n; + ci->name = 0; + small_number_glyph[n] = ci; + } + return small_number_glyph[n]; + } + charinfo *ci = ntable.lookup(n); + if (0 == ci) { + ci = new charinfo[1]; + ci->index = next_index++; + ci->number = n; + ci->name = 0; + ntable.define(n, ci); + } + return ci; +} + +static character_indexer indexer; + +glyph *number_to_glyph(int n) +{ + return indexer.numbered_char_glyph(n); +} + +// troff overrides this function with its own version. + +glyph *name_to_glyph(const char *s) +{ + assert(s != 0 && s[0] != '\0' && s[0] != ' '); + if (s[1] == '\0') + // \200 and char128 are synonyms + return indexer.ascii_char_glyph(s[0]); + return indexer.named_char_glyph(s); +} + +const char *glyph_to_name(glyph *g) +{ + charinfo *ci = (charinfo *)g; // Every glyph is actually a charinfo. + return ci->name; +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/new.cpp b/src/libs/libgroff/new.cpp new file mode 100644 index 0000000..2af976c --- /dev/null +++ b/src/libs/libgroff/new.cpp @@ -0,0 +1,75 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#include <stddef.h> +#include <stdlib.h> + +#include "posix.h" +#include "nonposix.h" + +extern "C" const char *program_name; + +static void ewrite(const char *s) +{ + write(2, s, strlen(s)); +} + +void *operator new(size_t size) +{ + // Avoid relying on the behaviour of malloc(0). + if (size == 0) + size++; + char *p = (char *)malloc(unsigned(size)); + if (p == 0) { + if (program_name) { + ewrite(program_name); + ewrite(": "); + } + ewrite("out of memory\n"); + _exit(-1); + } + return p; +} + +void operator delete(void *p) throw() +{ + if (p) + free(p); +} + +void operator delete(void *p, + __attribute__((__unused__)) long unsigned int size) +{ + // It's ugly to duplicate the code from delete(void *) above, but if + // we don't, g++ 6.3 can't figure out we're calling through it to + // free(). + // + // In function 'void operator delete(void*, long unsigned int)': + // warning: deleting 'void*' is undefined [-Wdelete-incomplete] + //delete p; + if (p) + free(p); +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/paper.cpp b/src/libs/libgroff/paper.cpp new file mode 100644 index 0000000..842f369 --- /dev/null +++ b/src/libs/libgroff/paper.cpp @@ -0,0 +1,82 @@ +// -*- C++ -*- +/* Copyright (C) 2002-2020 Free Software Foundation, Inc. + Written by Werner Lemberg (wl@gnu.org) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" +#include "paper.h" + +paper papersizes[NUM_PAPERSIZES]; + +// length and width in mm +static void add_iso_paper(char series, int offset, + int start_length, int start_width) +{ + int length = start_length; + int width = start_width; + for (int i = 0; i < 8; i++) + { + char *p = new char[3]; + p[0] = series; + p[1] = '0' + i; + p[2] = '\0'; + papersizes[offset + i].name = p; + // convert mm to inch + papersizes[offset + i].length = (double)length / 25.4; + papersizes[offset + i].width = (double)width / 25.4; + // after division by two, values must be rounded down to the next + // integer (as specified by ISO) + int tmp = length; + length = width; + width = tmp / 2; + } +} + +// length and width in inch +static void add_american_paper(const char *name, int idx, + double length, double width ) +{ + char *p = new char[strlen(name) + 1]; + strcpy(p, name); + papersizes[idx].name = p; + papersizes[idx].length = length; + papersizes[idx].width = width; +} + +int papersize_init::initialised = 0; + +papersize_init::papersize_init() +{ + if (initialised) + return; + initialised = 1; + add_iso_paper('a', 0, 1189, 841); + add_iso_paper('b', 8, 1414, 1000); + add_iso_paper('c', 16, 1297, 917); + add_iso_paper('d', 24, 1090, 771); + add_american_paper("letter", 32, 11, 8.5); + add_american_paper("legal", 33, 14, 8.5); + add_american_paper("tabloid", 34, 17, 11); + add_american_paper("ledger", 35, 11, 17); + add_american_paper("statement", 36, 8.5, 5.5); + add_american_paper("executive", 37, 10, 7.5); + // the next three entries are for grolj4 + add_american_paper("com10", 38, 9.5, 4.125); + add_american_paper("monarch", 39, 7.5, 3.875); + // this is an ISO format, but it easier to use add_american_paper + add_american_paper("dl", 40, 220/25.4, 110/25.4); +} diff --git a/src/libs/libgroff/prime.cpp b/src/libs/libgroff/prime.cpp new file mode 100644 index 0000000..5ae068d --- /dev/null +++ b/src/libs/libgroff/prime.cpp @@ -0,0 +1,55 @@ +/* Copyright (C) 2014-2020 Free Software Foundation, Inc. + +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 2 of the License, or +(at your option) any later version. + +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 +for more details. + +The GNU General Public License version 2 (GPL2) is available in the +internet at <http://www.gnu.org/licenses/gpl-2.0.txt>. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <assert.h> +#include <math.h> + +bool is_prime(unsigned n) +{ + assert(n > 1); + if (n <= 3) + return true; + if (!(n & 1)) + return false; + if (n % 3 == 0) + return false; + unsigned lim = unsigned(sqrt((double)n)); + unsigned d = 5; + for (;;) { + if (d > lim) + break; + if (n % d == 0) + return false; + d += 2; + if (d > lim) + break; + if (n % d == 0) + return false; + d += 4; + } + return true; +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/progname.c b/src/libs/libgroff/progname.c new file mode 100644 index 0000000..f4320c1 --- /dev/null +++ b/src/libs/libgroff/progname.c @@ -0,0 +1,18 @@ +/* Copyright (C) 2014-2020 Free Software Foundation, Inc. + +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 2 of the License, or +(at your option) any later version. + +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 +for more details. + +The GNU General Public License version 2 (GPL2) is available in the +internet at <http://www.gnu.org/licenses/gpl-2.0.txt>. */ + +const char *program_name = 0; diff --git a/src/libs/libgroff/ptable.cpp b/src/libs/libgroff/ptable.cpp new file mode 100644 index 0000000..52d09f8 --- /dev/null +++ b/src/libs/libgroff/ptable.cpp @@ -0,0 +1,57 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include "ptable.h" +#include "errarg.h" +#include "error.h" + +unsigned long hash_string(const char *s) +{ + // This is the mythical Aho-Hopcroft-Ullman hash function. + // TODO: Improve. See http://www.haible.de/bruno/hashfunc.html + assert(s != 0); + unsigned long h = 0, g; + while (*s != 0) { + h <<= 4; + h += *s++; + if ((g = h & 0xf0000000) != 0) { + h ^= g >> 24; + h ^= g; + } + } + return h; +} + +static const unsigned table_sizes[] = { + 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, + 80021, 160001, 500009, 1000003, 2000003, 4000037, 8000009, + 16000057, 32000011, 64000031, 128000003, 0 +}; + +unsigned next_ptable_size(unsigned n) +{ + const unsigned *p; + for (p = table_sizes; *p <= n; p++) + if (*p == 0) + fatal("cannot expand table"); + return *p; +} + +// end of ptable.cpp diff --git a/src/libs/libgroff/putenv.c b/src/libs/libgroff/putenv.c new file mode 100644 index 0000000..692a126 --- /dev/null +++ b/src/libs/libgroff/putenv.c @@ -0,0 +1,97 @@ +/* Copyright (C) 1991-2020 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Hacked slightly by jjc@jclark.com for groff. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> + +#ifdef __STDC__ +#include <stddef.h> +typedef void *PTR; +typedef size_t SIZE_T; +#else /* not __STDC__ */ +typedef char *PTR; +typedef int SIZE_T; +#endif /* not __STDC__ */ + +#ifdef HAVE_STDLIB_H +#include <stdlib.h> +#else /* not HAVE_STDLIB_H */ +PTR malloc(); +#endif /* not HAVE_STDLIB_H */ + +#ifndef NULL +#define NULL 0 +#endif + +extern char **environ; + +/* Put STRING, which is of the form 'NAME=VALUE', in the environment. */ + +int putenv(const char *string) +{ + char *name_end = strchr(string, '='); + SIZE_T size; + char **ep; + + if (name_end == NULL) + { + /* Remove the variable from the environment. */ + size = strlen(string); + for (ep = environ; *ep != NULL; ++ep) + if (!strncmp(*ep, string, size) && (*ep)[size] == '=') + { + while (ep[1] != NULL) + { + ep[0] = ep[1]; + ++ep; + } + *ep = NULL; + return 0; + } + } + + size = 0; + for (ep = environ; *ep != NULL; ++ep) + if (!strncmp(*ep, string, name_end - string) + && (*ep)[name_end - string] == '=') + break; + else + ++size; + + if (*ep == NULL) + { + static char **last_environ = NULL; + char **new_environ = (char **) malloc((size + 2) * sizeof(char *)); + if (new_environ == NULL) + return -1; + (void) memcpy((PTR) new_environ, (PTR) environ, size * sizeof(char *)); + new_environ[size] = (char *) string; + new_environ[size + 1] = NULL; + if (last_environ != NULL) + free((PTR) last_environ); + last_environ = new_environ; + environ = new_environ; + } + else + *ep = (char *) string; + + return 0; +} diff --git a/src/libs/libgroff/quotearg.c b/src/libs/libgroff/quotearg.c new file mode 100644 index 0000000..75eaca8 --- /dev/null +++ b/src/libs/libgroff/quotearg.c @@ -0,0 +1,213 @@ +/* Copyright (C) 2004-2020 Free Software Foundation, Inc. + Written by: Jeff Conrad (jeff_conrad@msn.com) + and Keith Marshall (keith.d.marshall@ntlworld.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <limits.h> + +/* Define the default mechanism, and messages, for error reporting + * (user may substitute a preferred alternative, by defining his own + * implementation of the macros REPORT_ERROR, QUOTE_ARG_MALLOC_FAILED + * and QUOTE_ARG_REALLOC_FAILED, in the header file 'nonposix.h'). + */ + +#include "nonposix.h" + +#ifndef REPORT_ERROR +# define REPORT_ERROR(WHY) fprintf(stderr, "%s:%s\n", program_name, WHY) +#endif +#ifndef QUOTE_ARG_MALLOC_ERROR +# define QUOTE_ARG_MALLOC_ERROR "malloc: Buffer allocation failed" +#endif +#ifndef QUOTE_ARG_REALLOC_ERROR +# define QUOTE_ARG_REALLOC_ERROR "realloc: Buffer resize failed" +#endif + +extern char *program_name; /* main program must define this */ + +/* Prototypes */ +char *quote_arg(char *); +void purge_quoted_args(char **); + +#undef FALSE +#undef TRUE +#define FALSE 0 +#define TRUE 1 + +static int +needs_quoting(const char *string) +{ + /* Scan 'string' to see whether it needs quoting for MSVC 'spawn'/'exec' + * (i.e., whether it contains whitespace or embedded quotes). + */ + + if (string == NULL) /* ignore NULL strings */ + return FALSE; + + if (*string == '\0') /* explicit arguments of zero length */ + return TRUE; /* need quoting, so they aren't discarded */ + + while (*string) { + /* Scan non-NULL strings, up to '\0' terminator, + * returning 'TRUE' if quote or white space found. + */ + + if (*string == '"' || isspace(*string)) + return TRUE; + + /* otherwise, continue scanning to end of string */ + + ++string; + } + + /* Fall through, if no quotes or white space found, + * in which case, return 'FALSE'. + */ + + return FALSE; +} + +char * +quote_arg(char *string) +{ + /* Enclose arguments in double quotes so that the parsing done in the + * MSVC runtime startup code doesn't split them at whitespace. Escape + * embedded double quotes so that they emerge intact from the parsing. + */ + + int backslashes; + char *quoted, *p, *q; + + if (needs_quoting(string)) { + /* Need to create a quoted copy of 'string'; + * maximum buffer space needed is twice the original length, + * plus two enclosing quotes and one '\0' terminator. + */ + + if ((quoted = (char *)malloc(2 * strlen(string) + 3)) == NULL) { + /* Couldn't get a buffer for the quoted string, + * so complain, and bail out gracefully. + */ + + REPORT_ERROR(QUOTE_ARG_MALLOC_ERROR); + exit(1); + } + + /* Ok to proceed: + * insert the opening quote, then copy the source string, + * adding escapes as required. + */ + + *quoted = '"'; + for (backslashes = 0, p = string, q = quoted; *p; p++) { + if (*p == '\\') { + /* Just count backslashes when we find them. + * We will copy them out later, when we know if the count + * needs to be adjusted, to escape an embedded quote. + */ + + ++backslashes; + } + else if (*p == '"') { + /* This embedded quote character must be escaped, + * but first double up any immediately preceding backslashes, + * with one extra, as the escape character. + */ + + for (backslashes += backslashes + 1; backslashes; backslashes--) + *++q = '\\'; + + /* and now, add the quote character itself */ + + *++q = '"'; + } + else { + /* Any other character is simply copied, + * but first, if we have any pending backslashes, + * we must now insert them, without any count adjustment. + */ + + while (backslashes) { + *++q = '\\'; + --backslashes; + } + + /* and then, copy the current character */ + + *++q = *p; + } + } + + /* At end of argument: + * If any backslashes remain to be copied out, append them now, + * doubling the actual count to protect against reduction by MSVC, + * as a consequence of the immediately following closing quote. + */ + + for (backslashes += backslashes; backslashes; backslashes--) + *++q = '\\'; + + /* Finally, + * add the closing quote, terminate the quoted string, + * and adjust its size to what was actually required, + * ready for return. + */ + + *++q = '"'; + *++q = '\0'; + if ((string = (char *)realloc(quoted, strlen(quoted) + 1)) == NULL) { + /* but bail out gracefully, on error */ + + REPORT_ERROR(QUOTE_ARG_REALLOC_ERROR); + exit(1); + } + } + + /* 'string' now refers to the argument, + * quoted and escaped, as required. + */ + + return string; +} + +void +purge_quoted_args(char **argv) +{ + /* To avoid memory leaks, + * free all memory previously allocated by 'quoted_arg()', + * within the scope of the referring argument vector, 'argv'. + */ + + if (argv) + while (*argv) { + /* Any argument beginning with a double quote + * SHOULD have been allocated by 'quoted_arg()'. + */ + + if (**argv == '"') + free( *argv ); /* so free its allocation */ + ++argv; /* and continue to the next argument */ + } +} + +/* quotearg.c: end of file */ diff --git a/src/libs/libgroff/ref-add.sin b/src/libs/libgroff/ref-add.sin new file mode 100644 index 0000000..50aa7d1 --- /dev/null +++ b/src/libs/libgroff/ref-add.sin @@ -0,0 +1,29 @@ +# Add this package to a list of references stored in a text file. +# +# Copyright (C) 2000-2020 Free Software Foundation, Inc. +# +# This program 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 2, or (at your option) +# any later version. +# +# This program 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 for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, see <http://www.gnu.org/licenses/>. +# +# Written by Bruno Haible <haible@clisp.cons.org>. +# +/^# Packages using this file: / { + s/# Packages using this file:// + ta + :a + s/ @PACKAGE@ / @PACKAGE@ / + tb + s/ $/ @PACKAGE@ / + :b + s/^/# Packages using this file:/ +} diff --git a/src/libs/libgroff/ref-del.sin b/src/libs/libgroff/ref-del.sin new file mode 100644 index 0000000..1601469 --- /dev/null +++ b/src/libs/libgroff/ref-del.sin @@ -0,0 +1,24 @@ +# Remove this package from a list of references stored in a text file. +# +# Copyright (C) 2000-2020 Free Software Foundation, Inc. +# +# This program 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 2, or (at your option) +# any later version. +# +# This program 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 for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, see <http://www.gnu.org/licenses/>. +# +# Written by Bruno Haible <haible@clisp.cons.org>. +# +/^# Packages using this file: / { + s/# Packages using this file:// + s/ @PACKAGE@ / / + s/^/# Packages using this file:/ +} diff --git a/src/libs/libgroff/relocatable.h b/src/libs/libgroff/relocatable.h new file mode 100644 index 0000000..f152194 --- /dev/null +++ b/src/libs/libgroff/relocatable.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2014-2020 Free Software Foundation, Inc. + +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 2 of the License, or +(at your option) any later version. + +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 +for more details. + +The GNU General Public License version 2 (GPL2) is available in the +internet at <http://www.gnu.org/licenses/gpl-2.0.txt>. */ + +#include "relocate.h" +#define relocate(path) relocatep(path) diff --git a/src/libs/libgroff/relocate.cpp b/src/libs/libgroff/relocate.cpp new file mode 100644 index 0000000..32a0e2e --- /dev/null +++ b/src/libs/libgroff/relocate.cpp @@ -0,0 +1,244 @@ +/* Provide relocation for macro and font files. + Copyright (C) 2005-2020 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +// Made after relocation code in kpathsea and gettext. + +#include "lib.h" + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> + +#include "defs.h" +#include "posix.h" +#include "nonposix.h" +#include "relocate.h" + +#if defined _WIN32 +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +#endif + +#define INSTALLPATHLEN (sizeof(INSTALLPATH) - 1) +#ifndef DEBUG +# define DEBUG 0 +#endif + +extern "C" const char *program_name; + +// The prefix (parent directory) corresponding to the binary. +char *curr_prefix = 0; +size_t curr_prefix_len = 0; + +// Return the directory part of a filename, or '.' if no path separators. +char *xdirname(char *s) +{ + static const char dot[] = "."; + if (!s) + return 0; + // DIR_SEPS[] are possible directory separator characters, see nonposix.h. + // We want the rightmost separator of all possible ones. + // Example: d:/foo\\bar. + char *p = strrchr(s, DIR_SEPS[0]); + const char *sep = &DIR_SEPS[1]; + while (*sep) { + char *p1 = strrchr(s, *sep); + if (p1 && (!p || p1 > p)) + p = p1; + sep++; + } + if (p) + *p = '\0'; + else + s = (char *)dot; + return s; +} + +// Return the full path of NAME along the path PATHP. +// Adapted from search_path::open_file in searchpath.cpp. +char *searchpath(const char *name, const char *pathp) +{ + char *path; + if (!name || !*name) + return 0; +#if DEBUG + fprintf(stderr, "searchpath: pathp: '%s'\n", pathp); + fprintf(stderr, "searchpath: trying '%s'\n", name); +#endif + // Try first NAME as such; success if NAME is an absolute filename, + // or if NAME is found in the current directory. + if (!access (name, F_OK)) { + path = new char[path_name_max()]; +#ifdef _WIN32 + path = _fullpath(path, name, path_name_max()); +#else + path = realpath(name, path); +#endif +#if DEBUG + fprintf(stderr, "searchpath: found '%s'\n", path); +#endif + return path; + } + // Secondly, try the current directory. + // Now search along PATHP. + size_t namelen = strlen(name); + char *p = (char *)pathp; + for (;;) { + char *end = strchr(p, PATH_SEP_CHAR); + if (!end) + end = strchr(p, '\0'); + int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0; + path = new char[end - p + need_slash + namelen + 1]; + memcpy(path, p, end - p); + if (need_slash) + path[end - p] = '/'; + strcpy(path + (end - p) + need_slash, name); +#if DEBUG + fprintf(stderr, "searchpath: trying '%s'\n", path); +#endif + if (!access(path, F_OK)) { +#if DEBUG + fprintf(stderr, "searchpath: found '%s'\n", name); +#endif + return path; + } + delete[] path; + if (*end == '\0') + break; + p = end + 1; + } + return 0; +} + +// Search NAME along PATHP with the elements of PATHEXT in turn added. +char *searchpathext(const char *name, const char *pathext, const char *pathp) +{ + char *found = 0; + char *tmpathext = strsave(pathext); // strtok modifies this string, + // so make a copy + char *ext = strtok(tmpathext, PATH_SEP); + while (ext) { + char *namex = new char[strlen(name) + strlen(ext) + 1]; + strcpy(namex, name); + strcat(namex, ext); + found = searchpath(namex, pathp); + delete[] namex; + if (found) + break; + ext = strtok(0, PATH_SEP); + } + delete[] tmpathext; + return found; +} + +// Convert an MS path to a POSIX path. +char *msw2posixpath(char *path) +{ + char *s = path; + while (*s) { + if (*s == '\\') + *s = '/'; + s++; + } + return path; +} + +// Compute the current prefix. +void set_current_prefix() +{ + // Obtain the full path of the current binary; + // using GetModuleFileName on MS-Windows, + // and searching along PATH on other systems. +#ifdef _WIN32 + char *pathextstr; + curr_prefix = new char[path_name_max()]; + int len = GetModuleFileName(0, curr_prefix, path_name_max()); + if (len) + len = GetShortPathName(curr_prefix, curr_prefix, path_name_max()); +# if DEBUG + fprintf(stderr, "curr_prefix: %s\n", curr_prefix); +# endif /* DEBUG */ + if (!curr_prefix && !strchr(program_name, '.')) { // try with extensions + pathextstr = strsave(getenv("PATHEXT")); + if (!pathextstr) + pathextstr = strsave(PATH_EXT); + curr_prefix = searchpathext(program_name, pathextstr, getenv("PATH")); + delete[] pathextstr; + } +#else /* !_WIN32 */ + curr_prefix = searchpath(program_name, getenv("PATH")); + if (!curr_prefix) + return; +#endif /* !_WIN32 */ + msw2posixpath(curr_prefix); +#if DEBUG + fprintf(stderr, "curr_prefix: %s\n", curr_prefix); +#endif + curr_prefix = xdirname(curr_prefix); // directory of executable + curr_prefix = xdirname(curr_prefix); // parent directory of executable + curr_prefix_len = strlen(curr_prefix); +#if DEBUG + fprintf(stderr, "curr_prefix: %s\n", curr_prefix); + fprintf(stderr, "curr_prefix_len: %d\n", curr_prefix_len); +#endif +} + +// Strip the installation prefix and replace it +// with the current installation prefix; return the relocated path. +char *relocatep(const char *path) +{ +#if DEBUG + fprintf(stderr, "relocatep: path = %s\n", path); + fprintf(stderr, "relocatep: INSTALLPATH = %s\n", INSTALLPATH); + fprintf(stderr, "relocatep: INSTALLPATHLEN = %d\n", INSTALLPATHLEN); +#endif + if (!curr_prefix) + set_current_prefix(); + if (strncmp(INSTALLPATH, path, INSTALLPATHLEN)) + return strsave(path); + char *relative_path = (char *)path + INSTALLPATHLEN; + size_t relative_path_len = strlen(relative_path); + char *relocated_path = (char *)malloc(curr_prefix_len + + relative_path_len + 1); + assert(0 != curr_prefix); + strcpy(relocated_path, curr_prefix); + strcat(relocated_path, relative_path); +#if DEBUG + fprintf(stderr, "relocated_path: %s\n", relocated_path); +#endif /* DEBUG */ + return relocated_path; +} + +// Return the original pathname if it exists; +// otherwise return the relocated path. +char *relocate(const char *path) +{ + char *p; + if (access(path, F_OK)) + p = relocatep(path); + else + p = strsave(path); +#if DEBUG + fprintf (stderr, "relocate: %s\n", p); +#endif + return p; +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/searchpath.cpp b/src/libs/libgroff/searchpath.cpp new file mode 100644 index 0000000..6062e8d --- /dev/null +++ b/src/libs/libgroff/searchpath.cpp @@ -0,0 +1,215 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> + +#include "searchpath.h" +#include "nonposix.h" + +#ifdef _WIN32 +# include "relocate.h" +#else +# define relocate(path) strsave(path) +#endif + +search_path::search_path(const char *envvar, const char *standard, + int add_home, int add_current) +{ + char *home = 0; + if (add_home) + home = getenv("HOME"); + char *e = 0; + if (envvar) + e = getenv(envvar); + dirs = new char[((e && *e) ? strlen(e) + 1 : 0) + + (add_current ? 1 + 1 : 0) + + ((home && *home) ? strlen(home) + 1 : 0) + + ((standard && *standard) ? strlen(standard) : 0) + + 1]; + *dirs = '\0'; + if (e && *e) { + strcat(dirs, e); + strcat(dirs, PATH_SEP); + } + if (add_current) { + strcat(dirs, "."); + strcat(dirs, PATH_SEP); + } + if (home && *home) { + strcat(dirs, home); + strcat(dirs, PATH_SEP); + } + if (standard && *standard) + strcat(dirs, standard); + init_len = strlen(dirs); +} + +search_path::~search_path() +{ + // dirs is always allocated + delete[] dirs; +} + +void search_path::command_line_dir(const char *s) +{ + char *old = dirs; + unsigned old_len = strlen(old); + unsigned slen = strlen(s); + dirs = new char[old_len + 1 + slen + 1]; + memcpy(dirs, old, old_len - init_len); + char *p = dirs; + p += old_len - init_len; + if (init_len == 0) + *p++ = PATH_SEP_CHAR; + memcpy(p, s, slen); + p += slen; + if (init_len > 0) { + *p++ = PATH_SEP_CHAR; + memcpy(p, old + old_len - init_len, init_len); + p += init_len; + } + *p++ = '\0'; + delete[] old; +} + +FILE *search_path::open_file(const char *name, char **pathp) +{ + assert(name != 0); + if (IS_ABSOLUTE(name) || *dirs == '\0') { + FILE *fp = fopen(name, "r"); + if (fp) { + if (pathp) + *pathp = strsave(name); + return fp; + } + else + return 0; + } + unsigned namelen = strlen(name); + char *p = dirs; + for (;;) { + char *end = strchr(p, PATH_SEP_CHAR); + if (!end) + end = strchr(p, '\0'); + int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0; + char *origpath = new char[(end - p) + need_slash + namelen + 1]; + memcpy(origpath, p, end - p); + if (need_slash) + origpath[end - p] = '/'; + strcpy(origpath + (end - p) + need_slash, name); +#if 0 + fprintf(stderr, "origpath '%s'\n", origpath); +#endif + char *path = relocate(origpath); + delete[] origpath; +#if 0 + fprintf(stderr, "trying '%s'\n", path); +#endif + FILE *fp = fopen(path, "r"); + int err = errno; + if (fp) { + if (pathp) + *pathp = path; + else { + free(path); + errno = err; + } + return fp; + } + free(path); + errno = err; + if (*end == '\0') + break; + p = end + 1; + } + return 0; +} + +FILE *search_path::open_file_cautious(const char *name, char **pathp, + const char *mode) +{ + if (!mode) + mode = "r"; + bool reading = (strchr(mode, 'r') != 0); + if (name == 0 || strcmp(name, "-") == 0) { + if (pathp) + *pathp = strsave(reading ? "stdin" : "stdout"); + return (reading ? stdin : stdout); + } + if (!reading || IS_ABSOLUTE(name) || *dirs == '\0') { + FILE *fp = fopen(name, mode); + if (fp) { + if (pathp) + *pathp = strsave(name); + return fp; + } + else + return 0; + } + unsigned namelen = strlen(name); + char *p = dirs; + for (;;) { + char *end = strchr(p, PATH_SEP_CHAR); + if (!end) + end = strchr(p, '\0'); + int need_slash = end > p && strchr(DIR_SEPS, end[-1]) == 0; + char *origpath = new char[(end - p) + need_slash + namelen + 1]; + memcpy(origpath, p, end - p); + if (need_slash) + origpath[end - p] = '/'; + strcpy(origpath + (end - p) + need_slash, name); +#if 0 + fprintf(stderr, "origpath '%s'\n", origpath); +#endif + char *path = relocate(origpath); + delete[] origpath; +#if 0 + fprintf(stderr, "trying '%s'\n", path); +#endif + FILE *fp = fopen(path, mode); + int err = errno; + if (fp) { + if (pathp) + *pathp = path; + else { + free(path); + errno = err; + } + return fp; + } + free(path); + errno = err; + if (err != ENOENT) + return 0; + if (*end == '\0') + break; + p = end + 1; + } + errno = ENOENT; + return 0; +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/spawnvp.c b/src/libs/libgroff/spawnvp.c new file mode 100644 index 0000000..1fffa2b --- /dev/null +++ b/src/libs/libgroff/spawnvp.c @@ -0,0 +1,120 @@ +/* Copyright (C) 2004-2020 Free Software Foundation, Inc. + Written by: Keith Marshall (keith.d.marshall@ntlworld.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> + +#ifdef HAVE_PROCESS_H +# include <process.h> +#endif + +#if defined(__MSDOS__) \ + || (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) \ + || defined(__EMX__) + +#define SPAWN_FUNCTION_WRAPPERS 1 + +/* Define the default mechanism, and messages, for error reporting + * (user may substitute a preferred alternative, by defining his own + * implementation of the macros REPORT_ERROR and ARGV_MALLOC_ERROR, + * in the header file 'nonposix.h'). + */ + +#include "nonposix.h" + +#ifndef REPORT_ERROR +# define REPORT_ERROR(WHY) fprintf(stderr, "%s:%s\n", program_name, WHY) +#endif +#ifndef ARGV_MALLOC_ERROR +# define ARGV_MALLOC_ERROR "malloc: Allocation for 'argv' failed" +#endif + +extern char *program_name; + +extern char *quote_arg(char *string); +extern void purge_quoted_args(char **argv); + +int +spawnvp_wrapper(int mode, char *path, char **argv) +{ + /* Invoke the system 'spawnvp' service + * enclosing the passed arguments in double quotes, as required, + * so that the (broken) default parsing in the MSVC runtime doesn't + * split them at whitespace. */ + + char **quoted_argv; /* used to build a quoted local copy of 'argv' */ + + int i; /* used as an index into 'argv' or 'quoted_argv' */ + int status = -1; /* initialise return code, in case we fail */ + int argc = 0; /* initialise argument count; may be none */ + + /* First count the number of arguments + * which are actually present in the passed 'argv'. */ + + if (argv) + for (quoted_argv = argv; *quoted_argv; ++argc, ++quoted_argv) + ; + + /* If we do not now have an argument count, + * then we must fall through and fail. */ + + if (argc) { + /* We do have at least one argument: + * We will use a copy of the 'argv', in which to do the quoting, + * so we must allocate space for it. */ + + if ((quoted_argv = (char **)malloc(++argc * sizeof(char **))) == NULL) { + /* If we didn't get enough space, + * then complain, and bail out gracefully. */ + + REPORT_ERROR(ARGV_MALLOC_ERROR); + exit(1); + } + + /* Now copy the passed 'argv' into our new vector, + * quoting its contents as required. */ + + for (i = 0; i < argc; i++) + quoted_argv[i] = quote_arg(argv[i]); + + /* Invoke the MSVC 'spawnvp' service + * passing our now appropriately quoted copy of 'argv'. */ + + status = spawnvp(mode, path, quoted_argv); + + /* Clean up our memory allocations + * for the quoted copy of 'argv', which is no longer required. */ + + purge_quoted_args(quoted_argv); + free(quoted_argv); + } + + /* Finally, + * return the status code returned by 'spawnvp', + * or a failure code if we fell through. */ + + return status; +} + +#endif /* __MSDOS__ || _WIN32 */ + +/* spawnvp.c: end of file */ diff --git a/src/libs/libgroff/strcasecmp.c b/src/libs/libgroff/strcasecmp.c new file mode 100644 index 0000000..22c0997 --- /dev/null +++ b/src/libs/libgroff/strcasecmp.c @@ -0,0 +1,65 @@ +/* strcasecmp.c -- case insensitive string comparator + Copyright (C) 1998-2020 Free Software Foundation, Inc. + + This program 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 3 of the License, or + (at your option) any later version. + + This program 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 for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#ifdef LENGTH_LIMIT +# define STRXCASECMP_FUNCTION strncasecmp +# define STRXCASECMP_DECLARE_N , size_t n +# define LENGTH_LIMIT_EXPR(Expr) Expr +#else +# define STRXCASECMP_FUNCTION strcasecmp +# define STRXCASECMP_DECLARE_N /* empty */ +# define LENGTH_LIMIT_EXPR(Expr) 0 +#endif + +#include <stddef.h> +#include <ctype.h> + +#define TOLOWER(Ch) (isupper (Ch) ? tolower (Ch) : (Ch)) + +/* Compare {{no more than N characters of }}strings S1 and S2, + ignoring case, returning less than, equal to or + greater than zero if S1 is lexicographically less + than, equal to or greater than S2. */ + +int +STRXCASECMP_FUNCTION (const char *s1, const char *s2 STRXCASECMP_DECLARE_N) +{ + register const unsigned char *p1 = (const unsigned char *) s1; + register const unsigned char *p2 = (const unsigned char *) s2; + unsigned char c1, c2; + + if (p1 == p2 || LENGTH_LIMIT_EXPR (n == 0)) + return 0; + + do + { + c1 = TOLOWER (*p1); + c2 = TOLOWER (*p2); + + if (LENGTH_LIMIT_EXPR (--n == 0) || c1 == '\0') + break; + + ++p1; + ++p2; + } + while (c1 == c2); + + return c1 - c2; +} diff --git a/src/libs/libgroff/strerror.c b/src/libs/libgroff/strerror.c new file mode 100644 index 0000000..a8887e5 --- /dev/null +++ b/src/libs/libgroff/strerror.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> /* for MinGW */ + +#define INT_DIGITS 19 /* enough for 64 bit integer */ + +#ifndef HAVE_SYS_NERR +extern int sys_nerr; +#endif +#ifndef HAVE_SYS_ERRLIST +extern char *sys_errlist[]; +#endif + +char *strerror(n) + int n; +{ + static char buf[sizeof("Error ") + 1 + INT_DIGITS]; + if (n >= 0 && n < sys_nerr && sys_errlist[n] != 0) + return sys_errlist[n]; + else { + sprintf(buf, "Error %d", n); + return buf; + } +} diff --git a/src/libs/libgroff/string.cpp b/src/libs/libgroff/string.cpp new file mode 100644 index 0000000..33c0565 --- /dev/null +++ b/src/libs/libgroff/string.cpp @@ -0,0 +1,354 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> + +#include "lib.h" + +#include "stringclass.h" + +static char *salloc(int len, int *sizep); +static void sfree(char *ptr, int size); +static char *sfree_alloc(char *ptr, int size, int len, int *sizep); +static char *srealloc(char *ptr, int size, int oldlen, int newlen, int *sizep); + +static char *salloc(int len, int *sizep) +{ + if (len == 0) { + *sizep = 0; + return 0; + } + else + return new char[*sizep = len*2]; +} + +static void sfree(char *ptr, int) +{ + delete[] ptr; +} + +static char *sfree_alloc(char *ptr, int oldsz, int len, int *sizep) +{ + if (oldsz >= len) { + *sizep = oldsz; + return ptr; + } + delete[] ptr; + if (len == 0) { + *sizep = 0; + return 0; + } + else + return new char[*sizep = len*2]; +} + +static char *srealloc(char *ptr, int oldsz, int oldlen, int newlen, int *sizep) +{ + if (oldsz >= newlen) { + *sizep = oldsz; + return ptr; + } + if (newlen == 0) { + delete[] ptr; + *sizep = 0; + return 0; + } + else { + char *p = new char[*sizep = newlen*2]; + if (oldlen < newlen && oldlen != 0) + memcpy(p, ptr, oldlen); + delete[] ptr; + return p; + } +} + +string::string() : ptr(0), len(0), sz(0) +{ +} + +string::string(const char *p, int n) : len(n) +{ + assert(n >= 0); + ptr = salloc(n, &sz); + if (n != 0) + memcpy(ptr, p, n); +} + +string::string(const char *p) +{ + if (p == 0) { + len = 0; + ptr = 0; + sz = 0; + } + else { + len = strlen(p); + ptr = salloc(len, &sz); + if (len != 0) + memcpy(ptr, p, len); + } +} + +string::string(char c) : len(1) +{ + ptr = salloc(1, &sz); + *ptr = c; +} + +string::string(const string &s) : len(s.len) +{ + ptr = salloc(len, &sz); + if (len != 0) + memcpy(ptr, s.ptr, len); +} + +string::~string() +{ + sfree(ptr, sz); +} + +string &string::operator=(const string &s) +{ + ptr = sfree_alloc(ptr, sz, s.len, &sz); + len = s.len; + if (len != 0) + memcpy(ptr, s.ptr, len); + return *this; +} + +string &string::operator=(const char *p) +{ + if (p == 0) { + sfree(ptr, len); + len = 0; + ptr = 0; + sz = 0; + } + else { + int slen = strlen(p); + ptr = sfree_alloc(ptr, sz, slen, &sz); + len = slen; + if (len != 0) + memcpy(ptr, p, len); + } + return *this; +} + +string &string::operator=(char c) +{ + ptr = sfree_alloc(ptr, sz, 1, &sz); + len = 1; + *ptr = c; + return *this; +} + +void string::move(string &s) +{ + sfree(ptr, sz); + ptr = s.ptr; + len = s.len; + sz = s.sz; + s.ptr = 0; + s.len = 0; + s.sz = 0; +} + +void string::grow1() +{ + ptr = srealloc(ptr, sz, len, len + 1, &sz); +} + +string &string::operator+=(const char *p) +{ + if (p != 0) { + int n = strlen(p); + int newlen = len + n; + if (newlen > sz) + ptr = srealloc(ptr, sz, len, newlen, &sz); + memcpy(ptr + len, p, n); + len = newlen; + } + return *this; +} + +string &string::operator+=(const string &s) +{ + if (s.len != 0) { + int newlen = len + s.len; + if (newlen > sz) + ptr = srealloc(ptr, sz, len, newlen, &sz); + memcpy(ptr + len, s.ptr, s.len); + len = newlen; + } + return *this; +} + +void string::append(const char *p, int n) +{ + if (n > 0) { + int newlen = len + n; + if (newlen > sz) + ptr = srealloc(ptr, sz, len, newlen, &sz); + memcpy(ptr + len, p, n); + len = newlen; + } +} + +string::string(const char *s1, int n1, const char *s2, int n2) +{ + assert(n1 >= 0 && n2 >= 0); + len = n1 + n2; + if (len == 0) { + sz = 0; + ptr = 0; + } + else { + ptr = salloc(len, &sz); + if (n1 == 0) + memcpy(ptr, s2, n2); + else { + memcpy(ptr, s1, n1); + if (n2 != 0) + memcpy(ptr + n1, s2, n2); + } + } +} + +int operator<=(const string &s1, const string &s2) +{ + return (s1.len <= s2.len + ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0 + : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0); +} + +int operator<(const string &s1, const string &s2) +{ + return (s1.len < s2.len + ? s1.len == 0 || memcmp(s1.ptr, s2.ptr, s1.len) <= 0 + : s2.len != 0 && memcmp(s1.ptr, s2.ptr, s2.len) < 0); +} + +int operator>=(const string &s1, const string &s2) +{ + return (s1.len >= s2.len + ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0 + : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0); +} + +int operator>(const string &s1, const string &s2) +{ + return (s1.len > s2.len + ? s2.len == 0 || memcmp(s1.ptr, s2.ptr, s2.len) >= 0 + : s1.len != 0 && memcmp(s1.ptr, s2.ptr, s1.len) > 0); +} + +void string::set_length(int i) +{ + assert(i >= 0); + if (i > sz) + ptr = srealloc(ptr, sz, len, i, &sz); + len = i; +} + +void string::clear() +{ + len = 0; +} + +int string::search(char c) const +{ + char *p = ptr ? (char *)memchr(ptr, c, len) : 0; + return p ? p - ptr : -1; +} + +// we silently strip nuls + +char *string::extract() const +{ + char *p = ptr; + int n = len; + int nnuls = 0; + int i; + for (i = 0; i < n; i++) + if (p[i] == '\0') + nnuls++; + char *q =(char*)malloc(n + 1 - nnuls); + if (q != 0 /* nullptr */) { + char *r = q; + for (i = 0; i < n; i++) + if (p[i] != '\0') + *r++ = p[i]; + *r = '\0'; + } + return q; +} + +void string::remove_spaces() +{ + int l = len - 1; + while (l >= 0 && ptr[l] == ' ') + l--; + char *p = ptr; + if (l > 0) + while (*p == ' ') { + p++; + l--; + } + if (len - 1 != l) { + if (l >= 0) { + len = l + 1; + char *tmp = new char[sz]; + memcpy(tmp, p, len); + delete[] ptr; + ptr = tmp; + } + else { + len = 0; + if (ptr) { + delete[] ptr; + ptr = 0; + sz = 0; + } + } + } +} + +void put_string(const string &s, FILE *fp) +{ + int len = s.length(); + const char *ptr = s.contents(); + for (int i = 0; i < len; i++) + putc(ptr[i], fp); +} + +string as_string(int i) +{ + static char buf[INT_DIGITS + 2]; + sprintf(buf, "%d", i); + return string(buf); +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/strncasecmp.c b/src/libs/libgroff/strncasecmp.c new file mode 100644 index 0000000..ec8aae2 --- /dev/null +++ b/src/libs/libgroff/strncasecmp.c @@ -0,0 +1,19 @@ +/* Copyright (C) 2014-2020 Free Software Foundation, Inc. + +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 2 of the License, or +(at your option) any later version. + +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 +for more details. + +The GNU General Public License version 2 (GPL2) is available in the +internet at <http://www.gnu.org/licenses/gpl-2.0.txt>. */ + +#define LENGTH_LIMIT +#include "strcasecmp.c" diff --git a/src/libs/libgroff/strsave.cpp b/src/libs/libgroff/strsave.cpp new file mode 100644 index 0000000..95a529b --- /dev/null +++ b/src/libs/libgroff/strsave.cpp @@ -0,0 +1,40 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <stdlib.h> + +char *strsave(const char *s) +{ + if (s == 0) + return 0; + char *p = (char*)malloc(strlen(s) + 1); + if (p != 0) + strcpy(p, s); + return p; +} + +// Local Variables: +// fill-column: 72 +// mode: C++ +// End: +// vim: set cindent noexpandtab shiftwidth=2 textwidth=72: diff --git a/src/libs/libgroff/strtol.c b/src/libs/libgroff/strtol.c new file mode 100644 index 0000000..1820732 --- /dev/null +++ b/src/libs/libgroff/strtol.c @@ -0,0 +1,131 @@ +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <string.h> +#include <ctype.h> +#include <errno.h> + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#ifndef LONG_MAX +#define LONG_MAX 2147483647 +#endif + +#ifndef LONG_MIN +#define LONG_MIN (-LONG_MAX-1) +#endif + +#ifdef isascii +#define ISASCII(c) isascii(c) +#else +#define ISASCII(c) (1) +#endif + +long strtol(str, ptr, base) + char *str, **ptr; + int base; +{ + char *start = str; + int neg = 0; + long val; + char *p; + static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + + while (ISASCII((unsigned char)*str) && isspace((unsigned char)*str)) + str++; + + if (*str == '-') { + neg = 1; + str++; + } + if (base == 0) { + if (*str == '0') { + if (str[1] == 'x' || str[1] == 'X') { + str += 2; + base = 16; + } + else + base = 8; + } + else + base = 10; + } + if (base < 2 || base > 36) + base = 10; + else if (base == 16 && *str == '0' && (str[1] == 'x' || str[1] == 'X')) + str += 2; + + p = strchr(digits, (ISASCII((unsigned char)*str) + && isupper((unsigned char)*str) + ? tolower((unsigned char)*str) + : *str)); + if (p == 0 || (val = (p - digits)) >= base) { + if (base == 16 && str > start && (str[-1] == 'x' || str[-1] == 'X')) { + if (ptr) + *ptr = str - 1; + } + else { + if (ptr) + *ptr = start; + errno = ERANGE; + } + return 0; + } + if (neg) + val = -val; + + while (*++str != '\0') { + int n; + + p = strchr(digits, (ISASCII((unsigned char)*str) + && isupper((unsigned char)*str) + ? tolower((unsigned char)*str) : *str)); + if (p == 0) + break; + n = p - digits; + if (n >= base) + break; + if (neg) { + if (-(unsigned long)val > (-(unsigned long)LONG_MIN - n)/base) { + val = LONG_MIN; + errno = ERANGE; + } + else + val = val*base - n; + } + else { + if (val > (LONG_MAX - n)/base) { + val = LONG_MAX; + errno = ERANGE; + } + else + val = val*base + n; + } + } + + if (ptr) + *ptr = str; + + return val; +} diff --git a/src/libs/libgroff/symbol.cpp b/src/libs/libgroff/symbol.cpp new file mode 100644 index 0000000..4f50627 --- /dev/null +++ b/src/libs/libgroff/symbol.cpp @@ -0,0 +1,157 @@ +// -*- C++ -*- +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#include "errarg.h" +#include "error.h" +#include "symbol.h" + +const char **symbol::table = 0; +int symbol::table_used = 0; +int symbol::table_size = 0; +char *symbol::block = 0; +int symbol::block_size = 0; + +const symbol NULL_SYMBOL; +const symbol EMPTY_SYMBOL(""); + +#ifdef BLOCK_SIZE +#undef BLOCK_SIZE +#endif + +const int BLOCK_SIZE = 1024; +// the table will increase in size as necessary +// the size will be chosen from the following array +// add some more if you want +static const unsigned int table_sizes[] = { + 101, 503, 1009, 2003, 3001, 4001, 5003, 10007, 20011, 40009, 80021, + 160001, 500009, 1000003, 1500007, 2000003, 0 +}; +const double FULL_MAX = 0.3; // don't let the table get more than this full + +static unsigned int hash_string(const char *p) +{ + // compute a hash code; this assumes 32-bit unsigned ints + // see p436 of Compilers by Aho, Sethi & Ullman + // give special treatment to two-character names + unsigned int hc = 0, g; + if (*p != 0) { + hc = *p++; + if (*p != 0) { + hc <<= 7; + hc += *p++; + for (; *p != 0; p++) { + hc <<= 4; + hc += *p; + if ((g = (hc & 0xf0000000)) == 0) { + hc ^= g >> 24; + hc ^= g; + } + } + } + } + return hc; +} + +// Tell compiler that a variable is intentionally unused. +inline void unused(void *) { } + +symbol::symbol(const char *p, int how) +{ + if (p == 0) { + s = 0; + return; + } + if (*p == 0) { + s = ""; + return; + } + if (table == 0) { + table_size = table_sizes[0]; + table = (const char **)new char*[table_size]; + for (int i = 0; i < table_size; i++) + table[i] = 0; + table_used = 0; + } + unsigned int hc = hash_string(p); + const char **pp; + for (pp = table + hc % table_size; + *pp != 0; + (pp == table ? pp = table + table_size - 1 : --pp)) + if (strcmp(p, *pp) == 0) { + s = *pp; + return; + } + if (how == MUST_ALREADY_EXIST) { + s = 0; + return; + } + if (table_used >= table_size - 1 || table_used >= table_size*FULL_MAX) { + const char **old_table = table; + unsigned int old_table_size = table_size; + int i; + for (i = 1; table_sizes[i] <= old_table_size; i++) + if (table_sizes[i] == 0) + fatal("too many symbols"); + table_size = table_sizes[i]; + table_used = 0; + table = (const char **)new char*[table_size]; + for (i = 0; i < table_size; i++) + table[i] = 0; + for (pp = old_table + old_table_size - 1; + pp >= old_table; + --pp) { + symbol temp(*pp, 1); /* insert it into the new table */ + unused(&temp); + } + delete[] old_table; + for (pp = table + hc % table_size; + *pp != 0; + (pp == table ? pp = table + table_size - 1 : --pp)) + ; + } + ++table_used; + if (how == DONT_STORE) { + s = *pp = p; + } + else { + int len = strlen(p)+1; + if (block == 0 || block_size < len) { + block_size = len > BLOCK_SIZE ? len : BLOCK_SIZE; + block = new char [block_size]; + } + (void)strcpy(block, p); + s = *pp = block; + block += len; + block_size -= len; + } +} + +symbol concat(symbol s1, symbol s2) +{ + char *buf = new char [strlen(s1.contents()) + strlen(s2.contents()) + 1]; + strcpy(buf, s1.contents()); + strcat(buf, s2.contents()); + symbol res(buf); + delete[] buf; + return res; +} + +symbol default_symbol("default"); diff --git a/src/libs/libgroff/tmpfile.cpp b/src/libs/libgroff/tmpfile.cpp new file mode 100644 index 0000000..5e807ae --- /dev/null +++ b/src/libs/libgroff/tmpfile.cpp @@ -0,0 +1,188 @@ +// -*- C++ -*- +/* Copyright (C) 1989-2020 Free Software Foundation, Inc. + Written by James Clark (jjc@jclark.com) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" + +#include <errno.h> +#include <stdlib.h> + +#include "posix.h" +#include "errarg.h" +#include "error.h" +#include "nonposix.h" + +// If this is set, create temporary files there +#define GROFF_TMPDIR_ENVVAR "GROFF_TMPDIR" +// otherwise if this is set, create temporary files there +#define TMPDIR_ENVVAR "TMPDIR" +// otherwise, on MS-DOS or MS-Windows ... +#if defined(__MSDOS__) || defined(_WIN32) +// if either of these is set, create temporary files there +// (giving priority to WIN32_TMPDIR_ENVVAR) +#define WIN32_TMPDIR_ENVVAR "TMP" +#define MSDOS_TMPDIR_ENVVAR "TEMP" +#endif +// otherwise if P_tmpdir is defined, create temporary files there +#ifdef P_tmpdir +# define DEFAULT_TMPDIR P_tmpdir +#else +// otherwise create temporary files here. +# define DEFAULT_TMPDIR "/tmp" +#endif +// Use this as the prefix for temporary filenames. +#define TMPFILE_PREFIX_SHORT "" +#define TMPFILE_PREFIX_LONG "groff" + +char *tmpfile_prefix; +size_t tmpfile_prefix_len; +int use_short_postfix = 0; + +struct temp_init { + temp_init(); + ~temp_init(); +} _temp_init; + +temp_init::temp_init() +{ + // First, choose a location for creating temporary files... + const char *tem; + // using the first match for any of the environment specs in listed order. + if ( + (tem = getenv(GROFF_TMPDIR_ENVVAR)) == 0 + && (tem = getenv(TMPDIR_ENVVAR)) == 0 +#if defined(__MSDOS__) || defined(_WIN32) + // If we didn't find a match for either of the above + // (which are preferred, regardless of the host operating system), + // and we are hosted on either MS-Windows or MS-DOS, + // then try the Microsoft conventions. + && (tem = getenv(WIN32_TMPDIR_ENVVAR)) == 0 + && (tem = getenv(MSDOS_TMPDIR_ENVVAR)) == 0 +#endif + ) + // If we didn't find an environment spec fall back to this default. + tem = DEFAULT_TMPDIR; + size_t tem_len = strlen(tem); + const char *tem_end = tem + tem_len - 1; + int need_slash = (strchr(DIR_SEPS, *tem_end) == 0) ? 1 : 0; + char *tem2 = new char[tem_len + need_slash + 1]; + strcpy(tem2, tem); + if (need_slash) + strcat(tem2, "/"); + const char *tem3 = TMPFILE_PREFIX_LONG; + if (file_name_max(tem2) <= 14) { + tem3 = TMPFILE_PREFIX_SHORT; + use_short_postfix = 1; + } + tmpfile_prefix_len = tem_len + need_slash + strlen(tem3); + tmpfile_prefix = new char[tmpfile_prefix_len + 1]; + strcpy(tmpfile_prefix, tem2); + strcat(tmpfile_prefix, tem3); + delete[] tem2; +} + +temp_init::~temp_init() +{ + delete[] tmpfile_prefix; +} + +/* + * Generate a temporary name template with a postfix + * immediately after the TMPFILE_PREFIX. + * It uses the groff preferences for a temporary directory. + * Note that no file name is either created or opened, + * only the *template* is returned. + */ + +char *xtmptemplate(const char *postfix_long, const char *postfix_short) +{ + const char *postfix = use_short_postfix ? postfix_short : postfix_long; + int postlen = 0; + if (postfix) + postlen = strlen(postfix); + char *templ = new char[tmpfile_prefix_len + postlen + 6 + 1]; + strcpy(templ, tmpfile_prefix); + if (postlen > 0) + strcat(templ, postfix); + strcat(templ, "XXXXXX"); + return templ; +} + +// The trick with unlinking the temporary file while it is still in +// use is not portable, it will fail on MS-DOS and most MS-Windows +// filesystems. So it cannot be used on non-Posix systems. +// Instead, we maintain a list of files to be deleted on exit. +// This should be portable to all platforms. + +struct xtmpfile_list { + char *fname; + xtmpfile_list *next; + xtmpfile_list(char *fn) : fname(fn), next(0) {} +}; + +xtmpfile_list *xtmpfiles_to_delete = 0; + +struct xtmpfile_list_init { + ~xtmpfile_list_init(); +} _xtmpfile_list_init; + +xtmpfile_list_init::~xtmpfile_list_init() +{ + xtmpfile_list *x = xtmpfiles_to_delete; + while (x != 0) { + if (unlink(x->fname) < 0) + error("cannot unlink '%1': %2", x->fname, strerror(errno)); + xtmpfile_list *tmp = x; + x = x->next; + delete[] tmp->fname; + delete tmp; + } +} + +static void add_tmp_file(const char *name) +{ + char *s = new char[strlen(name)+1]; + strcpy(s, name); + xtmpfile_list *x = new xtmpfile_list(s); + x->next = xtmpfiles_to_delete; + xtmpfiles_to_delete = x; +} + +// Open a temporary file and with fatal error on failure. + +FILE *xtmpfile(char **namep, + const char *postfix_long, const char *postfix_short, + int do_unlink) +{ + char *templ = xtmptemplate(postfix_long, postfix_short); + errno = 0; + int fd = mkstemp(templ); + if (fd < 0) + fatal("cannot create temporary file: %1", strerror(errno)); + errno = 0; + FILE *fp = fdopen(fd, FOPEN_RWB); // many callers of xtmpfile use binary I/O + if (!fp) + fatal("fdopen: %1", strerror(errno)); + if (do_unlink) + add_tmp_file(templ); + if (namep) + *namep = templ; + else + delete[] templ; + return fp; +} diff --git a/src/libs/libgroff/tmpname.cpp b/src/libs/libgroff/tmpname.cpp new file mode 100644 index 0000000..69dc9a4 --- /dev/null +++ b/src/libs/libgroff/tmpname.cpp @@ -0,0 +1,117 @@ +/* Copyright (C) 2001-2020 Free Software Foundation, Inc. + Written by Werner Lemberg (wl@gnu.org) + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + + +/* This file is heavily based on the function __gen_tempname() in the + file tempname.c which is part of the fileutils package. */ + + +#include "lib.h" + +#include <stddef.h> +#include <stdlib.h> +#include <errno.h> +#include <time.h> + +#include "posix.h" +#include "nonposix.h" + +#ifndef TMP_MAX +# define TMP_MAX 238328 +#endif + +#if HAVE_SYS_TIME_H +# include <sys/time.h> +#endif + +#ifdef HAVE_GETTIMEOFDAY +#ifdef NEED_DECLARATION_GETTIMEOFDAY +extern "C" { + int gettimeofday(struct timeval *, void *); +} +#endif +#endif + +#if HAVE_CC_INTTYPES_H +# include <inttypes.h> +#endif + +/* Use the widest available unsigned type if uint64_t is not + available. The algorithm below extracts a number less than 62**6 + (approximately 2**35.725) from uint64_t, so ancient hosts where + uintmax_t is only 32 bits lose about 3.725 bits of randomness, + which is better than not having mkstemp at all. */ +#if !defined UINT64_MAX && !defined uint64_t +# define uint64_t uintmax_t +#endif + +/* These are the characters used in temporary filenames. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +int gen_tempname(char *tmpl, int dir) +{ + static uint64_t value; + + size_t len = strlen(tmpl); + if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX")) + return -1; /* EINVAL */ + + /* This is where the Xs start. */ + char *XXXXXX = &tmpl[len - 6]; + + /* Get some more or less random data. */ +#if HAVE_GETTIMEOFDAY + timeval tv; + gettimeofday(&tv, 0); + uint64_t random_time_bits = ((uint64_t)tv.tv_usec << 16) ^ tv.tv_sec; +#else + uint64_t random_time_bits = time(0); +#endif + value += random_time_bits ^ getpid(); + + for (int count = 0; count < TMP_MAX; value += 7777, ++count) { + uint64_t v = value; + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + int fd = dir ? mkdir(tmpl, S_IRUSR | S_IWUSR | S_IXUSR) + : open(tmpl, + O_RDWR | O_CREAT | O_EXCL | O_BINARY, + S_IRUSR | S_IWUSR); + + if (fd >= 0) + return fd; + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + return -1; /* EEXIST */ +} diff --git a/src/libs/libgroff/unicode.cpp b/src/libs/libgroff/unicode.cpp new file mode 100644 index 0000000..29e80c7 --- /dev/null +++ b/src/libs/libgroff/unicode.cpp @@ -0,0 +1,65 @@ +// -*- C++ -*- +/* Copyright (C) 2002-2020 Free Software Foundation, Inc. + Written by Werner Lemberg <wl@gnu.org> + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" +#include "cset.h" +#include "stringclass.h" + +#include "unicode.h" + +const char *check_unicode_name(const char *u) +{ + if (*u != 'u') + return 0; + const char *p = ++u; + for (;;) { + int val = 0; + const char *start = p; + for (;;) { + // only uppercase hex digits allowed + if (!csxdigit(*p)) + return 0; + if (csdigit(*p)) + val = val*0x10 + (*p-'0'); + else if (csupper(*p)) + val = val*0x10 + (*p-'A'+10); + else + return 0; + // biggest Unicode value is U+10FFFF + if (val > 0x10FFFF) + return 0; + p++; + if (*p == '\0' || *p == '_') + break; + } + // surrogates not allowed + if ((val >= 0xD800 && val <= 0xDBFF) || (val >= 0xDC00 && val <= 0xDFFF)) + return 0; + if (val > 0xFFFF) { + if (*start == '0') // no leading zeros allowed if > 0xFFFF + return 0; + } + else if (p - start != 4) // otherwise, check for exactly 4 hex digits + return 0; + if (*p == '\0') + break; + p++; + } + return u; +} diff --git a/src/libs/libgroff/uniglyph.cpp b/src/libs/libgroff/uniglyph.cpp new file mode 100644 index 0000000..bab2bc4 --- /dev/null +++ b/src/libs/libgroff/uniglyph.cpp @@ -0,0 +1,497 @@ +// -*- C++ -*- +/* Copyright (C) 2002-2020 Free Software Foundation, Inc. + Written by Werner Lemberg <wl@gnu.org> + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "lib.h" +#include "stringclass.h" +#include "ptable.h" + +#include "unicode.h" + +struct unicode_to_glyph { + char *value; +}; + +declare_ptable(unicode_to_glyph) +implement_ptable(unicode_to_glyph) + +PTABLE(unicode_to_glyph) unicode_to_glyph_table; + +struct S { + const char *key; + const char *value; +} unicode_to_glyph_list[] = { + { "0021", "!" }, +//{ "0022", "\"" }, + { "0022", "dq" }, +//{ "0023", "#" }, + { "0023", "sh" }, +//{ "0024", "$" }, + { "0024", "Do" }, + { "0025", "%" }, + { "0026", "&" }, + { "0027", "aq" }, + { "0028", "(" }, + { "0029", ")" }, + { "002A", "*" }, +//{ "002B", "+" }, + { "002B", "pl" }, + { "002C", "," }, + { "002E", "." }, +//{ "002F", "/" }, + { "002F", "sl" }, + { "0030", "0" }, + { "0031", "1" }, + { "0032", "2" }, + { "0033", "3" }, + { "0034", "4" }, + { "0035", "5" }, + { "0036", "6" }, + { "0037", "7" }, + { "0038", "8" }, + { "0039", "9" }, + { "003A", ":" }, + { "003B", ";" }, + { "003C", "<" }, +//{ "003D", "=" }, + { "003D", "eq" }, + { "003D_0338", "!=" }, + { "003E", ">" }, + { "003F", "?" }, +//{ "0040", "@" }, + { "0040", "at" }, + { "0041", "A" }, + { "0041_0300", "`A" }, + { "0041_0301", "'A" }, + { "0041_0302", "^A" }, + { "0041_0303", "~A" }, + { "0041_0308", ":A" }, + { "0041_030A", "oA" }, + { "0042", "B" }, + { "0043", "C" }, + { "0043_0301", "'C" }, + { "0043_0327", ",C" }, + { "0044", "D" }, + { "0045", "E" }, + { "0045_0300", "`E" }, + { "0045_0301", "'E" }, + { "0045_0302", "^E" }, + { "0045_0308", ":E" }, + { "0046", "F" }, + { "0047", "G" }, + { "0048", "H" }, + { "0049", "I" }, + { "0049_0300", "`I" }, + { "0049_0301", "'I" }, + { "0049_0302", "^I" }, + { "0049_0308", ":I" }, + { "004A", "J" }, + { "004B", "K" }, + { "004C", "L" }, + { "004D", "M" }, + { "004E", "N" }, + { "004E_0303", "~N" }, + { "004F", "O" }, + { "004F_0300", "`O" }, + { "004F_0301", "'O" }, + { "004F_0302", "^O" }, + { "004F_0303", "~O" }, + { "004F_0308", ":O" }, + { "0050", "P" }, + { "0051", "Q" }, + { "0052", "R" }, + { "0053", "S" }, + { "0053_030C", "vS" }, + { "0054", "T" }, + { "0055", "U" }, + { "0055_0300", "`U" }, + { "0055_0301", "'U" }, + { "0055_0302", "^U" }, + { "0055_0308", ":U" }, + { "0056", "V" }, + { "0057", "W" }, + { "0058", "X" }, + { "0059", "Y" }, + { "0059_0301", "'Y" }, + { "0059_0308", ":Y" }, + { "005A", "Z" }, + { "005A_030C", "vZ" }, + { "005B", "lB" }, +//{ "005B", "[" }, + { "005C", "rs" }, +//{ "005C", "\\" }, + { "005D", "rB" }, +//{ "005D", "]" }, +//{ "005E", "^" }, +//{ "005E", "a^" }, + { "005E", "ha" }, +//{ "005F", "_" }, +//{ "005F", "ru" }, + { "005F", "ul" }, + { "0060", "ga" }, + { "0061", "a" }, + { "0061_0300", "`a" }, + { "0061_0301", "'a" }, + { "0061_0302", "^a" }, + { "0061_0303", "~a" }, + { "0061_0308", ":a" }, + { "0061_030A", "oa" }, + { "0062", "b" }, + { "0063", "c" }, + { "0063_0301", "'c" }, + { "0063_0327", ",c" }, + { "0064", "d" }, + { "0065", "e" }, + { "0065_0300", "`e" }, + { "0065_0301", "'e" }, + { "0065_0302", "^e" }, + { "0065_0308", ":e" }, + { "0066", "f" }, + { "0066_0066", "ff" }, + { "0066_0066_0069", "Fi" }, + { "0066_0066_006C", "Fl" }, + { "0066_0069", "fi" }, + { "0066_006C", "fl" }, + { "0067", "g" }, + { "0068", "h" }, + { "0069", "i" }, + { "0069_0300", "`i" }, + { "0069_0301", "'i" }, + { "0069_0302", "^i" }, + { "0069_0308", ":i" }, + { "006A", "j" }, + { "006B", "k" }, + { "006C", "l" }, + { "006D", "m" }, + { "006E", "n" }, + { "006E_0303", "~n" }, + { "006F", "o" }, + { "006F_0300", "`o" }, + { "006F_0301", "'o" }, + { "006F_0302", "^o" }, + { "006F_0303", "~o" }, + { "006F_0308", ":o" }, + { "0070", "p" }, + { "0071", "q" }, + { "0072", "r" }, + { "0073", "s" }, + { "0073_030C", "vs" }, + { "0074", "t" }, + { "0075", "u" }, + { "0075_0300", "`u" }, + { "0075_0301", "'u" }, + { "0075_0302", "^u" }, + { "0075_0308", ":u" }, + { "0076", "v" }, + { "0077", "w" }, + { "0078", "x" }, + { "0079", "y" }, + { "0079_0301", "'y" }, + { "0079_0308", ":y" }, + { "007A", "z" }, + { "007A_030C", "vz" }, + { "007B", "lC" }, +//{ "007B", "{" }, + { "007C", "ba" }, +//{ "007C", "or" }, +//{ "007C", "|" }, + { "007D", "rC" }, +//{ "007D", "}" }, +//{ "007E", "a~" }, + { "007E", "ti" }, +//{ "007E", "~" }, + { "00A1", "r!" }, + { "00A2", "ct" }, + { "00A3", "Po" }, + { "00A4", "Cs" }, + { "00A5", "Ye" }, + { "00A6", "bb" }, + { "00A7", "sc" }, + { "00A8", "ad" }, + { "00A9", "co" }, + { "00AA", "Of" }, + { "00AB", "Fo" }, + { "00AC", "no" }, +//{ "00AC", "tno" }, + // In groff, U+00AD is an input character only; it is not mapped to + // a glyph but to '\%'. + { "00AE", "rg" }, + { "00AF", "a-" }, + { "00B0", "de" }, + { "00B1", "+-" }, +//{ "00B1", "t+-" }, + { "00B2", "S2" }, + { "00B3", "S3" }, + { "00B4", "aa" }, + { "00B5", "mc" }, + { "00B6", "ps" }, + { "00B7", "pc" }, + { "00B8", "ac" }, + { "00B9", "S1" }, + { "00BA", "Om" }, + { "00BB", "Fc" }, + { "00BC", "14" }, + { "00BD", "12" }, + { "00BE", "34" }, + { "00BF", "r?" }, + { "00C6", "AE" }, + { "00D0", "-D" }, + { "00D7", "mu" }, +//{ "00D7", "tmu" }, + { "00D8", "/O" }, + { "00DE", "TP" }, + { "00DF", "ss" }, + { "00E6", "ae" }, + { "00F0", "Sd" }, + { "00F7", "di" }, +//{ "00F7", "tdi" }, + { "00F8", "/o" }, + { "00FE", "Tp" }, + { "0131", ".i" }, + { "0132", "IJ" }, + { "0133", "ij" }, + { "0141", "/L" }, + { "0142", "/l" }, + { "0152", "OE" }, + { "0153", "oe" }, + { "0192", "Fn" }, + { "0237", ".j" }, + { "02C7", "ah" }, + { "02D8", "ab" }, + { "02D9", "a." }, + { "02DA", "ao" }, + { "02DB", "ho" }, + { "02DD", "a\"" }, + { "0391", "*A" }, + { "0392", "*B" }, + { "0393", "*G" }, + { "0394", "*D" }, + { "0395", "*E" }, + { "0396", "*Z" }, + { "0397", "*Y" }, + { "0398", "*H" }, + { "0399", "*I" }, + { "039A", "*K" }, + { "039B", "*L" }, + { "039C", "*M" }, + { "039D", "*N" }, + { "039E", "*C" }, + { "039F", "*O" }, + { "03A0", "*P" }, + { "03A1", "*R" }, + { "03A3", "*S" }, + { "03A4", "*T" }, + { "03A5", "*U" }, + { "03A6", "*F" }, + { "03A7", "*X" }, + { "03A8", "*Q" }, + { "03A9", "*W" }, + { "03B1", "*a" }, + { "03B2", "*b" }, + { "03B3", "*g" }, + { "03B4", "*d" }, + { "03B5", "*e" }, + { "03B6", "*z" }, + { "03B7", "*y" }, + { "03B8", "*h" }, + { "03B9", "*i" }, + { "03BA", "*k" }, + { "03BB", "*l" }, + { "03BC", "*m" }, + { "03BD", "*n" }, + { "03BE", "*c" }, + { "03BF", "*o" }, + { "03C0", "*p" }, + { "03C1", "*r" }, + { "03C2", "ts" }, + { "03C3", "*s" }, + { "03C4", "*t" }, + { "03C5", "*u" }, + { "03C6", "+f" }, + { "03C7", "*x" }, + { "03C8", "*q" }, + { "03C9", "*w" }, + { "03D1", "+h" }, + { "03D5", "*f" }, + { "03D6", "+p" }, + { "03F5", "+e" }, +//{ "2010", "-" }, + { "2010", "hy" }, + { "2013", "en" }, + { "2014", "em" }, +//{ "2018", "`" }, + { "2018", "oq" }, +//{ "2019", "'" }, + { "2019", "cq" }, + { "201A", "bq" }, + { "201C", "lq" }, + { "201D", "rq" }, + { "201E", "Bq" }, + { "2020", "dg" }, + { "2021", "dd" }, + { "2022", "bu" }, + { "2030", "%0" }, + { "2032", "fm" }, + { "2033", "sd" }, + { "2039", "fo" }, + { "203A", "fc" }, + { "203E", "rn" }, + { "2044", "f/" }, + { "20AC", "Eu" }, +//{ "20AC", "eu" }, + { "210F", "-h" }, +//{ "210F", "hbar" }, + { "2111", "Im" }, + { "2118", "wp" }, + { "211C", "Re" }, + { "2122", "tm" }, + { "2135", "Ah" }, + { "215B", "18" }, + { "215C", "38" }, + { "215D", "58" }, + { "215E", "78" }, + { "2190", "<-" }, + { "2191", "ua" }, + { "2192", "->" }, + { "2193", "da" }, + { "2194", "<>" }, + { "2195", "va" }, + { "21B5", "CR" }, + { "21D0", "lA" }, + { "21D1", "uA" }, + { "21D2", "rA" }, + { "21D3", "dA" }, + { "21D4", "hA" }, + { "21D5", "vA" }, + { "2200", "fa" }, + { "2202", "pd" }, + { "2203", "te" }, + { "2205", "es" }, + { "2207", "gr" }, + { "2208", "mo" }, + { "2208_0338", "nm" }, + { "220B", "st" }, + { "220F", "product" }, + { "2210", "coproduct" }, + { "2211", "sum" }, + { "2212", "mi" }, +//{ "2212", "\\-" }, + { "2213", "-+" }, + { "2217", "**" }, + { "221A", "sr" }, + { "221D", "pt" }, + { "221E", "if" }, + { "2220", "/_" }, + { "2227", "AN" }, + { "2228", "OR" }, + { "2229", "ca" }, + { "222A", "cu" }, + { "222B", "is" }, +//{ "222B", "integral" }, +//{ "2234", "3d" }, + { "2234", "tf" }, + { "223C", "ap" }, + { "2243", "|=" }, + { "2245", "=~" }, +//{ "2248", "~=" }, + { "2248", "~~" }, + { "2261", "==" }, + { "2261_0338", "ne" }, + { "2264", "<=" }, + { "2265", ">=" }, + { "226A", ">>" }, + { "226B", "<<" }, + { "2282", "sb" }, + { "2282_0338", "nb" }, + { "2283", "sp" }, + { "2283_0338", "nc" }, + { "2286", "ib" }, + { "2287", "ip" }, + { "2295", "c+" }, + { "2297", "c*" }, + { "22A5", "pp" }, + { "22C5", "md" }, + { "2308", "lc" }, + { "2309", "rc" }, + { "230A", "lf" }, + { "230B", "rf" }, + { "239B", "parenlefttp" }, + { "239C", "parenleftex" }, + { "239D", "parenleftbt" }, + { "239E", "parenrighttp" }, + { "239F", "parenrightex" }, + { "23A0", "parenrightbt" }, +//{ "23A1", "bracketlefttp" }, + { "23A2", "bracketleftex" }, +//{ "23A3", "bracketleftbt" }, +//{ "23A4", "bracketrighttp" }, + { "23A5", "bracketrightex" }, +//{ "23A6", "bracketrightbt" }, + { "23A7", "lt" }, +//{ "23A7", "bracelefttp" }, + { "23A8", "lk" }, +//{ "23A8", "braceleftmid" }, + { "23A9", "lb" }, +//{ "23A9", "braceleftbt" }, + { "23AA", "bv" }, +//{ "23AA", "braceex" }, +//{ "23AA", "braceleftex" }, +//{ "23AA", "bracerightex" }, + { "23AB", "rt" }, +//{ "23AB", "bracerighttp" }, + { "23AC", "rk" }, +//{ "23AC", "bracerightmid" }, + { "23AD", "rb" }, +//{ "23AD", "bracerightbt" }, + { "23AF", "an" }, + { "2502", "br" }, + { "25A1", "sq" }, + { "25CA", "lz" }, + { "25CB", "ci" }, + { "261C", "lh" }, + { "261E", "rh" }, + { "2660", "SP" }, + { "2663", "CL" }, + { "2665", "HE" }, + { "2666", "DI" }, + { "2713", "OK" }, + { "27E8", "la" }, + { "27E9", "ra" }, +}; + +// global constructor +static struct unicode_to_glyph_init { + unicode_to_glyph_init(); +} _unicode_to_glyph_init; + +unicode_to_glyph_init::unicode_to_glyph_init() +{ + for (unsigned int i = 0; + i < sizeof(unicode_to_glyph_list)/sizeof(unicode_to_glyph_list[0]); + i++) { + unicode_to_glyph *utg = new unicode_to_glyph[1]; + utg->value = (char *)unicode_to_glyph_list[i].value; + unicode_to_glyph_table.define(unicode_to_glyph_list[i].key, utg); + } +} + +const char *unicode_to_glyph_name(const char *s) +{ + unicode_to_glyph *result = unicode_to_glyph_table.lookup(s); + return result ? result->value : 0; +} diff --git a/src/libs/libgroff/uniuni.cpp b/src/libs/libgroff/uniuni.cpp new file mode 100644 index 0000000..e3b2708 --- /dev/null +++ b/src/libs/libgroff/uniuni.cpp @@ -0,0 +1,2128 @@ +// -*- C++ -*- +/* Copyright (C) 2002-2020 Free Software Foundation, Inc. + Written by Werner Lemberg <wl@gnu.org> + +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 3 of the License, or +(at your option) any later version. + +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 +for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +// This code has been algorithmically derived from the file +// UnicodeData.txt, version 7.0.0, available from unicode.org, +// on 2014-12-16. + +#include "lib.h" +#include "stringclass.h" +#include "ptable.h" + +#include "unicode.h" + +struct unicode_decompose { + char *value; +}; + +declare_ptable(unicode_decompose) +implement_ptable(unicode_decompose) + +PTABLE(unicode_decompose) unicode_decompose_table; + +// the first digit in the composite string gives the number of composites + +struct S { + const char *key; + const char *value; +} unicode_decompose_list[] = { + { "00C0", "20041_0300" }, + { "00C1", "20041_0301" }, + { "00C2", "20041_0302" }, + { "00C3", "20041_0303" }, + { "00C4", "20041_0308" }, + { "00C5", "20041_030A" }, + { "00C7", "20043_0327" }, + { "00C8", "20045_0300" }, + { "00C9", "20045_0301" }, + { "00CA", "20045_0302" }, + { "00CB", "20045_0308" }, + { "00CC", "20049_0300" }, + { "00CD", "20049_0301" }, + { "00CE", "20049_0302" }, + { "00CF", "20049_0308" }, + { "00D1", "2004E_0303" }, + { "00D2", "2004F_0300" }, + { "00D3", "2004F_0301" }, + { "00D4", "2004F_0302" }, + { "00D5", "2004F_0303" }, + { "00D6", "2004F_0308" }, + { "00D9", "20055_0300" }, + { "00DA", "20055_0301" }, + { "00DB", "20055_0302" }, + { "00DC", "20055_0308" }, + { "00DD", "20059_0301" }, + { "00E0", "20061_0300" }, + { "00E1", "20061_0301" }, + { "00E2", "20061_0302" }, + { "00E3", "20061_0303" }, + { "00E4", "20061_0308" }, + { "00E5", "20061_030A" }, + { "00E7", "20063_0327" }, + { "00E8", "20065_0300" }, + { "00E9", "20065_0301" }, + { "00EA", "20065_0302" }, + { "00EB", "20065_0308" }, + { "00EC", "20069_0300" }, + { "00ED", "20069_0301" }, + { "00EE", "20069_0302" }, + { "00EF", "20069_0308" }, + { "00F1", "2006E_0303" }, + { "00F2", "2006F_0300" }, + { "00F3", "2006F_0301" }, + { "00F4", "2006F_0302" }, + { "00F5", "2006F_0303" }, + { "00F6", "2006F_0308" }, + { "00F9", "20075_0300" }, + { "00FA", "20075_0301" }, + { "00FB", "20075_0302" }, + { "00FC", "20075_0308" }, + { "00FD", "20079_0301" }, + { "00FF", "20079_0308" }, + { "0100", "20041_0304" }, + { "0101", "20061_0304" }, + { "0102", "20041_0306" }, + { "0103", "20061_0306" }, + { "0104", "20041_0328" }, + { "0105", "20061_0328" }, + { "0106", "20043_0301" }, + { "0107", "20063_0301" }, + { "0108", "20043_0302" }, + { "0109", "20063_0302" }, + { "010A", "20043_0307" }, + { "010B", "20063_0307" }, + { "010C", "20043_030C" }, + { "010D", "20063_030C" }, + { "010E", "20044_030C" }, + { "010F", "20064_030C" }, + { "0112", "20045_0304" }, + { "0113", "20065_0304" }, + { "0114", "20045_0306" }, + { "0115", "20065_0306" }, + { "0116", "20045_0307" }, + { "0117", "20065_0307" }, + { "0118", "20045_0328" }, + { "0119", "20065_0328" }, + { "011A", "20045_030C" }, + { "011B", "20065_030C" }, + { "011C", "20047_0302" }, + { "011D", "20067_0302" }, + { "011E", "20047_0306" }, + { "011F", "20067_0306" }, + { "0120", "20047_0307" }, + { "0121", "20067_0307" }, + { "0122", "20047_0327" }, + { "0123", "20067_0327" }, + { "0124", "20048_0302" }, + { "0125", "20068_0302" }, + { "0128", "20049_0303" }, + { "0129", "20069_0303" }, + { "012A", "20049_0304" }, + { "012B", "20069_0304" }, + { "012C", "20049_0306" }, + { "012D", "20069_0306" }, + { "012E", "20049_0328" }, + { "012F", "20069_0328" }, + { "0130", "20049_0307" }, + { "0134", "2004A_0302" }, + { "0135", "2006A_0302" }, + { "0136", "2004B_0327" }, + { "0137", "2006B_0327" }, + { "0139", "2004C_0301" }, + { "013A", "2006C_0301" }, + { "013B", "2004C_0327" }, + { "013C", "2006C_0327" }, + { "013D", "2004C_030C" }, + { "013E", "2006C_030C" }, + { "0143", "2004E_0301" }, + { "0144", "2006E_0301" }, + { "0145", "2004E_0327" }, + { "0146", "2006E_0327" }, + { "0147", "2004E_030C" }, + { "0148", "2006E_030C" }, + { "014C", "2004F_0304" }, + { "014D", "2006F_0304" }, + { "014E", "2004F_0306" }, + { "014F", "2006F_0306" }, + { "0150", "2004F_030B" }, + { "0151", "2006F_030B" }, + { "0154", "20052_0301" }, + { "0155", "20072_0301" }, + { "0156", "20052_0327" }, + { "0157", "20072_0327" }, + { "0158", "20052_030C" }, + { "0159", "20072_030C" }, + { "015A", "20053_0301" }, + { "015B", "20073_0301" }, + { "015C", "20053_0302" }, + { "015D", "20073_0302" }, + { "015E", "20053_0327" }, + { "015F", "20073_0327" }, + { "0160", "20053_030C" }, + { "0161", "20073_030C" }, + { "0162", "20054_0327" }, + { "0163", "20074_0327" }, + { "0164", "20054_030C" }, + { "0165", "20074_030C" }, + { "0168", "20055_0303" }, + { "0169", "20075_0303" }, + { "016A", "20055_0304" }, + { "016B", "20075_0304" }, + { "016C", "20055_0306" }, + { "016D", "20075_0306" }, + { "016E", "20055_030A" }, + { "016F", "20075_030A" }, + { "0170", "20055_030B" }, + { "0171", "20075_030B" }, + { "0172", "20055_0328" }, + { "0173", "20075_0328" }, + { "0174", "20057_0302" }, + { "0175", "20077_0302" }, + { "0176", "20059_0302" }, + { "0177", "20079_0302" }, + { "0178", "20059_0308" }, + { "0179", "2005A_0301" }, + { "017A", "2007A_0301" }, + { "017B", "2005A_0307" }, + { "017C", "2007A_0307" }, + { "017D", "2005A_030C" }, + { "017E", "2007A_030C" }, + { "01A0", "2004F_031B" }, + { "01A1", "2006F_031B" }, + { "01AF", "20055_031B" }, + { "01B0", "20075_031B" }, + { "01CD", "20041_030C" }, + { "01CE", "20061_030C" }, + { "01CF", "20049_030C" }, + { "01D0", "20069_030C" }, + { "01D1", "2004F_030C" }, + { "01D2", "2006F_030C" }, + { "01D3", "20055_030C" }, + { "01D4", "20075_030C" }, + { "01D5", "30055_0308_0304" }, + { "01D6", "30075_0308_0304" }, + { "01D7", "30055_0308_0301" }, + { "01D8", "30075_0308_0301" }, + { "01D9", "30055_0308_030C" }, + { "01DA", "30075_0308_030C" }, + { "01DB", "30055_0308_0300" }, + { "01DC", "30075_0308_0300" }, + { "01DE", "30041_0308_0304" }, + { "01DF", "30061_0308_0304" }, + { "01E0", "30041_0307_0304" }, + { "01E1", "30061_0307_0304" }, + { "01E2", "200C6_0304" }, + { "01E3", "200E6_0304" }, + { "01E6", "20047_030C" }, + { "01E7", "20067_030C" }, + { "01E8", "2004B_030C" }, + { "01E9", "2006B_030C" }, + { "01EA", "2004F_0328" }, + { "01EB", "2006F_0328" }, + { "01EC", "3004F_0328_0304" }, + { "01ED", "3006F_0328_0304" }, + { "01EE", "201B7_030C" }, + { "01EF", "20292_030C" }, + { "01F0", "2006A_030C" }, + { "01F4", "20047_0301" }, + { "01F5", "20067_0301" }, + { "01F8", "2004E_0300" }, + { "01F9", "2006E_0300" }, + { "01FA", "30041_030A_0301" }, + { "01FB", "30061_030A_0301" }, + { "01FC", "200C6_0301" }, + { "01FD", "200E6_0301" }, + { "01FE", "200D8_0301" }, + { "01FF", "200F8_0301" }, + { "0200", "20041_030F" }, + { "0201", "20061_030F" }, + { "0202", "20041_0311" }, + { "0203", "20061_0311" }, + { "0204", "20045_030F" }, + { "0205", "20065_030F" }, + { "0206", "20045_0311" }, + { "0207", "20065_0311" }, + { "0208", "20049_030F" }, + { "0209", "20069_030F" }, + { "020A", "20049_0311" }, + { "020B", "20069_0311" }, + { "020C", "2004F_030F" }, + { "020D", "2006F_030F" }, + { "020E", "2004F_0311" }, + { "020F", "2006F_0311" }, + { "0210", "20052_030F" }, + { "0211", "20072_030F" }, + { "0212", "20052_0311" }, + { "0213", "20072_0311" }, + { "0214", "20055_030F" }, + { "0215", "20075_030F" }, + { "0216", "20055_0311" }, + { "0217", "20075_0311" }, + { "0218", "20053_0326" }, + { "0219", "20073_0326" }, + { "021A", "20054_0326" }, + { "021B", "20074_0326" }, + { "021E", "20048_030C" }, + { "021F", "20068_030C" }, + { "0226", "20041_0307" }, + { "0227", "20061_0307" }, + { "0228", "20045_0327" }, + { "0229", "20065_0327" }, + { "022A", "3004F_0308_0304" }, + { "022B", "3006F_0308_0304" }, + { "022C", "3004F_0303_0304" }, + { "022D", "3006F_0303_0304" }, + { "022E", "2004F_0307" }, + { "022F", "2006F_0307" }, + { "0230", "3004F_0307_0304" }, + { "0231", "3006F_0307_0304" }, + { "0232", "20059_0304" }, + { "0233", "20079_0304" }, + { "0340", "10300" }, + { "0341", "10301" }, + { "0343", "10313" }, + { "0344", "20308_0301" }, + { "0374", "102B9" }, + { "037E", "1003B" }, + { "0385", "200A8_0301" }, + { "0386", "20391_0301" }, + { "0387", "100B7" }, + { "0388", "20395_0301" }, + { "0389", "20397_0301" }, + { "038A", "20399_0301" }, + { "038C", "2039F_0301" }, + { "038E", "203A5_0301" }, + { "038F", "203A9_0301" }, + { "0390", "303B9_0308_0301" }, + { "03AA", "20399_0308" }, + { "03AB", "203A5_0308" }, + { "03AC", "203B1_0301" }, + { "03AD", "203B5_0301" }, + { "03AE", "203B7_0301" }, + { "03AF", "203B9_0301" }, + { "03B0", "303C5_0308_0301" }, + { "03CA", "203B9_0308" }, + { "03CB", "203C5_0308" }, + { "03CC", "203BF_0301" }, + { "03CD", "203C5_0301" }, + { "03CE", "203C9_0301" }, + { "03D3", "203D2_0301" }, + { "03D4", "203D2_0308" }, + { "0400", "20415_0300" }, + { "0401", "20415_0308" }, + { "0403", "20413_0301" }, + { "0407", "20406_0308" }, + { "040C", "2041A_0301" }, + { "040D", "20418_0300" }, + { "040E", "20423_0306" }, + { "0419", "20418_0306" }, + { "0439", "20438_0306" }, + { "0450", "20435_0300" }, + { "0451", "20435_0308" }, + { "0453", "20433_0301" }, + { "0457", "20456_0308" }, + { "045C", "2043A_0301" }, + { "045D", "20438_0300" }, + { "045E", "20443_0306" }, + { "0476", "20474_030F" }, + { "0477", "20475_030F" }, + { "04C1", "20416_0306" }, + { "04C2", "20436_0306" }, + { "04D0", "20410_0306" }, + { "04D1", "20430_0306" }, + { "04D2", "20410_0308" }, + { "04D3", "20430_0308" }, + { "04D6", "20415_0306" }, + { "04D7", "20435_0306" }, + { "04DA", "204D8_0308" }, + { "04DB", "204D9_0308" }, + { "04DC", "20416_0308" }, + { "04DD", "20436_0308" }, + { "04DE", "20417_0308" }, + { "04DF", "20437_0308" }, + { "04E2", "20418_0304" }, + { "04E3", "20438_0304" }, + { "04E4", "20418_0308" }, + { "04E5", "20438_0308" }, + { "04E6", "2041E_0308" }, + { "04E7", "2043E_0308" }, + { "04EA", "204E8_0308" }, + { "04EB", "204E9_0308" }, + { "04EC", "2042D_0308" }, + { "04ED", "2044D_0308" }, + { "04EE", "20423_0304" }, + { "04EF", "20443_0304" }, + { "04F0", "20423_0308" }, + { "04F1", "20443_0308" }, + { "04F2", "20423_030B" }, + { "04F3", "20443_030B" }, + { "04F4", "20427_0308" }, + { "04F5", "20447_0308" }, + { "04F8", "2042B_0308" }, + { "04F9", "2044B_0308" }, + { "0622", "20627_0653" }, + { "0623", "20627_0654" }, + { "0624", "20648_0654" }, + { "0625", "20627_0655" }, + { "0626", "2064A_0654" }, + { "06C0", "206D5_0654" }, + { "06C2", "206C1_0654" }, + { "06D3", "206D2_0654" }, + { "0929", "20928_093C" }, + { "0931", "20930_093C" }, + { "0934", "20933_093C" }, + { "0958", "20915_093C" }, + { "0959", "20916_093C" }, + { "095A", "20917_093C" }, + { "095B", "2091C_093C" }, + { "095C", "20921_093C" }, + { "095D", "20922_093C" }, + { "095E", "2092B_093C" }, + { "095F", "2092F_093C" }, + { "09CB", "209C7_09BE" }, + { "09CC", "209C7_09D7" }, + { "09DC", "209A1_09BC" }, + { "09DD", "209A2_09BC" }, + { "09DF", "209AF_09BC" }, + { "0A33", "20A32_0A3C" }, + { "0A36", "20A38_0A3C" }, + { "0A59", "20A16_0A3C" }, + { "0A5A", "20A17_0A3C" }, + { "0A5B", "20A1C_0A3C" }, + { "0A5E", "20A2B_0A3C" }, + { "0B48", "20B47_0B56" }, + { "0B4B", "20B47_0B3E" }, + { "0B4C", "20B47_0B57" }, + { "0B5C", "20B21_0B3C" }, + { "0B5D", "20B22_0B3C" }, + { "0B94", "20B92_0BD7" }, + { "0BCA", "20BC6_0BBE" }, + { "0BCB", "20BC7_0BBE" }, + { "0BCC", "20BC6_0BD7" }, + { "0C48", "20C46_0C56" }, + { "0CC0", "20CBF_0CD5" }, + { "0CC7", "20CC6_0CD5" }, + { "0CC8", "20CC6_0CD6" }, + { "0CCA", "20CC6_0CC2" }, + { "0CCB", "30CC6_0CC2_0CD5" }, + { "0D4A", "20D46_0D3E" }, + { "0D4B", "20D47_0D3E" }, + { "0D4C", "20D46_0D57" }, + { "0DDA", "20DD9_0DCA" }, + { "0DDC", "20DD9_0DCF" }, + { "0DDD", "30DD9_0DCF_0DCA" }, + { "0DDE", "20DD9_0DDF" }, + { "0F43", "20F42_0FB7" }, + { "0F4D", "20F4C_0FB7" }, + { "0F52", "20F51_0FB7" }, + { "0F57", "20F56_0FB7" }, + { "0F5C", "20F5B_0FB7" }, + { "0F69", "20F40_0FB5" }, + { "0F73", "20F71_0F72" }, + { "0F75", "20F71_0F74" }, + { "0F76", "20FB2_0F80" }, + { "0F78", "20FB3_0F80" }, + { "0F81", "20F71_0F80" }, + { "0F93", "20F92_0FB7" }, + { "0F9D", "20F9C_0FB7" }, + { "0FA2", "20FA1_0FB7" }, + { "0FA7", "20FA6_0FB7" }, + { "0FAC", "20FAB_0FB7" }, + { "0FB9", "20F90_0FB5" }, + { "1026", "21025_102E" }, + { "1B06", "21B05_1B35" }, + { "1B08", "21B07_1B35" }, + { "1B0A", "21B09_1B35" }, + { "1B0C", "21B0B_1B35" }, + { "1B0E", "21B0D_1B35" }, + { "1B12", "21B11_1B35" }, + { "1B3B", "21B3A_1B35" }, + { "1B3D", "21B3C_1B35" }, + { "1B40", "21B3E_1B35" }, + { "1B41", "21B3F_1B35" }, + { "1B43", "21B42_1B35" }, + { "1E00", "20041_0325" }, + { "1E01", "20061_0325" }, + { "1E02", "20042_0307" }, + { "1E03", "20062_0307" }, + { "1E04", "20042_0323" }, + { "1E05", "20062_0323" }, + { "1E06", "20042_0331" }, + { "1E07", "20062_0331" }, + { "1E08", "30043_0327_0301" }, + { "1E09", "30063_0327_0301" }, + { "1E0A", "20044_0307" }, + { "1E0B", "20064_0307" }, + { "1E0C", "20044_0323" }, + { "1E0D", "20064_0323" }, + { "1E0E", "20044_0331" }, + { "1E0F", "20064_0331" }, + { "1E10", "20044_0327" }, + { "1E11", "20064_0327" }, + { "1E12", "20044_032D" }, + { "1E13", "20064_032D" }, + { "1E14", "30045_0304_0300" }, + { "1E15", "30065_0304_0300" }, + { "1E16", "30045_0304_0301" }, + { "1E17", "30065_0304_0301" }, + { "1E18", "20045_032D" }, + { "1E19", "20065_032D" }, + { "1E1A", "20045_0330" }, + { "1E1B", "20065_0330" }, + { "1E1C", "30045_0327_0306" }, + { "1E1D", "30065_0327_0306" }, + { "1E1E", "20046_0307" }, + { "1E1F", "20066_0307" }, + { "1E20", "20047_0304" }, + { "1E21", "20067_0304" }, + { "1E22", "20048_0307" }, + { "1E23", "20068_0307" }, + { "1E24", "20048_0323" }, + { "1E25", "20068_0323" }, + { "1E26", "20048_0308" }, + { "1E27", "20068_0308" }, + { "1E28", "20048_0327" }, + { "1E29", "20068_0327" }, + { "1E2A", "20048_032E" }, + { "1E2B", "20068_032E" }, + { "1E2C", "20049_0330" }, + { "1E2D", "20069_0330" }, + { "1E2E", "30049_0308_0301" }, + { "1E2F", "30069_0308_0301" }, + { "1E30", "2004B_0301" }, + { "1E31", "2006B_0301" }, + { "1E32", "2004B_0323" }, + { "1E33", "2006B_0323" }, + { "1E34", "2004B_0331" }, + { "1E35", "2006B_0331" }, + { "1E36", "2004C_0323" }, + { "1E37", "2006C_0323" }, + { "1E38", "3004C_0323_0304" }, + { "1E39", "3006C_0323_0304" }, + { "1E3A", "2004C_0331" }, + { "1E3B", "2006C_0331" }, + { "1E3C", "2004C_032D" }, + { "1E3D", "2006C_032D" }, + { "1E3E", "2004D_0301" }, + { "1E3F", "2006D_0301" }, + { "1E40", "2004D_0307" }, + { "1E41", "2006D_0307" }, + { "1E42", "2004D_0323" }, + { "1E43", "2006D_0323" }, + { "1E44", "2004E_0307" }, + { "1E45", "2006E_0307" }, + { "1E46", "2004E_0323" }, + { "1E47", "2006E_0323" }, + { "1E48", "2004E_0331" }, + { "1E49", "2006E_0331" }, + { "1E4A", "2004E_032D" }, + { "1E4B", "2006E_032D" }, + { "1E4C", "3004F_0303_0301" }, + { "1E4D", "3006F_0303_0301" }, + { "1E4E", "3004F_0303_0308" }, + { "1E4F", "3006F_0303_0308" }, + { "1E50", "3004F_0304_0300" }, + { "1E51", "3006F_0304_0300" }, + { "1E52", "3004F_0304_0301" }, + { "1E53", "3006F_0304_0301" }, + { "1E54", "20050_0301" }, + { "1E55", "20070_0301" }, + { "1E56", "20050_0307" }, + { "1E57", "20070_0307" }, + { "1E58", "20052_0307" }, + { "1E59", "20072_0307" }, + { "1E5A", "20052_0323" }, + { "1E5B", "20072_0323" }, + { "1E5C", "30052_0323_0304" }, + { "1E5D", "30072_0323_0304" }, + { "1E5E", "20052_0331" }, + { "1E5F", "20072_0331" }, + { "1E60", "20053_0307" }, + { "1E61", "20073_0307" }, + { "1E62", "20053_0323" }, + { "1E63", "20073_0323" }, + { "1E64", "30053_0301_0307" }, + { "1E65", "30073_0301_0307" }, + { "1E66", "30053_030C_0307" }, + { "1E67", "30073_030C_0307" }, + { "1E68", "30053_0323_0307" }, + { "1E69", "30073_0323_0307" }, + { "1E6A", "20054_0307" }, + { "1E6B", "20074_0307" }, + { "1E6C", "20054_0323" }, + { "1E6D", "20074_0323" }, + { "1E6E", "20054_0331" }, + { "1E6F", "20074_0331" }, + { "1E70", "20054_032D" }, + { "1E71", "20074_032D" }, + { "1E72", "20055_0324" }, + { "1E73", "20075_0324" }, + { "1E74", "20055_0330" }, + { "1E75", "20075_0330" }, + { "1E76", "20055_032D" }, + { "1E77", "20075_032D" }, + { "1E78", "30055_0303_0301" }, + { "1E79", "30075_0303_0301" }, + { "1E7A", "30055_0304_0308" }, + { "1E7B", "30075_0304_0308" }, + { "1E7C", "20056_0303" }, + { "1E7D", "20076_0303" }, + { "1E7E", "20056_0323" }, + { "1E7F", "20076_0323" }, + { "1E80", "20057_0300" }, + { "1E81", "20077_0300" }, + { "1E82", "20057_0301" }, + { "1E83", "20077_0301" }, + { "1E84", "20057_0308" }, + { "1E85", "20077_0308" }, + { "1E86", "20057_0307" }, + { "1E87", "20077_0307" }, + { "1E88", "20057_0323" }, + { "1E89", "20077_0323" }, + { "1E8A", "20058_0307" }, + { "1E8B", "20078_0307" }, + { "1E8C", "20058_0308" }, + { "1E8D", "20078_0308" }, + { "1E8E", "20059_0307" }, + { "1E8F", "20079_0307" }, + { "1E90", "2005A_0302" }, + { "1E91", "2007A_0302" }, + { "1E92", "2005A_0323" }, + { "1E93", "2007A_0323" }, + { "1E94", "2005A_0331" }, + { "1E95", "2007A_0331" }, + { "1E96", "20068_0331" }, + { "1E97", "20074_0308" }, + { "1E98", "20077_030A" }, + { "1E99", "20079_030A" }, + { "1E9B", "2017F_0307" }, + { "1EA0", "20041_0323" }, + { "1EA1", "20061_0323" }, + { "1EA2", "20041_0309" }, + { "1EA3", "20061_0309" }, + { "1EA4", "30041_0302_0301" }, + { "1EA5", "30061_0302_0301" }, + { "1EA6", "30041_0302_0300" }, + { "1EA7", "30061_0302_0300" }, + { "1EA8", "30041_0302_0309" }, + { "1EA9", "30061_0302_0309" }, + { "1EAA", "30041_0302_0303" }, + { "1EAB", "30061_0302_0303" }, + { "1EAC", "30041_0323_0302" }, + { "1EAD", "30061_0323_0302" }, + { "1EAE", "30041_0306_0301" }, + { "1EAF", "30061_0306_0301" }, + { "1EB0", "30041_0306_0300" }, + { "1EB1", "30061_0306_0300" }, + { "1EB2", "30041_0306_0309" }, + { "1EB3", "30061_0306_0309" }, + { "1EB4", "30041_0306_0303" }, + { "1EB5", "30061_0306_0303" }, + { "1EB6", "30041_0323_0306" }, + { "1EB7", "30061_0323_0306" }, + { "1EB8", "20045_0323" }, + { "1EB9", "20065_0323" }, + { "1EBA", "20045_0309" }, + { "1EBB", "20065_0309" }, + { "1EBC", "20045_0303" }, + { "1EBD", "20065_0303" }, + { "1EBE", "30045_0302_0301" }, + { "1EBF", "30065_0302_0301" }, + { "1EC0", "30045_0302_0300" }, + { "1EC1", "30065_0302_0300" }, + { "1EC2", "30045_0302_0309" }, + { "1EC3", "30065_0302_0309" }, + { "1EC4", "30045_0302_0303" }, + { "1EC5", "30065_0302_0303" }, + { "1EC6", "30045_0323_0302" }, + { "1EC7", "30065_0323_0302" }, + { "1EC8", "20049_0309" }, + { "1EC9", "20069_0309" }, + { "1ECA", "20049_0323" }, + { "1ECB", "20069_0323" }, + { "1ECC", "2004F_0323" }, + { "1ECD", "2006F_0323" }, + { "1ECE", "2004F_0309" }, + { "1ECF", "2006F_0309" }, + { "1ED0", "3004F_0302_0301" }, + { "1ED1", "3006F_0302_0301" }, + { "1ED2", "3004F_0302_0300" }, + { "1ED3", "3006F_0302_0300" }, + { "1ED4", "3004F_0302_0309" }, + { "1ED5", "3006F_0302_0309" }, + { "1ED6", "3004F_0302_0303" }, + { "1ED7", "3006F_0302_0303" }, + { "1ED8", "3004F_0323_0302" }, + { "1ED9", "3006F_0323_0302" }, + { "1EDA", "3004F_031B_0301" }, + { "1EDB", "3006F_031B_0301" }, + { "1EDC", "3004F_031B_0300" }, + { "1EDD", "3006F_031B_0300" }, + { "1EDE", "3004F_031B_0309" }, + { "1EDF", "3006F_031B_0309" }, + { "1EE0", "3004F_031B_0303" }, + { "1EE1", "3006F_031B_0303" }, + { "1EE2", "3004F_031B_0323" }, + { "1EE3", "3006F_031B_0323" }, + { "1EE4", "20055_0323" }, + { "1EE5", "20075_0323" }, + { "1EE6", "20055_0309" }, + { "1EE7", "20075_0309" }, + { "1EE8", "30055_031B_0301" }, + { "1EE9", "30075_031B_0301" }, + { "1EEA", "30055_031B_0300" }, + { "1EEB", "30075_031B_0300" }, + { "1EEC", "30055_031B_0309" }, + { "1EED", "30075_031B_0309" }, + { "1EEE", "30055_031B_0303" }, + { "1EEF", "30075_031B_0303" }, + { "1EF0", "30055_031B_0323" }, + { "1EF1", "30075_031B_0323" }, + { "1EF2", "20059_0300" }, + { "1EF3", "20079_0300" }, + { "1EF4", "20059_0323" }, + { "1EF5", "20079_0323" }, + { "1EF6", "20059_0309" }, + { "1EF7", "20079_0309" }, + { "1EF8", "20059_0303" }, + { "1EF9", "20079_0303" }, + { "1F00", "203B1_0313" }, + { "1F01", "203B1_0314" }, + { "1F02", "303B1_0313_0300" }, + { "1F03", "303B1_0314_0300" }, + { "1F04", "303B1_0313_0301" }, + { "1F05", "303B1_0314_0301" }, + { "1F06", "303B1_0313_0342" }, + { "1F07", "303B1_0314_0342" }, + { "1F08", "20391_0313" }, + { "1F09", "20391_0314" }, + { "1F0A", "30391_0313_0300" }, + { "1F0B", "30391_0314_0300" }, + { "1F0C", "30391_0313_0301" }, + { "1F0D", "30391_0314_0301" }, + { "1F0E", "30391_0313_0342" }, + { "1F0F", "30391_0314_0342" }, + { "1F10", "203B5_0313" }, + { "1F11", "203B5_0314" }, + { "1F12", "303B5_0313_0300" }, + { "1F13", "303B5_0314_0300" }, + { "1F14", "303B5_0313_0301" }, + { "1F15", "303B5_0314_0301" }, + { "1F18", "20395_0313" }, + { "1F19", "20395_0314" }, + { "1F1A", "30395_0313_0300" }, + { "1F1B", "30395_0314_0300" }, + { "1F1C", "30395_0313_0301" }, + { "1F1D", "30395_0314_0301" }, + { "1F20", "203B7_0313" }, + { "1F21", "203B7_0314" }, + { "1F22", "303B7_0313_0300" }, + { "1F23", "303B7_0314_0300" }, + { "1F24", "303B7_0313_0301" }, + { "1F25", "303B7_0314_0301" }, + { "1F26", "303B7_0313_0342" }, + { "1F27", "303B7_0314_0342" }, + { "1F28", "20397_0313" }, + { "1F29", "20397_0314" }, + { "1F2A", "30397_0313_0300" }, + { "1F2B", "30397_0314_0300" }, + { "1F2C", "30397_0313_0301" }, + { "1F2D", "30397_0314_0301" }, + { "1F2E", "30397_0313_0342" }, + { "1F2F", "30397_0314_0342" }, + { "1F30", "203B9_0313" }, + { "1F31", "203B9_0314" }, + { "1F32", "303B9_0313_0300" }, + { "1F33", "303B9_0314_0300" }, + { "1F34", "303B9_0313_0301" }, + { "1F35", "303B9_0314_0301" }, + { "1F36", "303B9_0313_0342" }, + { "1F37", "303B9_0314_0342" }, + { "1F38", "20399_0313" }, + { "1F39", "20399_0314" }, + { "1F3A", "30399_0313_0300" }, + { "1F3B", "30399_0314_0300" }, + { "1F3C", "30399_0313_0301" }, + { "1F3D", "30399_0314_0301" }, + { "1F3E", "30399_0313_0342" }, + { "1F3F", "30399_0314_0342" }, + { "1F40", "203BF_0313" }, + { "1F41", "203BF_0314" }, + { "1F42", "303BF_0313_0300" }, + { "1F43", "303BF_0314_0300" }, + { "1F44", "303BF_0313_0301" }, + { "1F45", "303BF_0314_0301" }, + { "1F48", "2039F_0313" }, + { "1F49", "2039F_0314" }, + { "1F4A", "3039F_0313_0300" }, + { "1F4B", "3039F_0314_0300" }, + { "1F4C", "3039F_0313_0301" }, + { "1F4D", "3039F_0314_0301" }, + { "1F50", "203C5_0313" }, + { "1F51", "203C5_0314" }, + { "1F52", "303C5_0313_0300" }, + { "1F53", "303C5_0314_0300" }, + { "1F54", "303C5_0313_0301" }, + { "1F55", "303C5_0314_0301" }, + { "1F56", "303C5_0313_0342" }, + { "1F57", "303C5_0314_0342" }, + { "1F59", "203A5_0314" }, + { "1F5B", "303A5_0314_0300" }, + { "1F5D", "303A5_0314_0301" }, + { "1F5F", "303A5_0314_0342" }, + { "1F60", "203C9_0313" }, + { "1F61", "203C9_0314" }, + { "1F62", "303C9_0313_0300" }, + { "1F63", "303C9_0314_0300" }, + { "1F64", "303C9_0313_0301" }, + { "1F65", "303C9_0314_0301" }, + { "1F66", "303C9_0313_0342" }, + { "1F67", "303C9_0314_0342" }, + { "1F68", "203A9_0313" }, + { "1F69", "203A9_0314" }, + { "1F6A", "303A9_0313_0300" }, + { "1F6B", "303A9_0314_0300" }, + { "1F6C", "303A9_0313_0301" }, + { "1F6D", "303A9_0314_0301" }, + { "1F6E", "303A9_0313_0342" }, + { "1F6F", "303A9_0314_0342" }, + { "1F70", "203B1_0300" }, + { "1F71", "203B1_0301" }, + { "1F72", "203B5_0300" }, + { "1F73", "203B5_0301" }, + { "1F74", "203B7_0300" }, + { "1F75", "203B7_0301" }, + { "1F76", "203B9_0300" }, + { "1F77", "203B9_0301" }, + { "1F78", "203BF_0300" }, + { "1F79", "203BF_0301" }, + { "1F7A", "203C5_0300" }, + { "1F7B", "203C5_0301" }, + { "1F7C", "203C9_0300" }, + { "1F7D", "203C9_0301" }, + { "1F80", "303B1_0313_0345" }, + { "1F81", "303B1_0314_0345" }, + { "1F82", "403B1_0313_0300_0345" }, + { "1F83", "403B1_0314_0300_0345" }, + { "1F84", "403B1_0313_0301_0345" }, + { "1F85", "403B1_0314_0301_0345" }, + { "1F86", "403B1_0313_0342_0345" }, + { "1F87", "403B1_0314_0342_0345" }, + { "1F88", "30391_0313_0345" }, + { "1F89", "30391_0314_0345" }, + { "1F8A", "40391_0313_0300_0345" }, + { "1F8B", "40391_0314_0300_0345" }, + { "1F8C", "40391_0313_0301_0345" }, + { "1F8D", "40391_0314_0301_0345" }, + { "1F8E", "40391_0313_0342_0345" }, + { "1F8F", "40391_0314_0342_0345" }, + { "1F90", "303B7_0313_0345" }, + { "1F91", "303B7_0314_0345" }, + { "1F92", "403B7_0313_0300_0345" }, + { "1F93", "403B7_0314_0300_0345" }, + { "1F94", "403B7_0313_0301_0345" }, + { "1F95", "403B7_0314_0301_0345" }, + { "1F96", "403B7_0313_0342_0345" }, + { "1F97", "403B7_0314_0342_0345" }, + { "1F98", "30397_0313_0345" }, + { "1F99", "30397_0314_0345" }, + { "1F9A", "40397_0313_0300_0345" }, + { "1F9B", "40397_0314_0300_0345" }, + { "1F9C", "40397_0313_0301_0345" }, + { "1F9D", "40397_0314_0301_0345" }, + { "1F9E", "40397_0313_0342_0345" }, + { "1F9F", "40397_0314_0342_0345" }, + { "1FA0", "303C9_0313_0345" }, + { "1FA1", "303C9_0314_0345" }, + { "1FA2", "403C9_0313_0300_0345" }, + { "1FA3", "403C9_0314_0300_0345" }, + { "1FA4", "403C9_0313_0301_0345" }, + { "1FA5", "403C9_0314_0301_0345" }, + { "1FA6", "403C9_0313_0342_0345" }, + { "1FA7", "403C9_0314_0342_0345" }, + { "1FA8", "303A9_0313_0345" }, + { "1FA9", "303A9_0314_0345" }, + { "1FAA", "403A9_0313_0300_0345" }, + { "1FAB", "403A9_0314_0300_0345" }, + { "1FAC", "403A9_0313_0301_0345" }, + { "1FAD", "403A9_0314_0301_0345" }, + { "1FAE", "403A9_0313_0342_0345" }, + { "1FAF", "403A9_0314_0342_0345" }, + { "1FB0", "203B1_0306" }, + { "1FB1", "203B1_0304" }, + { "1FB2", "303B1_0300_0345" }, + { "1FB3", "203B1_0345" }, + { "1FB4", "303B1_0301_0345" }, + { "1FB6", "203B1_0342" }, + { "1FB7", "303B1_0342_0345" }, + { "1FB8", "20391_0306" }, + { "1FB9", "20391_0304" }, + { "1FBA", "20391_0300" }, + { "1FBB", "20391_0301" }, + { "1FBC", "20391_0345" }, + { "1FBE", "103B9" }, + { "1FC1", "200A8_0342" }, + { "1FC2", "303B7_0300_0345" }, + { "1FC3", "203B7_0345" }, + { "1FC4", "303B7_0301_0345" }, + { "1FC6", "203B7_0342" }, + { "1FC7", "303B7_0342_0345" }, + { "1FC8", "20395_0300" }, + { "1FC9", "20395_0301" }, + { "1FCA", "20397_0300" }, + { "1FCB", "20397_0301" }, + { "1FCC", "20397_0345" }, + { "1FCD", "21FBF_0300" }, + { "1FCE", "21FBF_0301" }, + { "1FCF", "21FBF_0342" }, + { "1FD0", "203B9_0306" }, + { "1FD1", "203B9_0304" }, + { "1FD2", "303B9_0308_0300" }, + { "1FD3", "303B9_0308_0301" }, + { "1FD6", "203B9_0342" }, + { "1FD7", "303B9_0308_0342" }, + { "1FD8", "20399_0306" }, + { "1FD9", "20399_0304" }, + { "1FDA", "20399_0300" }, + { "1FDB", "20399_0301" }, + { "1FDD", "21FFE_0300" }, + { "1FDE", "21FFE_0301" }, + { "1FDF", "21FFE_0342" }, + { "1FE0", "203C5_0306" }, + { "1FE1", "203C5_0304" }, + { "1FE2", "303C5_0308_0300" }, + { "1FE3", "303C5_0308_0301" }, + { "1FE4", "203C1_0313" }, + { "1FE5", "203C1_0314" }, + { "1FE6", "203C5_0342" }, + { "1FE7", "303C5_0308_0342" }, + { "1FE8", "203A5_0306" }, + { "1FE9", "203A5_0304" }, + { "1FEA", "203A5_0300" }, + { "1FEB", "203A5_0301" }, + { "1FEC", "203A1_0314" }, + { "1FED", "200A8_0300" }, + { "1FEE", "200A8_0301" }, + { "1FEF", "10060" }, + { "1FF2", "303C9_0300_0345" }, + { "1FF3", "203C9_0345" }, + { "1FF4", "303C9_0301_0345" }, + { "1FF6", "203C9_0342" }, + { "1FF7", "303C9_0342_0345" }, + { "1FF8", "2039F_0300" }, + { "1FF9", "2039F_0301" }, + { "1FFA", "203A9_0300" }, + { "1FFB", "203A9_0301" }, + { "1FFC", "203A9_0345" }, + { "1FFD", "100B4" }, + { "2000", "12002" }, + { "2001", "12003" }, + { "2126", "103A9" }, + { "212A", "1004B" }, + { "212B", "20041_030A" }, + { "219A", "22190_0338" }, + { "219B", "22192_0338" }, + { "21AE", "22194_0338" }, + { "21CD", "221D0_0338" }, + { "21CE", "221D4_0338" }, + { "21CF", "221D2_0338" }, + { "2204", "22203_0338" }, + { "2209", "22208_0338" }, + { "220C", "2220B_0338" }, + { "2224", "22223_0338" }, + { "2226", "22225_0338" }, + { "2241", "2223C_0338" }, + { "2244", "22243_0338" }, + { "2247", "22245_0338" }, + { "2249", "22248_0338" }, + { "2260", "2003D_0338" }, + { "2262", "22261_0338" }, + { "226D", "2224D_0338" }, + { "226E", "2003C_0338" }, + { "226F", "2003E_0338" }, + { "2270", "22264_0338" }, + { "2271", "22265_0338" }, + { "2274", "22272_0338" }, + { "2275", "22273_0338" }, + { "2278", "22276_0338" }, + { "2279", "22277_0338" }, + { "2280", "2227A_0338" }, + { "2281", "2227B_0338" }, + { "2284", "22282_0338" }, + { "2285", "22283_0338" }, + { "2288", "22286_0338" }, + { "2289", "22287_0338" }, + { "22AC", "222A2_0338" }, + { "22AD", "222A8_0338" }, + { "22AE", "222A9_0338" }, + { "22AF", "222AB_0338" }, + { "22E0", "2227C_0338" }, + { "22E1", "2227D_0338" }, + { "22E2", "22291_0338" }, + { "22E3", "22292_0338" }, + { "22EA", "222B2_0338" }, + { "22EB", "222B3_0338" }, + { "22EC", "222B4_0338" }, + { "22ED", "222B5_0338" }, + { "2329", "13008" }, + { "232A", "13009" }, + { "2ADC", "22ADD_0338" }, + { "304C", "2304B_3099" }, + { "304E", "2304D_3099" }, + { "3050", "2304F_3099" }, + { "3052", "23051_3099" }, + { "3054", "23053_3099" }, + { "3056", "23055_3099" }, + { "3058", "23057_3099" }, + { "305A", "23059_3099" }, + { "305C", "2305B_3099" }, + { "305E", "2305D_3099" }, + { "3060", "2305F_3099" }, + { "3062", "23061_3099" }, + { "3065", "23064_3099" }, + { "3067", "23066_3099" }, + { "3069", "23068_3099" }, + { "3070", "2306F_3099" }, + { "3071", "2306F_309A" }, + { "3073", "23072_3099" }, + { "3074", "23072_309A" }, + { "3076", "23075_3099" }, + { "3077", "23075_309A" }, + { "3079", "23078_3099" }, + { "307A", "23078_309A" }, + { "307C", "2307B_3099" }, + { "307D", "2307B_309A" }, + { "3094", "23046_3099" }, + { "309E", "2309D_3099" }, + { "30AC", "230AB_3099" }, + { "30AE", "230AD_3099" }, + { "30B0", "230AF_3099" }, + { "30B2", "230B1_3099" }, + { "30B4", "230B3_3099" }, + { "30B6", "230B5_3099" }, + { "30B8", "230B7_3099" }, + { "30BA", "230B9_3099" }, + { "30BC", "230BB_3099" }, + { "30BE", "230BD_3099" }, + { "30C0", "230BF_3099" }, + { "30C2", "230C1_3099" }, + { "30C5", "230C4_3099" }, + { "30C7", "230C6_3099" }, + { "30C9", "230C8_3099" }, + { "30D0", "230CF_3099" }, + { "30D1", "230CF_309A" }, + { "30D3", "230D2_3099" }, + { "30D4", "230D2_309A" }, + { "30D6", "230D5_3099" }, + { "30D7", "230D5_309A" }, + { "30D9", "230D8_3099" }, + { "30DA", "230D8_309A" }, + { "30DC", "230DB_3099" }, + { "30DD", "230DB_309A" }, + { "30F4", "230A6_3099" }, + { "30F7", "230EF_3099" }, + { "30F8", "230F0_3099" }, + { "30F9", "230F1_3099" }, + { "30FA", "230F2_3099" }, + { "30FE", "230FD_3099" }, + { "F900", "18C48" }, + { "F901", "166F4" }, + { "F902", "18ECA" }, + { "F903", "18CC8" }, + { "F904", "16ED1" }, + { "F905", "14E32" }, + { "F906", "153E5" }, + { "F907", "19F9C" }, + { "F908", "19F9C" }, + { "F909", "15951" }, + { "F90A", "191D1" }, + { "F90B", "15587" }, + { "F90C", "15948" }, + { "F90D", "161F6" }, + { "F90E", "17669" }, + { "F90F", "17F85" }, + { "F910", "1863F" }, + { "F911", "187BA" }, + { "F912", "188F8" }, + { "F913", "1908F" }, + { "F914", "16A02" }, + { "F915", "16D1B" }, + { "F916", "170D9" }, + { "F917", "173DE" }, + { "F918", "1843D" }, + { "F919", "1916A" }, + { "F91A", "199F1" }, + { "F91B", "14E82" }, + { "F91C", "15375" }, + { "F91D", "16B04" }, + { "F91E", "1721B" }, + { "F91F", "1862D" }, + { "F920", "19E1E" }, + { "F921", "15D50" }, + { "F922", "16FEB" }, + { "F923", "185CD" }, + { "F924", "18964" }, + { "F925", "162C9" }, + { "F926", "181D8" }, + { "F927", "1881F" }, + { "F928", "15ECA" }, + { "F929", "16717" }, + { "F92A", "16D6A" }, + { "F92B", "172FC" }, + { "F92C", "190CE" }, + { "F92D", "14F86" }, + { "F92E", "151B7" }, + { "F92F", "152DE" }, + { "F930", "164C4" }, + { "F931", "16AD3" }, + { "F932", "17210" }, + { "F933", "176E7" }, + { "F934", "18001" }, + { "F935", "18606" }, + { "F936", "1865C" }, + { "F937", "18DEF" }, + { "F938", "19732" }, + { "F939", "19B6F" }, + { "F93A", "19DFA" }, + { "F93B", "1788C" }, + { "F93C", "1797F" }, + { "F93D", "17DA0" }, + { "F93E", "183C9" }, + { "F93F", "19304" }, + { "F940", "19E7F" }, + { "F941", "18AD6" }, + { "F942", "158DF" }, + { "F943", "15F04" }, + { "F944", "17C60" }, + { "F945", "1807E" }, + { "F946", "17262" }, + { "F947", "178CA" }, + { "F948", "18CC2" }, + { "F949", "196F7" }, + { "F94A", "158D8" }, + { "F94B", "15C62" }, + { "F94C", "16A13" }, + { "F94D", "16DDA" }, + { "F94E", "16F0F" }, + { "F94F", "17D2F" }, + { "F950", "17E37" }, + { "F951", "1964B" }, + { "F952", "152D2" }, + { "F953", "1808B" }, + { "F954", "151DC" }, + { "F955", "151CC" }, + { "F956", "17A1C" }, + { "F957", "17DBE" }, + { "F958", "183F1" }, + { "F959", "19675" }, + { "F95A", "18B80" }, + { "F95B", "162CF" }, + { "F95C", "16A02" }, + { "F95D", "18AFE" }, + { "F95E", "14E39" }, + { "F95F", "15BE7" }, + { "F960", "16012" }, + { "F961", "17387" }, + { "F962", "17570" }, + { "F963", "15317" }, + { "F964", "178FB" }, + { "F965", "14FBF" }, + { "F966", "15FA9" }, + { "F967", "14E0D" }, + { "F968", "16CCC" }, + { "F969", "16578" }, + { "F96A", "17D22" }, + { "F96B", "153C3" }, + { "F96C", "1585E" }, + { "F96D", "17701" }, + { "F96E", "18449" }, + { "F96F", "18AAA" }, + { "F970", "16BBA" }, + { "F971", "18FB0" }, + { "F972", "16C88" }, + { "F973", "162FE" }, + { "F974", "182E5" }, + { "F975", "163A0" }, + { "F976", "17565" }, + { "F977", "14EAE" }, + { "F978", "15169" }, + { "F979", "151C9" }, + { "F97A", "16881" }, + { "F97B", "17CE7" }, + { "F97C", "1826F" }, + { "F97D", "18AD2" }, + { "F97E", "191CF" }, + { "F97F", "152F5" }, + { "F980", "15442" }, + { "F981", "15973" }, + { "F982", "15EEC" }, + { "F983", "165C5" }, + { "F984", "16FFE" }, + { "F985", "1792A" }, + { "F986", "195AD" }, + { "F987", "19A6A" }, + { "F988", "19E97" }, + { "F989", "19ECE" }, + { "F98A", "1529B" }, + { "F98B", "166C6" }, + { "F98C", "16B77" }, + { "F98D", "18F62" }, + { "F98E", "15E74" }, + { "F98F", "16190" }, + { "F990", "16200" }, + { "F991", "1649A" }, + { "F992", "16F23" }, + { "F993", "17149" }, + { "F994", "17489" }, + { "F995", "179CA" }, + { "F996", "17DF4" }, + { "F997", "1806F" }, + { "F998", "18F26" }, + { "F999", "184EE" }, + { "F99A", "19023" }, + { "F99B", "1934A" }, + { "F99C", "15217" }, + { "F99D", "152A3" }, + { "F99E", "154BD" }, + { "F99F", "170C8" }, + { "F9A0", "188C2" }, + { "F9A1", "18AAA" }, + { "F9A2", "15EC9" }, + { "F9A3", "15FF5" }, + { "F9A4", "1637B" }, + { "F9A5", "16BAE" }, + { "F9A6", "17C3E" }, + { "F9A7", "17375" }, + { "F9A8", "14EE4" }, + { "F9A9", "156F9" }, + { "F9AA", "15BE7" }, + { "F9AB", "15DBA" }, + { "F9AC", "1601C" }, + { "F9AD", "173B2" }, + { "F9AE", "17469" }, + { "F9AF", "17F9A" }, + { "F9B0", "18046" }, + { "F9B1", "19234" }, + { "F9B2", "196F6" }, + { "F9B3", "19748" }, + { "F9B4", "19818" }, + { "F9B5", "14F8B" }, + { "F9B6", "179AE" }, + { "F9B7", "191B4" }, + { "F9B8", "196B8" }, + { "F9B9", "160E1" }, + { "F9BA", "14E86" }, + { "F9BB", "150DA" }, + { "F9BC", "15BEE" }, + { "F9BD", "15C3F" }, + { "F9BE", "16599" }, + { "F9BF", "16A02" }, + { "F9C0", "171CE" }, + { "F9C1", "17642" }, + { "F9C2", "184FC" }, + { "F9C3", "1907C" }, + { "F9C4", "19F8D" }, + { "F9C5", "16688" }, + { "F9C6", "1962E" }, + { "F9C7", "15289" }, + { "F9C8", "1677B" }, + { "F9C9", "167F3" }, + { "F9CA", "16D41" }, + { "F9CB", "16E9C" }, + { "F9CC", "17409" }, + { "F9CD", "17559" }, + { "F9CE", "1786B" }, + { "F9CF", "17D10" }, + { "F9D0", "1985E" }, + { "F9D1", "1516D" }, + { "F9D2", "1622E" }, + { "F9D3", "19678" }, + { "F9D4", "1502B" }, + { "F9D5", "15D19" }, + { "F9D6", "16DEA" }, + { "F9D7", "18F2A" }, + { "F9D8", "15F8B" }, + { "F9D9", "16144" }, + { "F9DA", "16817" }, + { "F9DB", "17387" }, + { "F9DC", "19686" }, + { "F9DD", "15229" }, + { "F9DE", "1540F" }, + { "F9DF", "15C65" }, + { "F9E0", "16613" }, + { "F9E1", "1674E" }, + { "F9E2", "168A8" }, + { "F9E3", "16CE5" }, + { "F9E4", "17406" }, + { "F9E5", "175E2" }, + { "F9E6", "17F79" }, + { "F9E7", "188CF" }, + { "F9E8", "188E1" }, + { "F9E9", "191CC" }, + { "F9EA", "196E2" }, + { "F9EB", "1533F" }, + { "F9EC", "16EBA" }, + { "F9ED", "1541D" }, + { "F9EE", "171D0" }, + { "F9EF", "17498" }, + { "F9F0", "185FA" }, + { "F9F1", "196A3" }, + { "F9F2", "19C57" }, + { "F9F3", "19E9F" }, + { "F9F4", "16797" }, + { "F9F5", "16DCB" }, + { "F9F6", "181E8" }, + { "F9F7", "17ACB" }, + { "F9F8", "17B20" }, + { "F9F9", "17C92" }, + { "F9FA", "172C0" }, + { "F9FB", "17099" }, + { "F9FC", "18B58" }, + { "F9FD", "14EC0" }, + { "F9FE", "18336" }, + { "F9FF", "1523A" }, + { "FA00", "15207" }, + { "FA01", "15EA6" }, + { "FA02", "162D3" }, + { "FA03", "17CD6" }, + { "FA04", "15B85" }, + { "FA05", "16D1E" }, + { "FA06", "166B4" }, + { "FA07", "18F3B" }, + { "FA08", "1884C" }, + { "FA09", "1964D" }, + { "FA0A", "1898B" }, + { "FA0B", "15ED3" }, + { "FA0C", "15140" }, + { "FA0D", "155C0" }, + { "FA10", "1585A" }, + { "FA12", "16674" }, + { "FA15", "151DE" }, + { "FA16", "1732A" }, + { "FA17", "176CA" }, + { "FA18", "1793C" }, + { "FA19", "1795E" }, + { "FA1A", "17965" }, + { "FA1B", "1798F" }, + { "FA1C", "19756" }, + { "FA1D", "17CBE" }, + { "FA1E", "17FBD" }, + { "FA20", "18612" }, + { "FA22", "18AF8" }, + { "FA25", "19038" }, + { "FA26", "190FD" }, + { "FA2A", "198EF" }, + { "FA2B", "198FC" }, + { "FA2C", "19928" }, + { "FA2D", "19DB4" }, + { "FA2E", "190DE" }, + { "FA2F", "196B7" }, + { "FA30", "14FAE" }, + { "FA31", "150E7" }, + { "FA32", "1514D" }, + { "FA33", "152C9" }, + { "FA34", "152E4" }, + { "FA35", "15351" }, + { "FA36", "1559D" }, + { "FA37", "15606" }, + { "FA38", "15668" }, + { "FA39", "15840" }, + { "FA3A", "158A8" }, + { "FA3B", "15C64" }, + { "FA3C", "15C6E" }, + { "FA3D", "16094" }, + { "FA3E", "16168" }, + { "FA3F", "1618E" }, + { "FA40", "161F2" }, + { "FA41", "1654F" }, + { "FA42", "165E2" }, + { "FA43", "16691" }, + { "FA44", "16885" }, + { "FA45", "16D77" }, + { "FA46", "16E1A" }, + { "FA47", "16F22" }, + { "FA48", "1716E" }, + { "FA49", "1722B" }, + { "FA4A", "17422" }, + { "FA4B", "17891" }, + { "FA4C", "1793E" }, + { "FA4D", "17949" }, + { "FA4E", "17948" }, + { "FA4F", "17950" }, + { "FA50", "17956" }, + { "FA51", "1795D" }, + { "FA52", "1798D" }, + { "FA53", "1798E" }, + { "FA54", "17A40" }, + { "FA55", "17A81" }, + { "FA56", "17BC0" }, + { "FA57", "17DF4" }, + { "FA58", "17E09" }, + { "FA59", "17E41" }, + { "FA5A", "17F72" }, + { "FA5B", "18005" }, + { "FA5C", "181ED" }, + { "FA5D", "18279" }, + { "FA5E", "18279" }, + { "FA5F", "18457" }, + { "FA60", "18910" }, + { "FA61", "18996" }, + { "FA62", "18B01" }, + { "FA63", "18B39" }, + { "FA64", "18CD3" }, + { "FA65", "18D08" }, + { "FA66", "18FB6" }, + { "FA67", "19038" }, + { "FA68", "196E3" }, + { "FA69", "197FF" }, + { "FA6A", "1983B" }, + { "FA6B", "16075" }, + { "FA6C", "1242EE" }, + { "FA6D", "18218" }, + { "FA70", "14E26" }, + { "FA71", "151B5" }, + { "FA72", "15168" }, + { "FA73", "14F80" }, + { "FA74", "15145" }, + { "FA75", "15180" }, + { "FA76", "152C7" }, + { "FA77", "152FA" }, + { "FA78", "1559D" }, + { "FA79", "15555" }, + { "FA7A", "15599" }, + { "FA7B", "155E2" }, + { "FA7C", "1585A" }, + { "FA7D", "158B3" }, + { "FA7E", "15944" }, + { "FA7F", "15954" }, + { "FA80", "15A62" }, + { "FA81", "15B28" }, + { "FA82", "15ED2" }, + { "FA83", "15ED9" }, + { "FA84", "15F69" }, + { "FA85", "15FAD" }, + { "FA86", "160D8" }, + { "FA87", "1614E" }, + { "FA88", "16108" }, + { "FA89", "1618E" }, + { "FA8A", "16160" }, + { "FA8B", "161F2" }, + { "FA8C", "16234" }, + { "FA8D", "163C4" }, + { "FA8E", "1641C" }, + { "FA8F", "16452" }, + { "FA90", "16556" }, + { "FA91", "16674" }, + { "FA92", "16717" }, + { "FA93", "1671B" }, + { "FA94", "16756" }, + { "FA95", "16B79" }, + { "FA96", "16BBA" }, + { "FA97", "16D41" }, + { "FA98", "16EDB" }, + { "FA99", "16ECB" }, + { "FA9A", "16F22" }, + { "FA9B", "1701E" }, + { "FA9C", "1716E" }, + { "FA9D", "177A7" }, + { "FA9E", "17235" }, + { "FA9F", "172AF" }, + { "FAA0", "1732A" }, + { "FAA1", "17471" }, + { "FAA2", "17506" }, + { "FAA3", "1753B" }, + { "FAA4", "1761D" }, + { "FAA5", "1761F" }, + { "FAA6", "176CA" }, + { "FAA7", "176DB" }, + { "FAA8", "176F4" }, + { "FAA9", "1774A" }, + { "FAAA", "17740" }, + { "FAAB", "178CC" }, + { "FAAC", "17AB1" }, + { "FAAD", "17BC0" }, + { "FAAE", "17C7B" }, + { "FAAF", "17D5B" }, + { "FAB0", "17DF4" }, + { "FAB1", "17F3E" }, + { "FAB2", "18005" }, + { "FAB3", "18352" }, + { "FAB4", "183EF" }, + { "FAB5", "18779" }, + { "FAB6", "18941" }, + { "FAB7", "18986" }, + { "FAB8", "18996" }, + { "FAB9", "18ABF" }, + { "FABA", "18AF8" }, + { "FABB", "18ACB" }, + { "FABC", "18B01" }, + { "FABD", "18AFE" }, + { "FABE", "18AED" }, + { "FABF", "18B39" }, + { "FAC0", "18B8A" }, + { "FAC1", "18D08" }, + { "FAC2", "18F38" }, + { "FAC3", "19072" }, + { "FAC4", "19199" }, + { "FAC5", "19276" }, + { "FAC6", "1967C" }, + { "FAC7", "196E3" }, + { "FAC8", "19756" }, + { "FAC9", "197DB" }, + { "FACA", "197FF" }, + { "FACB", "1980B" }, + { "FACC", "1983B" }, + { "FACD", "19B12" }, + { "FACE", "19F9C" }, + { "FACF", "12284A" }, + { "FAD0", "122844" }, + { "FAD1", "1233D5" }, + { "FAD2", "13B9D" }, + { "FAD3", "14018" }, + { "FAD4", "14039" }, + { "FAD5", "125249" }, + { "FAD6", "125CD0" }, + { "FAD7", "127ED3" }, + { "FAD8", "19F43" }, + { "FAD9", "19F8E" }, + { "FB1D", "205D9_05B4" }, + { "FB1F", "205F2_05B7" }, + { "FB2A", "205E9_05C1" }, + { "FB2B", "205E9_05C2" }, + { "FB2C", "305E9_05BC_05C1" }, + { "FB2D", "305E9_05BC_05C2" }, + { "FB2E", "205D0_05B7" }, + { "FB2F", "205D0_05B8" }, + { "FB30", "205D0_05BC" }, + { "FB31", "205D1_05BC" }, + { "FB32", "205D2_05BC" }, + { "FB33", "205D3_05BC" }, + { "FB34", "205D4_05BC" }, + { "FB35", "205D5_05BC" }, + { "FB36", "205D6_05BC" }, + { "FB38", "205D8_05BC" }, + { "FB39", "205D9_05BC" }, + { "FB3A", "205DA_05BC" }, + { "FB3B", "205DB_05BC" }, + { "FB3C", "205DC_05BC" }, + { "FB3E", "205DE_05BC" }, + { "FB40", "205E0_05BC" }, + { "FB41", "205E1_05BC" }, + { "FB43", "205E3_05BC" }, + { "FB44", "205E4_05BC" }, + { "FB46", "205E6_05BC" }, + { "FB47", "205E7_05BC" }, + { "FB48", "205E8_05BC" }, + { "FB49", "205E9_05BC" }, + { "FB4A", "205EA_05BC" }, + { "FB4B", "205D5_05B9" }, + { "FB4C", "205D1_05BF" }, + { "FB4D", "205DB_05BF" }, + { "FB4E", "205E4_05BF" }, + { "1109A", "211099_110BA" }, + { "1109C", "21109B_110BA" }, + { "110AB", "2110A5_110BA" }, + { "1112E", "211131_11127" }, + { "1112F", "211132_11127" }, + { "1134B", "211347_1133E" }, + { "1134C", "211347_11357" }, + { "114BB", "2114B9_114BA" }, + { "114BC", "2114B9_114B0" }, + { "114BE", "2114B9_114BD" }, + { "115BA", "2115B8_115AF" }, + { "115BB", "2115B9_115AF" }, + { "1D15E", "21D157_1D165" }, + { "1D15F", "21D158_1D165" }, + { "1D160", "31D158_1D165_1D16E" }, + { "1D161", "31D158_1D165_1D16F" }, + { "1D162", "31D158_1D165_1D170" }, + { "1D163", "31D158_1D165_1D171" }, + { "1D164", "31D158_1D165_1D172" }, + { "1D1BB", "21D1B9_1D165" }, + { "1D1BC", "21D1BA_1D165" }, + { "1D1BD", "31D1B9_1D165_1D16E" }, + { "1D1BE", "31D1BA_1D165_1D16E" }, + { "1D1BF", "31D1B9_1D165_1D16F" }, + { "1D1C0", "31D1BA_1D165_1D16F" }, + { "2F800", "14E3D" }, + { "2F801", "14E38" }, + { "2F802", "14E41" }, + { "2F803", "120122" }, + { "2F804", "14F60" }, + { "2F805", "14FAE" }, + { "2F806", "14FBB" }, + { "2F807", "15002" }, + { "2F808", "1507A" }, + { "2F809", "15099" }, + { "2F80A", "150E7" }, + { "2F80B", "150CF" }, + { "2F80C", "1349E" }, + { "2F80D", "12063A" }, + { "2F80E", "1514D" }, + { "2F80F", "15154" }, + { "2F810", "15164" }, + { "2F811", "15177" }, + { "2F812", "12051C" }, + { "2F813", "134B9" }, + { "2F814", "15167" }, + { "2F815", "1518D" }, + { "2F816", "12054B" }, + { "2F817", "15197" }, + { "2F818", "151A4" }, + { "2F819", "14ECC" }, + { "2F81A", "151AC" }, + { "2F81B", "151B5" }, + { "2F81C", "1291DF" }, + { "2F81D", "151F5" }, + { "2F81E", "15203" }, + { "2F81F", "134DF" }, + { "2F820", "1523B" }, + { "2F821", "15246" }, + { "2F822", "15272" }, + { "2F823", "15277" }, + { "2F824", "13515" }, + { "2F825", "152C7" }, + { "2F826", "152C9" }, + { "2F827", "152E4" }, + { "2F828", "152FA" }, + { "2F829", "15305" }, + { "2F82A", "15306" }, + { "2F82B", "15317" }, + { "2F82C", "15349" }, + { "2F82D", "15351" }, + { "2F82E", "1535A" }, + { "2F82F", "15373" }, + { "2F830", "1537D" }, + { "2F831", "1537F" }, + { "2F832", "1537F" }, + { "2F833", "1537F" }, + { "2F834", "120A2C" }, + { "2F835", "17070" }, + { "2F836", "153CA" }, + { "2F837", "153DF" }, + { "2F838", "120B63" }, + { "2F839", "153EB" }, + { "2F83A", "153F1" }, + { "2F83B", "15406" }, + { "2F83C", "1549E" }, + { "2F83D", "15438" }, + { "2F83E", "15448" }, + { "2F83F", "15468" }, + { "2F840", "154A2" }, + { "2F841", "154F6" }, + { "2F842", "15510" }, + { "2F843", "15553" }, + { "2F844", "15563" }, + { "2F845", "15584" }, + { "2F846", "15584" }, + { "2F847", "15599" }, + { "2F848", "155AB" }, + { "2F849", "155B3" }, + { "2F84A", "155C2" }, + { "2F84B", "15716" }, + { "2F84C", "15606" }, + { "2F84D", "15717" }, + { "2F84E", "15651" }, + { "2F84F", "15674" }, + { "2F850", "15207" }, + { "2F851", "158EE" }, + { "2F852", "157CE" }, + { "2F853", "157F4" }, + { "2F854", "1580D" }, + { "2F855", "1578B" }, + { "2F856", "15832" }, + { "2F857", "15831" }, + { "2F858", "158AC" }, + { "2F859", "1214E4" }, + { "2F85A", "158F2" }, + { "2F85B", "158F7" }, + { "2F85C", "15906" }, + { "2F85D", "1591A" }, + { "2F85E", "15922" }, + { "2F85F", "15962" }, + { "2F860", "1216A8" }, + { "2F861", "1216EA" }, + { "2F862", "159EC" }, + { "2F863", "15A1B" }, + { "2F864", "15A27" }, + { "2F865", "159D8" }, + { "2F866", "15A66" }, + { "2F867", "136EE" }, + { "2F868", "136FC" }, + { "2F869", "15B08" }, + { "2F86A", "15B3E" }, + { "2F86B", "15B3E" }, + { "2F86C", "1219C8" }, + { "2F86D", "15BC3" }, + { "2F86E", "15BD8" }, + { "2F86F", "15BE7" }, + { "2F870", "15BF3" }, + { "2F871", "121B18" }, + { "2F872", "15BFF" }, + { "2F873", "15C06" }, + { "2F874", "15F53" }, + { "2F875", "15C22" }, + { "2F876", "13781" }, + { "2F877", "15C60" }, + { "2F878", "15C6E" }, + { "2F879", "15CC0" }, + { "2F87A", "15C8D" }, + { "2F87B", "121DE4" }, + { "2F87C", "15D43" }, + { "2F87D", "121DE6" }, + { "2F87E", "15D6E" }, + { "2F87F", "15D6B" }, + { "2F880", "15D7C" }, + { "2F881", "15DE1" }, + { "2F882", "15DE2" }, + { "2F883", "1382F" }, + { "2F884", "15DFD" }, + { "2F885", "15E28" }, + { "2F886", "15E3D" }, + { "2F887", "15E69" }, + { "2F888", "13862" }, + { "2F889", "122183" }, + { "2F88A", "1387C" }, + { "2F88B", "15EB0" }, + { "2F88C", "15EB3" }, + { "2F88D", "15EB6" }, + { "2F88E", "15ECA" }, + { "2F88F", "12A392" }, + { "2F890", "15EFE" }, + { "2F891", "122331" }, + { "2F892", "122331" }, + { "2F893", "18201" }, + { "2F894", "15F22" }, + { "2F895", "15F22" }, + { "2F896", "138C7" }, + { "2F897", "1232B8" }, + { "2F898", "1261DA" }, + { "2F899", "15F62" }, + { "2F89A", "15F6B" }, + { "2F89B", "138E3" }, + { "2F89C", "15F9A" }, + { "2F89D", "15FCD" }, + { "2F89E", "15FD7" }, + { "2F89F", "15FF9" }, + { "2F8A0", "16081" }, + { "2F8A1", "1393A" }, + { "2F8A2", "1391C" }, + { "2F8A3", "16094" }, + { "2F8A4", "1226D4" }, + { "2F8A5", "160C7" }, + { "2F8A6", "16148" }, + { "2F8A7", "1614C" }, + { "2F8A8", "1614E" }, + { "2F8A9", "1614C" }, + { "2F8AA", "1617A" }, + { "2F8AB", "1618E" }, + { "2F8AC", "161B2" }, + { "2F8AD", "161A4" }, + { "2F8AE", "161AF" }, + { "2F8AF", "161DE" }, + { "2F8B0", "161F2" }, + { "2F8B1", "161F6" }, + { "2F8B2", "16210" }, + { "2F8B3", "1621B" }, + { "2F8B4", "1625D" }, + { "2F8B5", "162B1" }, + { "2F8B6", "162D4" }, + { "2F8B7", "16350" }, + { "2F8B8", "122B0C" }, + { "2F8B9", "1633D" }, + { "2F8BA", "162FC" }, + { "2F8BB", "16368" }, + { "2F8BC", "16383" }, + { "2F8BD", "163E4" }, + { "2F8BE", "122BF1" }, + { "2F8BF", "16422" }, + { "2F8C0", "163C5" }, + { "2F8C1", "163A9" }, + { "2F8C2", "13A2E" }, + { "2F8C3", "16469" }, + { "2F8C4", "1647E" }, + { "2F8C5", "1649D" }, + { "2F8C6", "16477" }, + { "2F8C7", "13A6C" }, + { "2F8C8", "1654F" }, + { "2F8C9", "1656C" }, + { "2F8CA", "12300A" }, + { "2F8CB", "165E3" }, + { "2F8CC", "166F8" }, + { "2F8CD", "16649" }, + { "2F8CE", "13B19" }, + { "2F8CF", "16691" }, + { "2F8D0", "13B08" }, + { "2F8D1", "13AE4" }, + { "2F8D2", "15192" }, + { "2F8D3", "15195" }, + { "2F8D4", "16700" }, + { "2F8D5", "1669C" }, + { "2F8D6", "180AD" }, + { "2F8D7", "143D9" }, + { "2F8D8", "16717" }, + { "2F8D9", "1671B" }, + { "2F8DA", "16721" }, + { "2F8DB", "1675E" }, + { "2F8DC", "16753" }, + { "2F8DD", "1233C3" }, + { "2F8DE", "13B49" }, + { "2F8DF", "167FA" }, + { "2F8E0", "16785" }, + { "2F8E1", "16852" }, + { "2F8E2", "16885" }, + { "2F8E3", "12346D" }, + { "2F8E4", "1688E" }, + { "2F8E5", "1681F" }, + { "2F8E6", "16914" }, + { "2F8E7", "13B9D" }, + { "2F8E8", "16942" }, + { "2F8E9", "169A3" }, + { "2F8EA", "169EA" }, + { "2F8EB", "16AA8" }, + { "2F8EC", "1236A3" }, + { "2F8ED", "16ADB" }, + { "2F8EE", "13C18" }, + { "2F8EF", "16B21" }, + { "2F8F0", "1238A7" }, + { "2F8F1", "16B54" }, + { "2F8F2", "13C4E" }, + { "2F8F3", "16B72" }, + { "2F8F4", "16B9F" }, + { "2F8F5", "16BBA" }, + { "2F8F6", "16BBB" }, + { "2F8F7", "123A8D" }, + { "2F8F8", "121D0B" }, + { "2F8F9", "123AFA" }, + { "2F8FA", "16C4E" }, + { "2F8FB", "123CBC" }, + { "2F8FC", "16CBF" }, + { "2F8FD", "16CCD" }, + { "2F8FE", "16C67" }, + { "2F8FF", "16D16" }, + { "2F900", "16D3E" }, + { "2F901", "16D77" }, + { "2F902", "16D41" }, + { "2F903", "16D69" }, + { "2F904", "16D78" }, + { "2F905", "16D85" }, + { "2F906", "123D1E" }, + { "2F907", "16D34" }, + { "2F908", "16E2F" }, + { "2F909", "16E6E" }, + { "2F90A", "13D33" }, + { "2F90B", "16ECB" }, + { "2F90C", "16EC7" }, + { "2F90D", "123ED1" }, + { "2F90E", "16DF9" }, + { "2F90F", "16F6E" }, + { "2F910", "123F5E" }, + { "2F911", "123F8E" }, + { "2F912", "16FC6" }, + { "2F913", "17039" }, + { "2F914", "1701E" }, + { "2F915", "1701B" }, + { "2F916", "13D96" }, + { "2F917", "1704A" }, + { "2F918", "1707D" }, + { "2F919", "17077" }, + { "2F91A", "170AD" }, + { "2F91B", "120525" }, + { "2F91C", "17145" }, + { "2F91D", "124263" }, + { "2F91E", "1719C" }, + { "2F91F", "1243AB" }, + { "2F920", "17228" }, + { "2F921", "17235" }, + { "2F922", "17250" }, + { "2F923", "124608" }, + { "2F924", "17280" }, + { "2F925", "17295" }, + { "2F926", "124735" }, + { "2F927", "124814" }, + { "2F928", "1737A" }, + { "2F929", "1738B" }, + { "2F92A", "13EAC" }, + { "2F92B", "173A5" }, + { "2F92C", "13EB8" }, + { "2F92D", "13EB8" }, + { "2F92E", "17447" }, + { "2F92F", "1745C" }, + { "2F930", "17471" }, + { "2F931", "17485" }, + { "2F932", "174CA" }, + { "2F933", "13F1B" }, + { "2F934", "17524" }, + { "2F935", "124C36" }, + { "2F936", "1753E" }, + { "2F937", "124C92" }, + { "2F938", "17570" }, + { "2F939", "12219F" }, + { "2F93A", "17610" }, + { "2F93B", "124FA1" }, + { "2F93C", "124FB8" }, + { "2F93D", "125044" }, + { "2F93E", "13FFC" }, + { "2F93F", "14008" }, + { "2F940", "176F4" }, + { "2F941", "1250F3" }, + { "2F942", "1250F2" }, + { "2F943", "125119" }, + { "2F944", "125133" }, + { "2F945", "1771E" }, + { "2F946", "1771F" }, + { "2F947", "1771F" }, + { "2F948", "1774A" }, + { "2F949", "14039" }, + { "2F94A", "1778B" }, + { "2F94B", "14046" }, + { "2F94C", "14096" }, + { "2F94D", "12541D" }, + { "2F94E", "1784E" }, + { "2F94F", "1788C" }, + { "2F950", "178CC" }, + { "2F951", "140E3" }, + { "2F952", "125626" }, + { "2F953", "17956" }, + { "2F954", "12569A" }, + { "2F955", "1256C5" }, + { "2F956", "1798F" }, + { "2F957", "179EB" }, + { "2F958", "1412F" }, + { "2F959", "17A40" }, + { "2F95A", "17A4A" }, + { "2F95B", "17A4F" }, + { "2F95C", "12597C" }, + { "2F95D", "125AA7" }, + { "2F95E", "125AA7" }, + { "2F95F", "17AEE" }, + { "2F960", "14202" }, + { "2F961", "125BAB" }, + { "2F962", "17BC6" }, + { "2F963", "17BC9" }, + { "2F964", "14227" }, + { "2F965", "125C80" }, + { "2F966", "17CD2" }, + { "2F967", "142A0" }, + { "2F968", "17CE8" }, + { "2F969", "17CE3" }, + { "2F96A", "17D00" }, + { "2F96B", "125F86" }, + { "2F96C", "17D63" }, + { "2F96D", "14301" }, + { "2F96E", "17DC7" }, + { "2F96F", "17E02" }, + { "2F970", "17E45" }, + { "2F971", "14334" }, + { "2F972", "126228" }, + { "2F973", "126247" }, + { "2F974", "14359" }, + { "2F975", "1262D9" }, + { "2F976", "17F7A" }, + { "2F977", "12633E" }, + { "2F978", "17F95" }, + { "2F979", "17FFA" }, + { "2F97A", "18005" }, + { "2F97B", "1264DA" }, + { "2F97C", "126523" }, + { "2F97D", "18060" }, + { "2F97E", "1265A8" }, + { "2F97F", "18070" }, + { "2F980", "12335F" }, + { "2F981", "143D5" }, + { "2F982", "180B2" }, + { "2F983", "18103" }, + { "2F984", "1440B" }, + { "2F985", "1813E" }, + { "2F986", "15AB5" }, + { "2F987", "1267A7" }, + { "2F988", "1267B5" }, + { "2F989", "123393" }, + { "2F98A", "12339C" }, + { "2F98B", "18201" }, + { "2F98C", "18204" }, + { "2F98D", "18F9E" }, + { "2F98E", "1446B" }, + { "2F98F", "18291" }, + { "2F990", "1828B" }, + { "2F991", "1829D" }, + { "2F992", "152B3" }, + { "2F993", "182B1" }, + { "2F994", "182B3" }, + { "2F995", "182BD" }, + { "2F996", "182E6" }, + { "2F997", "126B3C" }, + { "2F998", "182E5" }, + { "2F999", "1831D" }, + { "2F99A", "18363" }, + { "2F99B", "183AD" }, + { "2F99C", "18323" }, + { "2F99D", "183BD" }, + { "2F99E", "183E7" }, + { "2F99F", "18457" }, + { "2F9A0", "18353" }, + { "2F9A1", "183CA" }, + { "2F9A2", "183CC" }, + { "2F9A3", "183DC" }, + { "2F9A4", "126C36" }, + { "2F9A5", "126D6B" }, + { "2F9A6", "126CD5" }, + { "2F9A7", "1452B" }, + { "2F9A8", "184F1" }, + { "2F9A9", "184F3" }, + { "2F9AA", "18516" }, + { "2F9AB", "1273CA" }, + { "2F9AC", "18564" }, + { "2F9AD", "126F2C" }, + { "2F9AE", "1455D" }, + { "2F9AF", "14561" }, + { "2F9B0", "126FB1" }, + { "2F9B1", "1270D2" }, + { "2F9B2", "1456B" }, + { "2F9B3", "18650" }, + { "2F9B4", "1865C" }, + { "2F9B5", "18667" }, + { "2F9B6", "18669" }, + { "2F9B7", "186A9" }, + { "2F9B8", "18688" }, + { "2F9B9", "1870E" }, + { "2F9BA", "186E2" }, + { "2F9BB", "18779" }, + { "2F9BC", "18728" }, + { "2F9BD", "1876B" }, + { "2F9BE", "18786" }, + { "2F9BF", "145D7" }, + { "2F9C0", "187E1" }, + { "2F9C1", "18801" }, + { "2F9C2", "145F9" }, + { "2F9C3", "18860" }, + { "2F9C4", "18863" }, + { "2F9C5", "127667" }, + { "2F9C6", "188D7" }, + { "2F9C7", "188DE" }, + { "2F9C8", "14635" }, + { "2F9C9", "188FA" }, + { "2F9CA", "134BB" }, + { "2F9CB", "1278AE" }, + { "2F9CC", "127966" }, + { "2F9CD", "146BE" }, + { "2F9CE", "146C7" }, + { "2F9CF", "18AA0" }, + { "2F9D0", "18AED" }, + { "2F9D1", "18B8A" }, + { "2F9D2", "18C55" }, + { "2F9D3", "127CA8" }, + { "2F9D4", "18CAB" }, + { "2F9D5", "18CC1" }, + { "2F9D6", "18D1B" }, + { "2F9D7", "18D77" }, + { "2F9D8", "127F2F" }, + { "2F9D9", "120804" }, + { "2F9DA", "18DCB" }, + { "2F9DB", "18DBC" }, + { "2F9DC", "18DF0" }, + { "2F9DD", "1208DE" }, + { "2F9DE", "18ED4" }, + { "2F9DF", "18F38" }, + { "2F9E0", "1285D2" }, + { "2F9E1", "1285ED" }, + { "2F9E2", "19094" }, + { "2F9E3", "190F1" }, + { "2F9E4", "19111" }, + { "2F9E5", "12872E" }, + { "2F9E6", "1911B" }, + { "2F9E7", "19238" }, + { "2F9E8", "192D7" }, + { "2F9E9", "192D8" }, + { "2F9EA", "1927C" }, + { "2F9EB", "193F9" }, + { "2F9EC", "19415" }, + { "2F9ED", "128BFA" }, + { "2F9EE", "1958B" }, + { "2F9EF", "14995" }, + { "2F9F0", "195B7" }, + { "2F9F1", "128D77" }, + { "2F9F2", "149E6" }, + { "2F9F3", "196C3" }, + { "2F9F4", "15DB2" }, + { "2F9F5", "19723" }, + { "2F9F6", "129145" }, + { "2F9F7", "12921A" }, + { "2F9F8", "14A6E" }, + { "2F9F9", "14A76" }, + { "2F9FA", "197E0" }, + { "2F9FB", "12940A" }, + { "2F9FC", "14AB2" }, + { "2F9FD", "129496" }, + { "2F9FE", "1980B" }, + { "2F9FF", "1980B" }, + { "2FA00", "19829" }, + { "2FA01", "1295B6" }, + { "2FA02", "198E2" }, + { "2FA03", "14B33" }, + { "2FA04", "19929" }, + { "2FA05", "199A7" }, + { "2FA06", "199C2" }, + { "2FA07", "199FE" }, + { "2FA08", "14BCE" }, + { "2FA09", "129B30" }, + { "2FA0A", "19B12" }, + { "2FA0B", "19C40" }, + { "2FA0C", "19CFD" }, + { "2FA0D", "14CCE" }, + { "2FA0E", "14CED" }, + { "2FA0F", "19D67" }, + { "2FA10", "12A0CE" }, + { "2FA11", "14CF8" }, + { "2FA12", "12A105" }, + { "2FA13", "12A20E" }, + { "2FA14", "12A291" }, + { "2FA15", "19EBB" }, + { "2FA16", "14D56" }, + { "2FA17", "19EF9" }, + { "2FA18", "19EFE" }, + { "2FA19", "19F05" }, + { "2FA1A", "19F0F" }, + { "2FA1B", "19F16" }, + { "2FA1C", "19F3B" }, + { "2FA1D", "12A600" }, +}; + +// global constructor + +static struct unicode_decompose_init { + unicode_decompose_init(); +} _unicode_decompose_init; + +unicode_decompose_init::unicode_decompose_init() +{ + for (unsigned int i = 0; + i < sizeof(unicode_decompose_list)/sizeof(unicode_decompose_list[0]); + i++) { + unicode_decompose *dec = new unicode_decompose[1]; + dec->value = (char *)unicode_decompose_list[i].value; + unicode_decompose_table.define(unicode_decompose_list[i].key, dec); + } +} + +const char *decompose_unicode(const char *s) +{ + unicode_decompose *result = unicode_decompose_table.lookup(s); + return result ? result->value : 0; +} |