11590Srgrimes%{ 21590Srgrimes/*- 31590Srgrimes * Copyright (c) 1993 41590Srgrimes * The Regents of the University of California. All rights reserved. 51590Srgrimes * 61590Srgrimes * This code is derived from software contributed to Berkeley by 71590Srgrimes * Paul Borman at Krystal Technologies. 81590Srgrimes * 91590Srgrimes * Redistribution and use in source and binary forms, with or without 101590Srgrimes * modification, are permitted provided that the following conditions 111590Srgrimes * are met: 121590Srgrimes * 1. Redistributions of source code must retain the above copyright 131590Srgrimes * notice, this list of conditions and the following disclaimer. 141590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 151590Srgrimes * notice, this list of conditions and the following disclaimer in the 161590Srgrimes * documentation and/or other materials provided with the distribution. 171590Srgrimes * 4. Neither the name of the University nor the names of its contributors 181590Srgrimes * may be used to endorse or promote products derived from this software 191590Srgrimes * without specific prior written permission. 201590Srgrimes * 211590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311590Srgrimes * SUCH DAMAGE. 321590Srgrimes */ 331590Srgrimes 341590Srgrimes#ifndef lint 3595643Smarkm#if 0 361590Srgrimesstatic char sccsid[] = "@(#)yacc.y 8.1 (Berkeley) 6/6/93"; 3795643Smarkm#endif /* 0 */ 381590Srgrimes#endif /* not lint */ 391590Srgrimes 4095643Smarkm#include <sys/cdefs.h> 4195643Smarkm__FBSDID("$FreeBSD$"); 4295643Smarkm 4390868Smike#include <arpa/inet.h> 4490868Smike 451590Srgrimes#include <ctype.h> 46108158Stjr#include <err.h> 47200462Sdelphij#include <stddef.h> 481590Srgrimes#include <stdio.h> 491590Srgrimes#include <stdlib.h> 5033648Sjb#include <string.h> 5195643Smarkm#include <unistd.h> 521590Srgrimes 531590Srgrimes#include "ldef.h" 5495643Smarkm#include "extern.h" 55146261Sru#include "runefile.h" 561590Srgrimes 5795643Smarkmstatic void *xmalloc(unsigned int sz); 58142582Srustatic uint32_t *xlalloc(unsigned int sz); 59105548Sachevoid yyerror(const char *s); 60142582Srustatic uint32_t *xrelalloc(uint32_t *old, unsigned int sz); 6195643Smarkmstatic void dump_tables(void); 62105548Sachestatic void cleanout(void); 631590Srgrimes 6495643Smarkmconst char *locale_file = "<stdout>"; 651590Srgrimes 6695643Smarkmrune_map maplower = { { 0 }, NULL }; 6795643Smarkmrune_map mapupper = { { 0 }, NULL }; 6895643Smarkmrune_map types = { { 0 }, NULL }; 691590Srgrimes 70142582Sru_FileRuneLocale new_locale = { "", "", {}, {}, {}, 0, 0, 0, 0 }; 71142582Sruchar *variable = NULL; 7295643Smarkm 73142582Sruvoid set_map(rune_map *, rune_list *, uint32_t); 7499982Salfredvoid set_digitmap(rune_map *, rune_list *); 75142582Sruvoid add_map(rune_map *, rune_list *, uint32_t); 76116502Scharnierstatic void usage(void); 771590Srgrimes%} 781590Srgrimes 791590Srgrimes%union { 80142582Sru int32_t rune; 811590Srgrimes int i; 821590Srgrimes char *str; 831590Srgrimes 841590Srgrimes rune_list *list; 851590Srgrimes} 861590Srgrimes 871590Srgrimes%token <rune> RUNE 881590Srgrimes%token LBRK 891590Srgrimes%token RBRK 901590Srgrimes%token THRU 911590Srgrimes%token MAPLOWER 921590Srgrimes%token MAPUPPER 931590Srgrimes%token DIGITMAP 941590Srgrimes%token <i> LIST 951590Srgrimes%token <str> VARIABLE 961590Srgrimes%token ENCODING 971590Srgrimes%token INVALID 981590Srgrimes%token <str> STRING 991590Srgrimes 1001590Srgrimes%type <list> list 1011590Srgrimes%type <list> map 1021590Srgrimes 1031590Srgrimes 1041590Srgrimes%% 1051590Srgrimes 1061590Srgrimeslocale : /* empty */ 1071590Srgrimes | table 1081590Srgrimes { dump_tables(); } 1091590Srgrimes ; 1101590Srgrimes 1111590Srgrimestable : entry 1121590Srgrimes | table entry 1131590Srgrimes ; 1141590Srgrimes 1151590Srgrimesentry : ENCODING STRING 116115722Sache { if (strcmp($2, "NONE") && 117175556Sache strcmp($2, "ASCII") && 118115722Sache strcmp($2, "UTF-8") && 119115722Sache strcmp($2, "EUC") && 120115722Sache strcmp($2, "GBK") && 121118147Sache strcmp($2, "GB18030") && 122122145Sdavidxu strcmp($2, "GB2312") && 123115722Sache strcmp($2, "BIG5") && 124115776Sache strcmp($2, "MSKanji")) 125115776Sache warnx("ENCODING %s is not supported by libc", $2); 126300265Struckman strlcpy(new_locale.encoding, $2, 127142582Sru sizeof(new_locale.encoding)); } 1281590Srgrimes | VARIABLE 129142582Sru { new_locale.variable_len = strlen($1) + 1; 130142582Sru variable = xmalloc(new_locale.variable_len); 131142582Sru strcpy(variable, $1); 1321590Srgrimes } 1331590Srgrimes | INVALID RUNE 134142582Sru { warnx("the INVALID keyword is deprecated"); } 1351590Srgrimes | LIST list 1361590Srgrimes { set_map(&types, $2, $1); } 1371590Srgrimes | MAPLOWER map 1381590Srgrimes { set_map(&maplower, $2, 0); } 1391590Srgrimes | MAPUPPER map 1401590Srgrimes { set_map(&mapupper, $2, 0); } 1411590Srgrimes | DIGITMAP map 1421590Srgrimes { set_digitmap(&types, $2); } 1431590Srgrimes ; 1441590Srgrimes 1451590Srgrimeslist : RUNE 1461590Srgrimes { 147116502Scharnier $$ = (rune_list *)xmalloc(sizeof(rune_list)); 1481590Srgrimes $$->min = $1; 1491590Srgrimes $$->max = $1; 1501590Srgrimes $$->next = 0; 1511590Srgrimes } 1521590Srgrimes | RUNE THRU RUNE 1531590Srgrimes { 154116502Scharnier $$ = (rune_list *)xmalloc(sizeof(rune_list)); 1551590Srgrimes $$->min = $1; 1561590Srgrimes $$->max = $3; 1571590Srgrimes $$->next = 0; 1581590Srgrimes } 1591590Srgrimes | list RUNE 1601590Srgrimes { 161116502Scharnier $$ = (rune_list *)xmalloc(sizeof(rune_list)); 1621590Srgrimes $$->min = $2; 1631590Srgrimes $$->max = $2; 1641590Srgrimes $$->next = $1; 1651590Srgrimes } 1661590Srgrimes | list RUNE THRU RUNE 1671590Srgrimes { 168116502Scharnier $$ = (rune_list *)xmalloc(sizeof(rune_list)); 1691590Srgrimes $$->min = $2; 1701590Srgrimes $$->max = $4; 1711590Srgrimes $$->next = $1; 1721590Srgrimes } 1731590Srgrimes ; 1741590Srgrimes 1751590Srgrimesmap : LBRK RUNE RUNE RBRK 1761590Srgrimes { 177116502Scharnier $$ = (rune_list *)xmalloc(sizeof(rune_list)); 1781590Srgrimes $$->min = $2; 1791590Srgrimes $$->max = $2; 1801590Srgrimes $$->map = $3; 1811590Srgrimes $$->next = 0; 1821590Srgrimes } 1831590Srgrimes | map LBRK RUNE RUNE RBRK 1841590Srgrimes { 185116502Scharnier $$ = (rune_list *)xmalloc(sizeof(rune_list)); 1861590Srgrimes $$->min = $3; 1871590Srgrimes $$->max = $3; 1881590Srgrimes $$->map = $4; 1891590Srgrimes $$->next = $1; 1901590Srgrimes } 1911590Srgrimes | LBRK RUNE THRU RUNE ':' RUNE RBRK 1921590Srgrimes { 193116502Scharnier $$ = (rune_list *)xmalloc(sizeof(rune_list)); 1941590Srgrimes $$->min = $2; 1951590Srgrimes $$->max = $4; 1961590Srgrimes $$->map = $6; 1971590Srgrimes $$->next = 0; 1981590Srgrimes } 1991590Srgrimes | map LBRK RUNE THRU RUNE ':' RUNE RBRK 2001590Srgrimes { 201116502Scharnier $$ = (rune_list *)xmalloc(sizeof(rune_list)); 2021590Srgrimes $$->min = $3; 2031590Srgrimes $$->max = $5; 2041590Srgrimes $$->map = $7; 2051590Srgrimes $$->next = $1; 2061590Srgrimes } 2071590Srgrimes ; 2081590Srgrimes%% 2091590Srgrimes 210105548Sacheint debug; 21181606SpeterFILE *fp; 2121590Srgrimes 213105548Sachestatic void 214105548Sachecleanout(void) 215105548Sache{ 216105548Sache if (fp != NULL) 217105548Sache unlink(locale_file); 218105548Sache} 219105548Sache 22095643Smarkmint 22199984Salfredmain(int ac, char *av[]) 2221590Srgrimes{ 2231590Srgrimes int x; 2241590Srgrimes 22581606Speter fp = stdout; 2261590Srgrimes 227166529Skevlo while ((x = getopt(ac, av, "do:")) != -1) { 2281590Srgrimes switch(x) { 2291590Srgrimes case 'd': 2301590Srgrimes debug = 1; 2311590Srgrimes break; 2321590Srgrimes case 'o': 2331590Srgrimes locale_file = optarg; 234172261Skevlo if ((fp = fopen(locale_file, "w")) == NULL) 235116502Scharnier err(1, "%s", locale_file); 236105548Sache atexit(cleanout); 2371590Srgrimes break; 2381590Srgrimes default: 239116502Scharnier usage(); 2401590Srgrimes } 2411590Srgrimes } 2421590Srgrimes 2431590Srgrimes switch (ac - optind) { 2441590Srgrimes case 0: 2451590Srgrimes break; 2461590Srgrimes case 1: 247116502Scharnier if (freopen(av[optind], "r", stdin) == 0) 248116502Scharnier err(1, "%s", av[optind]); 2491590Srgrimes break; 2501590Srgrimes default: 251116502Scharnier usage(); 2521590Srgrimes } 2531590Srgrimes for (x = 0; x < _CACHED_RUNES; ++x) { 2541590Srgrimes mapupper.map[x] = x; 2551590Srgrimes maplower.map[x] = x; 2561590Srgrimes } 257142582Sru memcpy(new_locale.magic, _FILE_RUNE_MAGIC_1, sizeof(new_locale.magic)); 2581590Srgrimes 2591590Srgrimes yyparse(); 26095643Smarkm 26195643Smarkm return(0); 2621590Srgrimes} 2631590Srgrimes 264116502Scharnierstatic void 265201227Sedusage(void) 266116502Scharnier{ 267116502Scharnier fprintf(stderr, "usage: mklocale [-d] [-o output] [source]\n"); 268116502Scharnier exit(1); 269116502Scharnier} 270116502Scharnier 27195643Smarkmvoid 272201227Sedyyerror(const char *s) 2731590Srgrimes{ 2741590Srgrimes fprintf(stderr, "%s\n", s); 2751590Srgrimes} 2761590Srgrimes 277105548Sachestatic void * 278201227Sedxmalloc(unsigned int sz) 2791590Srgrimes{ 2801590Srgrimes void *r = malloc(sz); 281116502Scharnier if (!r) 282116502Scharnier errx(1, "xmalloc"); 2831590Srgrimes return(r); 2841590Srgrimes} 2851590Srgrimes 286142582Srustatic uint32_t * 287201227Sedxlalloc(unsigned int sz) 2881590Srgrimes{ 289142582Sru uint32_t *r = (uint32_t *)malloc(sz * sizeof(uint32_t)); 290116502Scharnier if (!r) 291116502Scharnier errx(1, "xlalloc"); 2921590Srgrimes return(r); 2931590Srgrimes} 2941590Srgrimes 295142582Srustatic uint32_t * 296201227Sedxrelalloc(uint32_t *old, unsigned int sz) 2971590Srgrimes{ 298142582Sru uint32_t *r = (uint32_t *)realloc((char *)old, 299142582Sru sz * sizeof(uint32_t)); 300116502Scharnier if (!r) 301116502Scharnier errx(1, "xrelalloc"); 3021590Srgrimes return(r); 3031590Srgrimes} 3041590Srgrimes 3051590Srgrimesvoid 306201227Sedset_map(rune_map *map, rune_list *list, uint32_t flag) 3071590Srgrimes{ 3081590Srgrimes while (list) { 3091590Srgrimes rune_list *nlist = list->next; 3101590Srgrimes add_map(map, list, flag); 3111590Srgrimes list = nlist; 3121590Srgrimes } 3131590Srgrimes} 3141590Srgrimes 3151590Srgrimesvoid 316201227Sedset_digitmap(rune_map *map, rune_list *list) 3171590Srgrimes{ 318142582Sru int32_t i; 3191590Srgrimes 3201590Srgrimes while (list) { 3211590Srgrimes rune_list *nlist = list->next; 3221590Srgrimes for (i = list->min; i <= list->max; ++i) { 3231590Srgrimes if (list->map + (i - list->min)) { 3241590Srgrimes rune_list *tmp = (rune_list *)xmalloc(sizeof(rune_list)); 3251590Srgrimes tmp->min = i; 3261590Srgrimes tmp->max = i; 3271590Srgrimes add_map(map, tmp, list->map + (i - list->min)); 3281590Srgrimes } 3291590Srgrimes } 3301590Srgrimes free(list); 3311590Srgrimes list = nlist; 3321590Srgrimes } 3331590Srgrimes} 3341590Srgrimes 3351590Srgrimesvoid 336201227Sedadd_map(rune_map *map, rune_list *list, uint32_t flag) 3371590Srgrimes{ 338142582Sru int32_t i; 3391590Srgrimes rune_list *lr = 0; 3401590Srgrimes rune_list *r; 341142582Sru int32_t run; 3421590Srgrimes 3431590Srgrimes while (list->min < _CACHED_RUNES && list->min <= list->max) { 3441590Srgrimes if (flag) 3451590Srgrimes map->map[list->min++] |= flag; 3461590Srgrimes else 3471590Srgrimes map->map[list->min++] = list->map++; 3481590Srgrimes } 3491590Srgrimes 3501590Srgrimes if (list->min > list->max) { 3511590Srgrimes free(list); 3521590Srgrimes return; 3531590Srgrimes } 3541590Srgrimes 3551590Srgrimes run = list->max - list->min + 1; 3561590Srgrimes 3571590Srgrimes if (!(r = map->root) || (list->max < r->min - 1) 3581590Srgrimes || (!flag && list->max == r->min - 1)) { 3591590Srgrimes if (flag) { 3601590Srgrimes list->types = xlalloc(run); 3611590Srgrimes for (i = 0; i < run; ++i) 3621590Srgrimes list->types[i] = flag; 3631590Srgrimes } 3641590Srgrimes list->next = map->root; 3651590Srgrimes map->root = list; 3661590Srgrimes return; 3671590Srgrimes } 3681590Srgrimes 3691590Srgrimes for (r = map->root; r && r->max + 1 < list->min; r = r->next) 3701590Srgrimes lr = r; 3711590Srgrimes 3721590Srgrimes if (!r) { 3731590Srgrimes /* 3741590Srgrimes * We are off the end. 3751590Srgrimes */ 3761590Srgrimes if (flag) { 3771590Srgrimes list->types = xlalloc(run); 3781590Srgrimes for (i = 0; i < run; ++i) 3791590Srgrimes list->types[i] = flag; 3801590Srgrimes } 3811590Srgrimes list->next = 0; 3821590Srgrimes lr->next = list; 3831590Srgrimes return; 3841590Srgrimes } 3851590Srgrimes 3861590Srgrimes if (list->max < r->min - 1) { 3871590Srgrimes /* 3881590Srgrimes * We come before this range and we do not intersect it. 3891590Srgrimes * We are not before the root node, it was checked before the loop 3901590Srgrimes */ 3911590Srgrimes if (flag) { 3921590Srgrimes list->types = xlalloc(run); 3931590Srgrimes for (i = 0; i < run; ++i) 3941590Srgrimes list->types[i] = flag; 3951590Srgrimes } 3961590Srgrimes list->next = lr->next; 3971590Srgrimes lr->next = list; 3981590Srgrimes return; 3991590Srgrimes } 4001590Srgrimes 4011590Srgrimes /* 4021590Srgrimes * At this point we have found that we at least intersect with 4031590Srgrimes * the range pointed to by `r', we might intersect with one or 4041590Srgrimes * more ranges beyond `r' as well. 4051590Srgrimes */ 4061590Srgrimes 4071590Srgrimes if (!flag && list->map - list->min != r->map - r->min) { 4081590Srgrimes /* 4091590Srgrimes * There are only two cases when we are doing case maps and 4101590Srgrimes * our maps needn't have the same offset. When we are adjoining 4111590Srgrimes * but not intersecting. 4121590Srgrimes */ 4131590Srgrimes if (list->max + 1 == r->min) { 4141590Srgrimes lr->next = list; 4151590Srgrimes list->next = r; 4161590Srgrimes return; 4171590Srgrimes } 4181590Srgrimes if (list->min - 1 == r->max) { 4191590Srgrimes list->next = r->next; 4201590Srgrimes r->next = list; 4211590Srgrimes return; 4221590Srgrimes } 423116502Scharnier errx(1, "error: conflicting map entries"); 4241590Srgrimes } 4251590Srgrimes 4261590Srgrimes if (list->min >= r->min && list->max <= r->max) { 4271590Srgrimes /* 4281590Srgrimes * Subset case. 4291590Srgrimes */ 4301590Srgrimes 4311590Srgrimes if (flag) { 4321590Srgrimes for (i = list->min; i <= list->max; ++i) 4331590Srgrimes r->types[i - r->min] |= flag; 4341590Srgrimes } 4351590Srgrimes free(list); 4361590Srgrimes return; 4371590Srgrimes } 4381590Srgrimes if (list->min <= r->min && list->max >= r->max) { 4391590Srgrimes /* 4401590Srgrimes * Superset case. Make him big enough to hold us. 4411590Srgrimes * We might need to merge with the guy after him. 4421590Srgrimes */ 4431590Srgrimes if (flag) { 4441590Srgrimes list->types = xlalloc(list->max - list->min + 1); 4451590Srgrimes 4461590Srgrimes for (i = list->min; i <= list->max; ++i) 4471590Srgrimes list->types[i - list->min] = flag; 4481590Srgrimes 4491590Srgrimes for (i = r->min; i <= r->max; ++i) 4501590Srgrimes list->types[i - list->min] |= r->types[i - r->min]; 4511590Srgrimes 4521590Srgrimes free(r->types); 4531590Srgrimes r->types = list->types; 4541590Srgrimes } else { 4551590Srgrimes r->map = list->map; 4561590Srgrimes } 4571590Srgrimes r->min = list->min; 4581590Srgrimes r->max = list->max; 4591590Srgrimes free(list); 4601590Srgrimes } else if (list->min < r->min) { 4611590Srgrimes /* 4621590Srgrimes * Our tail intersects his head. 4631590Srgrimes */ 4641590Srgrimes if (flag) { 4651590Srgrimes list->types = xlalloc(r->max - list->min + 1); 4661590Srgrimes 4671590Srgrimes for (i = r->min; i <= r->max; ++i) 4681590Srgrimes list->types[i - list->min] = r->types[i - r->min]; 4691590Srgrimes 4701590Srgrimes for (i = list->min; i < r->min; ++i) 4711590Srgrimes list->types[i - list->min] = flag; 4721590Srgrimes 4731590Srgrimes for (i = r->min; i <= list->max; ++i) 4741590Srgrimes list->types[i - list->min] |= flag; 4751590Srgrimes 4761590Srgrimes free(r->types); 4771590Srgrimes r->types = list->types; 4781590Srgrimes } else { 4791590Srgrimes r->map = list->map; 4801590Srgrimes } 4811590Srgrimes r->min = list->min; 4821590Srgrimes free(list); 4831590Srgrimes return; 4841590Srgrimes } else { 4851590Srgrimes /* 4861590Srgrimes * Our head intersects his tail. 4871590Srgrimes * We might need to merge with the guy after him. 4881590Srgrimes */ 4891590Srgrimes if (flag) { 4901590Srgrimes r->types = xrelalloc(r->types, list->max - r->min + 1); 4911590Srgrimes 4921590Srgrimes for (i = list->min; i <= r->max; ++i) 4931590Srgrimes r->types[i - r->min] |= flag; 4941590Srgrimes 4951590Srgrimes for (i = r->max+1; i <= list->max; ++i) 4961590Srgrimes r->types[i - r->min] = flag; 4971590Srgrimes } 49821393Sache r->max = list->max; 4991590Srgrimes free(list); 5001590Srgrimes } 5011590Srgrimes 5021590Srgrimes /* 5031590Srgrimes * Okay, check to see if we grew into the next guy(s) 5041590Srgrimes */ 5051590Srgrimes while ((lr = r->next) && r->max >= lr->min) { 5061590Srgrimes if (flag) { 5071590Srgrimes if (r->max >= lr->max) { 5081590Srgrimes /* 5091590Srgrimes * Good, we consumed all of him. 5101590Srgrimes */ 5111590Srgrimes for (i = lr->min; i <= lr->max; ++i) 5121590Srgrimes r->types[i - r->min] |= lr->types[i - lr->min]; 5131590Srgrimes } else { 5141590Srgrimes /* 5151590Srgrimes * "append" him on to the end of us. 5161590Srgrimes */ 5171590Srgrimes r->types = xrelalloc(r->types, lr->max - r->min + 1); 5181590Srgrimes 5191590Srgrimes for (i = lr->min; i <= r->max; ++i) 5201590Srgrimes r->types[i - r->min] |= lr->types[i - lr->min]; 5211590Srgrimes 5221590Srgrimes for (i = r->max+1; i <= lr->max; ++i) 5231590Srgrimes r->types[i - r->min] = lr->types[i - lr->min]; 5241590Srgrimes 5251590Srgrimes r->max = lr->max; 5261590Srgrimes } 5271590Srgrimes } else { 5281590Srgrimes if (lr->max > r->max) 5291590Srgrimes r->max = lr->max; 5301590Srgrimes } 5311590Srgrimes 5321590Srgrimes r->next = lr->next; 5331590Srgrimes 5341590Srgrimes if (flag) 5351590Srgrimes free(lr->types); 5361590Srgrimes free(lr); 5371590Srgrimes } 5381590Srgrimes} 5391590Srgrimes 540105548Sachestatic void 541201227Seddump_tables(void) 5421590Srgrimes{ 543105548Sache int x, first_d, curr_d; 5441590Srgrimes rune_list *list; 5451590Srgrimes 5461590Srgrimes /* 5471590Srgrimes * See if we can compress some of the istype arrays 5481590Srgrimes */ 5491590Srgrimes for(list = types.root; list; list = list->next) { 5501590Srgrimes list->map = list->types[0]; 5511590Srgrimes for (x = 1; x < list->max - list->min + 1; ++x) { 552142582Sru if ((int32_t)list->types[x] != list->map) { 5531590Srgrimes list->map = 0; 5541590Srgrimes break; 5551590Srgrimes } 5561590Srgrimes } 5571590Srgrimes } 5581590Srgrimes 559116502Scharnier first_d = curr_d = -1; 560105548Sache for (x = 0; x < _CACHED_RUNES; ++x) { 561142582Sru uint32_t r = types.map[x]; 562105548Sache 563105548Sache if (r & _CTYPE_D) { 564105548Sache if (first_d < 0) 565105548Sache first_d = curr_d = x; 566116502Scharnier else if (x != curr_d + 1) 567116502Scharnier errx(1, "error: DIGIT range is not contiguous"); 568116502Scharnier else if (x - first_d > 9) 569116502Scharnier errx(1, "error: DIGIT range is too big"); 570116502Scharnier else 571105548Sache curr_d++; 572116502Scharnier if (!(r & _CTYPE_X)) 573116502Scharnier errx(1, 574116502Scharnier "error: DIGIT range is not a subset of XDIGIT range"); 575105548Sache } 576105548Sache } 577116502Scharnier if (first_d < 0) 578116502Scharnier errx(1, "error: no DIGIT range defined in the single byte area"); 579116502Scharnier else if (curr_d - first_d < 9) 580116502Scharnier errx(1, "error: DIGIT range is too small in the single byte area"); 581105548Sache 5821590Srgrimes /* 5831590Srgrimes * Fill in our tables. Do this in network order so that 5841590Srgrimes * diverse machines have a chance of sharing data. 5851590Srgrimes * (Machines like Crays cannot share with little machines due to 5861590Srgrimes * word size. Sigh. We tried.) 5871590Srgrimes */ 5881590Srgrimes for (x = 0; x < _CACHED_RUNES; ++x) { 589142582Sru new_locale.runetype[x] = htonl(types.map[x]); 590142582Sru new_locale.maplower[x] = htonl(maplower.map[x]); 591142582Sru new_locale.mapupper[x] = htonl(mapupper.map[x]); 5921590Srgrimes } 5931590Srgrimes 5941590Srgrimes /* 5951590Srgrimes * Count up how many ranges we will need for each of the extents. 5961590Srgrimes */ 5971590Srgrimes list = types.root; 5981590Srgrimes 5991590Srgrimes while (list) { 600142582Sru new_locale.runetype_ext_nranges++; 6011590Srgrimes list = list->next; 6021590Srgrimes } 603142582Sru new_locale.runetype_ext_nranges = 604142582Sru htonl(new_locale.runetype_ext_nranges); 6051590Srgrimes 6061590Srgrimes list = maplower.root; 6071590Srgrimes 6081590Srgrimes while (list) { 609142582Sru new_locale.maplower_ext_nranges++; 6101590Srgrimes list = list->next; 6111590Srgrimes } 612142582Sru new_locale.maplower_ext_nranges = 613142582Sru htonl(new_locale.maplower_ext_nranges); 6141590Srgrimes 6151590Srgrimes list = mapupper.root; 6161590Srgrimes 6171590Srgrimes while (list) { 618142582Sru new_locale.mapupper_ext_nranges++; 6191590Srgrimes list = list->next; 6201590Srgrimes } 621142582Sru new_locale.mapupper_ext_nranges = 622142582Sru htonl(new_locale.mapupper_ext_nranges); 6231590Srgrimes 624142582Sru new_locale.variable_len = htonl(new_locale.variable_len); 6251590Srgrimes 6261590Srgrimes /* 6271590Srgrimes * Okay, we are now ready to write the new locale file. 6281590Srgrimes */ 6291590Srgrimes 6301590Srgrimes /* 631142582Sru * PART 1: The _FileRuneLocale structure 6321590Srgrimes */ 6331590Srgrimes if (fwrite((char *)&new_locale, sizeof(new_locale), 1, fp) != 1) { 6341590Srgrimes perror(locale_file); 6351590Srgrimes exit(1); 6361590Srgrimes } 6371590Srgrimes /* 6381590Srgrimes * PART 2: The runetype_ext structures (not the actual tables) 6391590Srgrimes */ 6401590Srgrimes list = types.root; 6411590Srgrimes 6421590Srgrimes while (list) { 643142582Sru _FileRuneEntry re; 6441590Srgrimes 645142582Sru re.min = htonl(list->min); 646142582Sru re.max = htonl(list->max); 647142582Sru re.map = htonl(list->map); 6481590Srgrimes 6491590Srgrimes if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 6501590Srgrimes perror(locale_file); 6511590Srgrimes exit(1); 6521590Srgrimes } 6531590Srgrimes 6541590Srgrimes list = list->next; 6551590Srgrimes } 6561590Srgrimes /* 6571590Srgrimes * PART 3: The maplower_ext structures 6581590Srgrimes */ 6591590Srgrimes list = maplower.root; 6601590Srgrimes 6611590Srgrimes while (list) { 662142582Sru _FileRuneEntry re; 6631590Srgrimes 664142582Sru re.min = htonl(list->min); 665142582Sru re.max = htonl(list->max); 666142582Sru re.map = htonl(list->map); 6671590Srgrimes 6681590Srgrimes if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 6691590Srgrimes perror(locale_file); 6701590Srgrimes exit(1); 6711590Srgrimes } 6721590Srgrimes 6731590Srgrimes list = list->next; 6741590Srgrimes } 6751590Srgrimes /* 6761590Srgrimes * PART 4: The mapupper_ext structures 6771590Srgrimes */ 6781590Srgrimes list = mapupper.root; 6791590Srgrimes 6801590Srgrimes while (list) { 681142582Sru _FileRuneEntry re; 6821590Srgrimes 683142582Sru re.min = htonl(list->min); 684142582Sru re.max = htonl(list->max); 685142582Sru re.map = htonl(list->map); 6861590Srgrimes 6871590Srgrimes if (fwrite((char *)&re, sizeof(re), 1, fp) != 1) { 6881590Srgrimes perror(locale_file); 6891590Srgrimes exit(1); 6901590Srgrimes } 6911590Srgrimes 6921590Srgrimes list = list->next; 6931590Srgrimes } 6941590Srgrimes /* 6951590Srgrimes * PART 5: The runetype_ext tables 6961590Srgrimes */ 6971590Srgrimes list = types.root; 6981590Srgrimes 6991590Srgrimes while (list) { 7001590Srgrimes for (x = 0; x < list->max - list->min + 1; ++x) 7011590Srgrimes list->types[x] = htonl(list->types[x]); 7021590Srgrimes 7031590Srgrimes if (!list->map) { 70421393Sache if (fwrite((char *)list->types, 705142582Sru (list->max - list->min + 1) * sizeof(uint32_t), 7062509Sbde 1, fp) != 1) { 7071590Srgrimes perror(locale_file); 7081590Srgrimes exit(1); 7091590Srgrimes } 7101590Srgrimes } 7111590Srgrimes list = list->next; 7121590Srgrimes } 7131590Srgrimes /* 714142582Sru * PART 6: And finally the variable data 7151590Srgrimes */ 716195676Sed if (new_locale.variable_len != 0 && 717195676Sed fwrite(variable, ntohl(new_locale.variable_len), 1, fp) != 1) { 7181590Srgrimes perror(locale_file); 7191590Srgrimes exit(1); 7201590Srgrimes } 721105548Sache if (fclose(fp) != 0) { 722105548Sache perror(locale_file); 723105548Sache exit(1); 724105548Sache } 725105548Sache fp = NULL; 7261590Srgrimes 7271590Srgrimes if (!debug) 7281590Srgrimes return; 7291590Srgrimes 730142582Sru if (new_locale.encoding[0]) 731142582Sru fprintf(stderr, "ENCODING %s\n", new_locale.encoding); 732142582Sru if (variable) 733142582Sru fprintf(stderr, "VARIABLE %s\n", variable); 7341590Srgrimes 7351590Srgrimes fprintf(stderr, "\nMAPLOWER:\n\n"); 7361590Srgrimes 7371590Srgrimes for (x = 0; x < _CACHED_RUNES; ++x) { 7381590Srgrimes if (isprint(maplower.map[x])) 73938022Sbde fprintf(stderr, " '%c'", (int)maplower.map[x]); 7401590Srgrimes else if (maplower.map[x]) 741142582Sru fprintf(stderr, "%04x", maplower.map[x]); 7421590Srgrimes else 7431590Srgrimes fprintf(stderr, "%4x", 0); 7441590Srgrimes if ((x & 0xf) == 0xf) 7451590Srgrimes fprintf(stderr, "\n"); 7461590Srgrimes else 7471590Srgrimes fprintf(stderr, " "); 7481590Srgrimes } 7491590Srgrimes fprintf(stderr, "\n"); 7501590Srgrimes 7511590Srgrimes for (list = maplower.root; list; list = list->next) 7521590Srgrimes fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); 7531590Srgrimes 7541590Srgrimes fprintf(stderr, "\nMAPUPPER:\n\n"); 7551590Srgrimes 7561590Srgrimes for (x = 0; x < _CACHED_RUNES; ++x) { 7571590Srgrimes if (isprint(mapupper.map[x])) 75838022Sbde fprintf(stderr, " '%c'", (int)mapupper.map[x]); 7591590Srgrimes else if (mapupper.map[x]) 760142582Sru fprintf(stderr, "%04x", mapupper.map[x]); 7611590Srgrimes else 7621590Srgrimes fprintf(stderr, "%4x", 0); 7631590Srgrimes if ((x & 0xf) == 0xf) 7641590Srgrimes fprintf(stderr, "\n"); 7651590Srgrimes else 7661590Srgrimes fprintf(stderr, " "); 7671590Srgrimes } 7681590Srgrimes fprintf(stderr, "\n"); 7691590Srgrimes 7701590Srgrimes for (list = mapupper.root; list; list = list->next) 7711590Srgrimes fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map); 7721590Srgrimes 7731590Srgrimes 7741590Srgrimes fprintf(stderr, "\nTYPES:\n\n"); 7751590Srgrimes 7761590Srgrimes for (x = 0; x < _CACHED_RUNES; ++x) { 777142582Sru uint32_t r = types.map[x]; 7781590Srgrimes 7791590Srgrimes if (r) { 7801590Srgrimes if (isprint(x)) 78138022Sbde fprintf(stderr, " '%c': %2d", x, (int)(r & 0xff)); 7821590Srgrimes else 78338022Sbde fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff)); 7841590Srgrimes 78557035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 78657035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 78757035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 78857035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 78957035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 79057035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 79157035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 79257035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 79357035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 79457035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 79557035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 79657035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 79757035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 79857035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 7991590Srgrimes fprintf(stderr, "\n"); 8001590Srgrimes } 8011590Srgrimes } 8021590Srgrimes 8031590Srgrimes for (list = types.root; list; list = list->next) { 8041590Srgrimes if (list->map && list->min + 3 < list->max) { 805142582Sru uint32_t r = list->map; 8061590Srgrimes 807142582Sru fprintf(stderr, "%04x: %2d", 808142582Sru (uint32_t)list->min, (int)(r & 0xff)); 8091590Srgrimes 81057035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 81157035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 81257035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 81357035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 81457035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 81557035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 81657035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 81757035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 81857035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 81957035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 82057035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 82157035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 82257035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 82357035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 8241590Srgrimes fprintf(stderr, "\n...\n"); 8251590Srgrimes 826142582Sru fprintf(stderr, "%04x: %2d", 827142582Sru (uint32_t)list->max, (int)(r & 0xff)); 8281590Srgrimes 82957035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 83057035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 83157035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 83257035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 83357035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 83457035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 83557035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 83657035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 83757035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 83857035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 83957035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 84057035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 84157035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 84257035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 8431590Srgrimes fprintf(stderr, "\n"); 8441590Srgrimes } else 8451590Srgrimes for (x = list->min; x <= list->max; ++x) { 846142582Sru uint32_t r = ntohl(list->types[x - list->min]); 8471590Srgrimes 8481590Srgrimes if (r) { 84938022Sbde fprintf(stderr, "%04x: %2d", x, (int)(r & 0xff)); 8501590Srgrimes 85157035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_A) ? "alph" : ""); 85257035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_C) ? "ctrl" : ""); 85357035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_D) ? "dig" : ""); 85457035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_G) ? "graf" : ""); 85557035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_L) ? "low" : ""); 85657035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_P) ? "punc" : ""); 85757035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_S) ? "spac" : ""); 85857035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_U) ? "upp" : ""); 85957035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_X) ? "xdig" : ""); 86057035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_B) ? "blnk" : ""); 86157035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_R) ? "prnt" : ""); 86257035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_I) ? "ideo" : ""); 86357035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_T) ? "spec" : ""); 86457035Sobrien fprintf(stderr, " %4s", (r & _CTYPE_Q) ? "phon" : ""); 8651590Srgrimes fprintf(stderr, "\n"); 8661590Srgrimes } 8671590Srgrimes } 8681590Srgrimes } 8691590Srgrimes} 870