[BACK]Return to yacc.y CVS log [TXT][DIR] Up to [local] / src / usr.bin / mklocale

Annotation of src/usr.bin/mklocale/yacc.y, Revision 1.1

1.1     ! espie       1: /*     $NetBSD: yacc.y,v 1.24 2004/01/05 23:23:36 jmmv Exp $   */
        !             2:
        !             3: %{
        !             4: /*-
        !             5:  * Copyright (c) 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to Berkeley by
        !             9:  * Paul Borman at Krystal Technologies.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. Neither the name of the University nor the names of its contributors
        !            20:  *    may be used to endorse or promote products derived from this software
        !            21:  *    without specific prior written permission.
        !            22:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            33:  * SUCH DAMAGE.
        !            34:  */
        !            35:
        !            36: #include <sys/cdefs.h>
        !            37:
        !            38: #include <sys/types.h>
        !            39: #include <netinet/in.h>        /* Needed by <arpa/inet.h> on NetBSD 1.5. */
        !            40: #include <arpa/inet.h> /* Needed for htonl on POSIX systems. */
        !            41:
        !            42: #include <err.h>
        !            43: #include "locale/runetype.h"
        !            44: #include <stddef.h>
        !            45: #include <stdio.h>
        !            46: #include <stdlib.h>
        !            47: #include <string.h>
        !            48: #include <unistd.h>
        !            49: #include <ctype.h>
        !            50:
        !            51: #include "ldef.h"
        !            52:
        !            53: const char     *locale_file = "<stdout>";
        !            54:
        !            55: rune_map       maplower = { { 0, }, };
        !            56: rune_map       mapupper = { { 0, }, };
        !            57: rune_map       types = { { 0, }, };
        !            58:
        !            59: _RuneLocale    new_locale = { { 0, }, };
        !            60:
        !            61: rune_t charsetbits = (rune_t)0x00000000;
        !            62: #if 0
        !            63: rune_t charsetmask = (rune_t)0x0000007f;
        !            64: #endif
        !            65: rune_t charsetmask = (rune_t)0xffffffff;
        !            66:
        !            67: void set_map(rune_map *, rune_list *, u_int32_t);
        !            68: void set_digitmap(rune_map *, rune_list *);
        !            69: void add_map(rune_map *, rune_list *, u_int32_t);
        !            70:
        !            71: int            main(int, char *[]);
        !            72: int            yyerror(const char *s);
        !            73: void           *xmalloc(size_t sz);
        !            74: u_int32_t      *xlalloc(size_t sz);
        !            75: u_int32_t      *xrelalloc(u_int32_t *old, size_t sz);
        !            76: void           dump_tables(void);
        !            77: int            yyparse(void);
        !            78: extern int     yylex(void);
        !            79: %}
        !            80:
        !            81: %union {
        !            82:     rune_t     rune;
        !            83:     int                i;
        !            84:     char       *str;
        !            85:
        !            86:     rune_list  *list;
        !            87: }
        !            88:
        !            89: %token <rune>  RUNE
        !            90: %token         LBRK
        !            91: %token         RBRK
        !            92: %token         THRU
        !            93: %token         MAPLOWER
        !            94: %token         MAPUPPER
        !            95: %token         DIGITMAP
        !            96: %token <i>     LIST
        !            97: %token <str>   VARIABLE
        !            98: %token         CHARSET
        !            99: %token         ENCODING
        !           100: %token         INVALID
        !           101: %token <str>   STRING
        !           102:
        !           103: %type  <list>  list
        !           104: %type  <list>  map
        !           105:
        !           106:
        !           107: %%
        !           108:
        !           109: locale :       /* empty */
        !           110:        |       table
        !           111:                { dump_tables(); }
        !           112:        ;
        !           113:
        !           114: table  :       entry
        !           115:        |       table entry
        !           116:        ;
        !           117:
        !           118: entry  :       ENCODING STRING
        !           119:                { strncpy(new_locale.rl_encoding, $2, sizeof(new_locale.rl_encoding)); }
        !           120:        |       VARIABLE
        !           121:                { new_locale.rl_variable_len = strlen($1) + 1;
        !           122:                  new_locale.rl_variable = strdup($1);
        !           123:                }
        !           124:        |       CHARSET RUNE
        !           125:                { charsetbits = $2; charsetmask = 0x0000007f; }
        !           126:        |       CHARSET RUNE RUNE
        !           127:                { charsetbits = $2; charsetmask = $3; }
        !           128:        |       CHARSET STRING
        !           129:                { int final = $2[strlen($2) - 1] & 0x7f;
        !           130:                  charsetbits = final << 24;
        !           131:                  if ($2[0] == '$') {
        !           132:                        charsetmask = 0x00007f7f;
        !           133:                        if (strchr(",-./", $2[1]))
        !           134:                                charsetbits |= 0x80;
        !           135:                        if (0xd0 <= final && final <= 0xdf)
        !           136:                                charsetmask |= 0x007f0000;
        !           137:                  } else {
        !           138:                        charsetmask = 0x0000007f;
        !           139:                        if (strchr(",-./", $2[0]))
        !           140:                                charsetbits |= 0x80;
        !           141:                        if (strlen($2) == 2 && $2[0] == '!')
        !           142:                                charsetbits |= ((0x80 | $2[0]) << 16);
        !           143:                  }
        !           144:
        !           145:                  /*
        !           146:                   * special rules
        !           147:                   */
        !           148:                  if (charsetbits == ('B' << 24)
        !           149:                   && charsetmask == 0x0000007f) {
        !           150:                        /*ASCII: 94B*/
        !           151:                        charsetbits = 0;
        !           152:                        charsetmask = 0x0000007f;
        !           153:                  } else if (charsetbits == (('A' << 24) | 0x80)
        !           154:                          && charsetmask == 0x0000007f) {
        !           155:                        /*Latin1: 96A*/
        !           156:                        charsetbits = 0x80;
        !           157:                        charsetmask = 0x0000007f;
        !           158:                  }
        !           159:                }
        !           160:        |       INVALID RUNE
        !           161:                { new_locale.rl_invalid_rune = $2; }
        !           162:        |       LIST list
        !           163:                { set_map(&types, $2, $1); }
        !           164:        |       MAPLOWER map
        !           165:                { set_map(&maplower, $2, 0); }
        !           166:        |       MAPUPPER map
        !           167:                { set_map(&mapupper, $2, 0); }
        !           168:        |       DIGITMAP map
        !           169:                { set_digitmap(&types, $2); }
        !           170:        ;
        !           171:
        !           172: list   :       RUNE
        !           173:                {
        !           174:                    $$ = (rune_list *)malloc(sizeof(rune_list));
        !           175:                    $$->min = ($1 & charsetmask) | charsetbits;
        !           176:                    $$->max = ($1 & charsetmask) | charsetbits;
        !           177:                    $$->next = 0;
        !           178:                }
        !           179:        |       RUNE THRU RUNE
        !           180:                {
        !           181:                    $$ = (rune_list *)malloc(sizeof(rune_list));
        !           182:                    $$->min = ($1 & charsetmask) | charsetbits;
        !           183:                    $$->max = ($3 & charsetmask) | charsetbits;
        !           184:                    $$->next = 0;
        !           185:                }
        !           186:        |       list RUNE
        !           187:                {
        !           188:                    $$ = (rune_list *)malloc(sizeof(rune_list));
        !           189:                    $$->min = ($2 & charsetmask) | charsetbits;
        !           190:                    $$->max = ($2 & charsetmask) | charsetbits;
        !           191:                    $$->next = $1;
        !           192:                }
        !           193:        |       list RUNE THRU RUNE
        !           194:                {
        !           195:                    $$ = (rune_list *)malloc(sizeof(rune_list));
        !           196:                    $$->min = ($2 & charsetmask) | charsetbits;
        !           197:                    $$->max = ($4 & charsetmask) | charsetbits;
        !           198:                    $$->next = $1;
        !           199:                }
        !           200:        ;
        !           201:
        !           202: map    :       LBRK RUNE RUNE RBRK
        !           203:                {
        !           204:                    $$ = (rune_list *)malloc(sizeof(rune_list));
        !           205:                    $$->min = ($2 & charsetmask) | charsetbits;
        !           206:                    $$->max = ($2 & charsetmask) | charsetbits;
        !           207:                    $$->map = $3;
        !           208:                    $$->next = 0;
        !           209:                }
        !           210:        |       map LBRK RUNE RUNE RBRK
        !           211:                {
        !           212:                    $$ = (rune_list *)malloc(sizeof(rune_list));
        !           213:                    $$->min = ($3 & charsetmask) | charsetbits;
        !           214:                    $$->max = ($3 & charsetmask) | charsetbits;
        !           215:                    $$->map = $4;
        !           216:                    $$->next = $1;
        !           217:                }
        !           218:        |       LBRK RUNE THRU RUNE ':' RUNE RBRK
        !           219:                {
        !           220:                    $$ = (rune_list *)malloc(sizeof(rune_list));
        !           221:                    $$->min = ($2 & charsetmask) | charsetbits;
        !           222:                    $$->max = ($4 & charsetmask) | charsetbits;
        !           223:                    $$->map = $6;
        !           224:                    $$->next = 0;
        !           225:                }
        !           226:        |       map LBRK RUNE THRU RUNE ':' RUNE RBRK
        !           227:                {
        !           228:                    $$ = (rune_list *)malloc(sizeof(rune_list));
        !           229:                    $$->min = ($3 & charsetmask) | charsetbits;
        !           230:                    $$->max = ($5 & charsetmask) | charsetbits;
        !           231:                    $$->map = $7;
        !           232:                    $$->next = $1;
        !           233:                }
        !           234:        ;
        !           235: %%
        !           236:
        !           237: int debug = 0;
        !           238: FILE *ofile;
        !           239:
        !           240: int
        !           241: main(int ac, char *av[])
        !           242: {
        !           243:     int x;
        !           244:
        !           245:     extern char *optarg;
        !           246:     extern int optind;
        !           247:
        !           248:     while ((x = getopt(ac, av, "do:")) != EOF) {
        !           249:        switch(x) {
        !           250:        case 'd':
        !           251:            debug = 1;
        !           252:            break;
        !           253:        case 'o':
        !           254:            locale_file = optarg;
        !           255:            if ((ofile = fopen(locale_file, "w")) == 0)
        !           256:                err(1, "unable to open output file %s", locale_file);
        !           257:            break;
        !           258:        default:
        !           259:        usage:
        !           260:            fprintf(stderr, "usage: mklocale [-d] [-o output] [source]\n");
        !           261:            exit(1);
        !           262:        }
        !           263:     }
        !           264:
        !           265:     switch (ac - optind) {
        !           266:     case 0:
        !           267:        break;
        !           268:     case 1:
        !           269:        if (freopen(av[optind], "r", stdin) == 0)
        !           270:            err(1, "unable to open input file %s", av[optind]);
        !           271:        break;
        !           272:     default:
        !           273:        goto usage;
        !           274:     }
        !           275:     for (x = 0; x < _CACHED_RUNES; ++x) {
        !           276:        mapupper.map[x] = x;
        !           277:        maplower.map[x] = x;
        !           278:     }
        !           279:     new_locale.rl_invalid_rune = _DEFAULT_INVALID_RUNE;
        !           280:     memcpy(new_locale.rl_magic, _RUNE_MAGIC_1, sizeof(new_locale.rl_magic));
        !           281:
        !           282:     yyparse();
        !           283:
        !           284:     return 0;
        !           285: }
        !           286:
        !           287: int
        !           288: yyerror(const char *s)
        !           289: {
        !           290:     fprintf(stderr, "%s\n", s);
        !           291:
        !           292:     return 0;
        !           293: }
        !           294:
        !           295: void *
        !           296: xmalloc(size_t sz)
        !           297: {
        !           298:     void *r = malloc(sz);
        !           299:     if (!r) {
        !           300:        perror("xmalloc");
        !           301:        abort();
        !           302:     }
        !           303:     return(r);
        !           304: }
        !           305:
        !           306: u_int32_t *
        !           307: xlalloc(size_t sz)
        !           308: {
        !           309:     u_int32_t *r = (u_int32_t *)malloc(sz * sizeof(u_int32_t));
        !           310:     if (!r) {
        !           311:        perror("xlalloc");
        !           312:        abort();
        !           313:     }
        !           314:     return(r);
        !           315: }
        !           316:
        !           317: u_int32_t *
        !           318: xrelalloc(u_int32_t *old, size_t sz)
        !           319: {
        !           320:     u_int32_t *r = (u_int32_t *)realloc(old, sz * sizeof(u_int32_t));
        !           321:     if (!r) {
        !           322:        perror("xrelalloc");
        !           323:        abort();
        !           324:     }
        !           325:     return(r);
        !           326: }
        !           327:
        !           328: void
        !           329: set_map(rune_map *map, rune_list *list, u_int32_t flag)
        !           330: {
        !           331:     list->map &= charsetmask;
        !           332:     list->map |= charsetbits;
        !           333:     while (list) {
        !           334:        rune_list *nlist = list->next;
        !           335:        add_map(map, list, flag);
        !           336:        list = nlist;
        !           337:     }
        !           338: }
        !           339:
        !           340: void
        !           341: set_digitmap(rune_map *map, rune_list *list)
        !           342: {
        !           343:     rune_t i;
        !           344:
        !           345:     while (list) {
        !           346:        rune_list *nlist = list->next;
        !           347:        for (i = list->min; i <= list->max; ++i) {
        !           348:            if (list->map + (i - list->min)) {
        !           349:                rune_list *tmp = (rune_list *)xmalloc(sizeof(rune_list));
        !           350:                tmp->min = i;
        !           351:                tmp->max = i;
        !           352:                add_map(map, tmp, list->map + (i - list->min));
        !           353:            }
        !           354:        }
        !           355:        free(list);
        !           356:        list = nlist;
        !           357:     }
        !           358: }
        !           359:
        !           360: void
        !           361: add_map(rune_map *map, rune_list *list, u_int32_t flag)
        !           362: {
        !           363:     rune_t i;
        !           364:     rune_list *lr = 0;
        !           365:     rune_list *r;
        !           366:     rune_t run;
        !           367:
        !           368:     while (list->min < _CACHED_RUNES && list->min <= list->max) {
        !           369:        if (flag)
        !           370:            map->map[list->min++] |= flag;
        !           371:        else
        !           372:            map->map[list->min++] = list->map++;
        !           373:     }
        !           374:
        !           375:     if (list->min > list->max) {
        !           376:        free(list);
        !           377:        return;
        !           378:     }
        !           379:
        !           380:     run = list->max - list->min + 1;
        !           381:
        !           382:     if (!(r = map->root) || (list->max < r->min - 1)
        !           383:                         || (!flag && list->max == r->min - 1)) {
        !           384:        if (flag) {
        !           385:            list->types = xlalloc(run);
        !           386:            for (i = 0; i < run; ++i)
        !           387:                list->types[i] = flag;
        !           388:        }
        !           389:        list->next = map->root;
        !           390:        map->root = list;
        !           391:        return;
        !           392:     }
        !           393:
        !           394:     for (r = map->root; r && r->max + 1 < list->min; r = r->next)
        !           395:        lr = r;
        !           396:
        !           397:     if (!r) {
        !           398:        /*
        !           399:         * We are off the end.
        !           400:         */
        !           401:        if (flag) {
        !           402:            list->types = xlalloc(run);
        !           403:            for (i = 0; i < run; ++i)
        !           404:                list->types[i] = flag;
        !           405:        }
        !           406:        list->next = 0;
        !           407:        lr->next = list;
        !           408:        return;
        !           409:     }
        !           410:
        !           411:     if (list->max < r->min - 1) {
        !           412:        /*
        !           413:         * We come before this range and we do not intersect it.
        !           414:         * We are not before the root node, it was checked before the loop
        !           415:         */
        !           416:        if (flag) {
        !           417:            list->types = xlalloc(run);
        !           418:            for (i = 0; i < run; ++i)
        !           419:                list->types[i] = flag;
        !           420:        }
        !           421:        list->next = lr->next;
        !           422:        lr->next = list;
        !           423:        return;
        !           424:     }
        !           425:
        !           426:     /*
        !           427:      * At this point we have found that we at least intersect with
        !           428:      * the range pointed to by `r', we might intersect with one or
        !           429:      * more ranges beyond `r' as well.
        !           430:      */
        !           431:
        !           432:     if (!flag && list->map - list->min != r->map - r->min) {
        !           433:        /*
        !           434:         * There are only two cases when we are doing case maps and
        !           435:         * our maps needn't have the same offset.  When we are adjoining
        !           436:         * but not intersecting.
        !           437:         */
        !           438:        if (list->max + 1 == r->min) {
        !           439:            lr->next = list;
        !           440:            list->next = r;
        !           441:            return;
        !           442:        }
        !           443:        if (list->min - 1 == r->max) {
        !           444:            list->next = r->next;
        !           445:            r->next = list;
        !           446:            return;
        !           447:        }
        !           448:        fprintf(stderr, "Error: conflicting map entries\n");
        !           449:        exit(1);
        !           450:     }
        !           451:
        !           452:     if (list->min >= r->min && list->max <= r->max) {
        !           453:        /*
        !           454:         * Subset case.
        !           455:         */
        !           456:
        !           457:        if (flag) {
        !           458:            for (i = list->min; i <= list->max; ++i)
        !           459:                r->types[i - r->min] |= flag;
        !           460:        }
        !           461:        free(list);
        !           462:        return;
        !           463:     }
        !           464:     if (list->min <= r->min && list->max >= r->max) {
        !           465:        /*
        !           466:         * Superset case.  Make him big enough to hold us.
        !           467:         * We might need to merge with the guy after him.
        !           468:         */
        !           469:        if (flag) {
        !           470:            list->types = xlalloc(list->max - list->min + 1);
        !           471:
        !           472:            for (i = list->min; i <= list->max; ++i)
        !           473:                list->types[i - list->min] = flag;
        !           474:
        !           475:            for (i = r->min; i <= r->max; ++i)
        !           476:                list->types[i - list->min] |= r->types[i - r->min];
        !           477:
        !           478:            free(r->types);
        !           479:            r->types = list->types;
        !           480:        } else {
        !           481:            r->map = list->map;
        !           482:        }
        !           483:        r->min = list->min;
        !           484:        r->max = list->max;
        !           485:        free(list);
        !           486:     } else if (list->min < r->min) {
        !           487:        /*
        !           488:         * Our tail intersects his head.
        !           489:         */
        !           490:        if (flag) {
        !           491:            list->types = xlalloc(r->max - list->min + 1);
        !           492:
        !           493:            for (i = r->min; i <= r->max; ++i)
        !           494:                list->types[i - list->min] = r->types[i - r->min];
        !           495:
        !           496:            for (i = list->min; i < r->min; ++i)
        !           497:                list->types[i - list->min] = flag;
        !           498:
        !           499:            for (i = r->min; i <= list->max; ++i)
        !           500:                list->types[i - list->min] |= flag;
        !           501:
        !           502:            free(r->types);
        !           503:            r->types = list->types;
        !           504:        } else {
        !           505:            r->map = list->map;
        !           506:        }
        !           507:        r->min = list->min;
        !           508:        free(list);
        !           509:        return;
        !           510:     } else {
        !           511:        /*
        !           512:         * Our head intersects his tail.
        !           513:         * We might need to merge with the guy after him.
        !           514:         */
        !           515:        if (flag) {
        !           516:            r->types = xrelalloc(r->types, list->max - r->min + 1);
        !           517:
        !           518:            for (i = list->min; i <= r->max; ++i)
        !           519:                r->types[i - r->min] |= flag;
        !           520:
        !           521:            for (i = r->max+1; i <= list->max; ++i)
        !           522:                r->types[i - r->min] = flag;
        !           523:        }
        !           524:        r->max = list->max;
        !           525:        free(list);
        !           526:     }
        !           527:
        !           528:     /*
        !           529:      * Okay, check to see if we grew into the next guy(s)
        !           530:      */
        !           531:     while ((lr = r->next) && r->max >= lr->min) {
        !           532:        if (flag) {
        !           533:            if (r->max >= lr->max) {
        !           534:                /*
        !           535:                 * Good, we consumed all of him.
        !           536:                 */
        !           537:                for (i = lr->min; i <= lr->max; ++i)
        !           538:                    r->types[i - r->min] |= lr->types[i - lr->min];
        !           539:            } else {
        !           540:                /*
        !           541:                 * "append" him on to the end of us.
        !           542:                 */
        !           543:                r->types = xrelalloc(r->types, lr->max - r->min + 1);
        !           544:
        !           545:                for (i = lr->min; i <= r->max; ++i)
        !           546:                    r->types[i - r->min] |= lr->types[i - lr->min];
        !           547:
        !           548:                for (i = r->max+1; i <= lr->max; ++i)
        !           549:                    r->types[i - r->min] = lr->types[i - lr->min];
        !           550:
        !           551:                r->max = lr->max;
        !           552:            }
        !           553:        } else {
        !           554:            if (lr->max > r->max)
        !           555:                r->max = lr->max;
        !           556:        }
        !           557:
        !           558:        r->next = lr->next;
        !           559:
        !           560:        if (flag)
        !           561:            free(lr->types);
        !           562:        free(lr);
        !           563:     }
        !           564: }
        !           565:
        !           566: void
        !           567: dump_tables()
        !           568: {
        !           569:     int x, n;
        !           570:     rune_list *list;
        !           571:     _FileRuneLocale file_new_locale;
        !           572:     FILE *fp = (ofile ? ofile : stdout);
        !           573:
        !           574:     memset(&file_new_locale, 0, sizeof(file_new_locale));
        !           575:
        !           576:     /*
        !           577:      * See if we can compress some of the istype arrays
        !           578:      */
        !           579:     for(list = types.root; list; list = list->next) {
        !           580:        list->map = list->types[0];
        !           581:        for (x = 1; x < list->max - list->min + 1; ++x) {
        !           582:            if (list->types[x] != list->map) {
        !           583:                list->map = 0;
        !           584:                break;
        !           585:            }
        !           586:        }
        !           587:     }
        !           588:
        !           589:     memcpy(&file_new_locale.frl_magic, new_locale.rl_magic,
        !           590:        sizeof(file_new_locale.frl_magic));
        !           591:     memcpy(&file_new_locale.frl_encoding, new_locale.rl_encoding,
        !           592:        sizeof(file_new_locale.frl_encoding));
        !           593:
        !           594:     file_new_locale.frl_invalid_rune = htonl(new_locale.rl_invalid_rune);
        !           595:
        !           596:     /*
        !           597:      * Fill in our tables.  Do this in network order so that
        !           598:      * diverse machines have a chance of sharing data.
        !           599:      * (Machines like Crays cannot share with little machines due to
        !           600:      *  word size.  Sigh.  We tried.)
        !           601:      */
        !           602:     for (x = 0; x < _CACHED_RUNES; ++x) {
        !           603:        file_new_locale.frl_runetype[x] = htonl(types.map[x]);
        !           604:        file_new_locale.frl_maplower[x] = htonl(maplower.map[x]);
        !           605:        file_new_locale.frl_mapupper[x] = htonl(mapupper.map[x]);
        !           606:     }
        !           607:
        !           608:     /*
        !           609:      * Count up how many ranges we will need for each of the extents.
        !           610:      */
        !           611:     list = types.root;
        !           612:
        !           613:     while (list) {
        !           614:        new_locale.rl_runetype_ext.rr_nranges++;
        !           615:        list = list->next;
        !           616:     }
        !           617:     file_new_locale.frl_runetype_ext.frr_nranges =
        !           618:        htonl(new_locale.rl_runetype_ext.rr_nranges);
        !           619:
        !           620:     list = maplower.root;
        !           621:
        !           622:     while (list) {
        !           623:        new_locale.rl_maplower_ext.rr_nranges++;
        !           624:        list = list->next;
        !           625:     }
        !           626:     file_new_locale.frl_maplower_ext.frr_nranges =
        !           627:        htonl(new_locale.rl_maplower_ext.rr_nranges);
        !           628:
        !           629:     list = mapupper.root;
        !           630:
        !           631:     while (list) {
        !           632:        new_locale.rl_mapupper_ext.rr_nranges++;
        !           633:        list = list->next;
        !           634:     }
        !           635:     file_new_locale.frl_mapupper_ext.frr_nranges =
        !           636:        htonl(new_locale.rl_mapupper_ext.rr_nranges);
        !           637:
        !           638:     file_new_locale.frl_variable_len = htonl(new_locale.rl_variable_len);
        !           639:
        !           640:     /*
        !           641:      * Okay, we are now ready to write the new locale file.
        !           642:      */
        !           643:
        !           644:     /*
        !           645:      * PART 1: The _RuneLocale structure
        !           646:      */
        !           647:     if (fwrite((char *)&file_new_locale, sizeof(file_new_locale), 1, fp) != 1)
        !           648:        err(1, "writing _RuneLocale to %s", locale_file);
        !           649:     /*
        !           650:      * PART 2: The runetype_ext structures (not the actual tables)
        !           651:      */
        !           652:     for (list = types.root, n = 0; list != NULL; list = list->next, n++) {
        !           653:        _FileRuneEntry re;
        !           654:
        !           655:        memset(&re, 0, sizeof(re));
        !           656:        re.fre_min = htonl(list->min);
        !           657:        re.fre_max = htonl(list->max);
        !           658:        re.fre_map = htonl(list->map);
        !           659:
        !           660:        if (fwrite((char *)&re, sizeof(re), 1, fp) != 1)
        !           661:            err(1, "writing runetype_ext #%d to %s", n, locale_file);
        !           662:     }
        !           663:     /*
        !           664:      * PART 3: The maplower_ext structures
        !           665:      */
        !           666:     for (list = maplower.root, n = 0; list != NULL; list = list->next, n++) {
        !           667:        _FileRuneEntry re;
        !           668:
        !           669:        memset(&re, 0, sizeof(re));
        !           670:        re.fre_min = htonl(list->min);
        !           671:        re.fre_max = htonl(list->max);
        !           672:        re.fre_map = htonl(list->map);
        !           673:
        !           674:        if (fwrite((char *)&re, sizeof(re), 1, fp) != 1)
        !           675:            err(1, "writing maplower_ext #%d to %s", n, locale_file);
        !           676:     }
        !           677:     /*
        !           678:      * PART 4: The mapupper_ext structures
        !           679:      */
        !           680:     for (list = mapupper.root, n = 0; list != NULL; list = list->next, n++) {
        !           681:        _FileRuneEntry re;
        !           682:
        !           683:        memset(&re, 0, sizeof(re));
        !           684:        re.fre_min = htonl(list->min);
        !           685:        re.fre_max = htonl(list->max);
        !           686:        re.fre_map = htonl(list->map);
        !           687:
        !           688:        if (fwrite((char *)&re, sizeof(re), 1, fp) != 1)
        !           689:            err(1, "writing mapupper_ext #%d to %s", n, locale_file);
        !           690:     }
        !           691:     /*
        !           692:      * PART 5: The runetype_ext tables
        !           693:      */
        !           694:     for (list = types.root, n = 0; list != NULL; list = list->next, n++) {
        !           695:        for (x = 0; x < list->max - list->min + 1; ++x)
        !           696:            list->types[x] = htonl(list->types[x]);
        !           697:
        !           698:        if (!list->map) {
        !           699:            if (fwrite((char *)list->types,
        !           700:                       (list->max - list->min + 1) * sizeof(u_int32_t),
        !           701:                       1, fp) != 1)
        !           702:                err(1, "writing runetype_ext table #%d to %s", n, locale_file);
        !           703:        }
        !           704:     }
        !           705:     /*
        !           706:      * PART 5: And finally the variable data
        !           707:      */
        !           708:     if (new_locale.rl_variable_len != 0 &&
        !           709:        fwrite((char *)new_locale.rl_variable,
        !           710:               new_locale.rl_variable_len, 1, fp) != 1)
        !           711:        err(1, "writing variable data to %s", locale_file);
        !           712:     fclose(fp);
        !           713:
        !           714:     if (!debug)
        !           715:        return;
        !           716:
        !           717:     if (new_locale.rl_encoding[0])
        !           718:        fprintf(stderr, "ENCODING       %s\n", new_locale.rl_encoding);
        !           719:     if (new_locale.rl_variable)
        !           720:        fprintf(stderr, "VARIABLE       %s\n",
        !           721:                (char *)new_locale.rl_variable);
        !           722:
        !           723:     fprintf(stderr, "\nMAPLOWER:\n\n");
        !           724:
        !           725:     for (x = 0; x < _CACHED_RUNES; ++x) {
        !           726:        if (isprint(maplower.map[x]))
        !           727:            fprintf(stderr, " '%c'", (int)maplower.map[x]);
        !           728:        else if (maplower.map[x])
        !           729:            fprintf(stderr, "%04x", maplower.map[x]);
        !           730:        else
        !           731:            fprintf(stderr, "%4x", 0);
        !           732:        if ((x & 0xf) == 0xf)
        !           733:            fprintf(stderr, "\n");
        !           734:        else
        !           735:            fprintf(stderr, " ");
        !           736:     }
        !           737:     fprintf(stderr, "\n");
        !           738:
        !           739:     for (list = maplower.root; list; list = list->next)
        !           740:        fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map);
        !           741:
        !           742:     fprintf(stderr, "\nMAPUPPER:\n\n");
        !           743:
        !           744:     for (x = 0; x < _CACHED_RUNES; ++x) {
        !           745:        if (isprint(mapupper.map[x]))
        !           746:            fprintf(stderr, " '%c'", (int)mapupper.map[x]);
        !           747:        else if (mapupper.map[x])
        !           748:            fprintf(stderr, "%04x", mapupper.map[x]);
        !           749:        else
        !           750:            fprintf(stderr, "%4x", 0);
        !           751:        if ((x & 0xf) == 0xf)
        !           752:            fprintf(stderr, "\n");
        !           753:        else
        !           754:            fprintf(stderr, " ");
        !           755:     }
        !           756:     fprintf(stderr, "\n");
        !           757:
        !           758:     for (list = mapupper.root; list; list = list->next)
        !           759:        fprintf(stderr, "\t%04x - %04x : %04x\n", list->min, list->max, list->map);
        !           760:
        !           761:
        !           762:     fprintf(stderr, "\nTYPES:\n\n");
        !           763:
        !           764:     for (x = 0; x < _CACHED_RUNES; ++x) {
        !           765:        u_int32_t r = types.map[x];
        !           766:
        !           767:        if (r) {
        !           768:            if (isprint(x))
        !           769:                fprintf(stderr, " '%c':%2d", x, (int)(r & 0xff));
        !           770:            else
        !           771:                fprintf(stderr, "%04x:%2d", x, (int)(r & 0xff));
        !           772:
        !           773:            fprintf(stderr, " %4s", (r & _RUNETYPE_A) ? "alph" : "");
        !           774:            fprintf(stderr, " %4s", (r & _RUNETYPE_C) ? "ctrl" : "");
        !           775:            fprintf(stderr, " %4s", (r & _RUNETYPE_D) ? "dig" : "");
        !           776:            fprintf(stderr, " %4s", (r & _RUNETYPE_G) ? "graf" : "");
        !           777:            fprintf(stderr, " %4s", (r & _RUNETYPE_L) ? "low" : "");
        !           778:            fprintf(stderr, " %4s", (r & _RUNETYPE_P) ? "punc" : "");
        !           779:            fprintf(stderr, " %4s", (r & _RUNETYPE_S) ? "spac" : "");
        !           780:            fprintf(stderr, " %4s", (r & _RUNETYPE_U) ? "upp" : "");
        !           781:            fprintf(stderr, " %4s", (r & _RUNETYPE_X) ? "xdig" : "");
        !           782:            fprintf(stderr, " %4s", (r & _RUNETYPE_B) ? "blnk" : "");
        !           783:            fprintf(stderr, " %4s", (r & _RUNETYPE_R) ? "prnt" : "");
        !           784:            fprintf(stderr, " %4s", (r & _RUNETYPE_I) ? "ideo" : "");
        !           785:            fprintf(stderr, " %4s", (r & _RUNETYPE_T) ? "spec" : "");
        !           786:            fprintf(stderr, " %4s", (r & _RUNETYPE_Q) ? "phon" : "");
        !           787:            fprintf(stderr, "\n");
        !           788:        }
        !           789:     }
        !           790:
        !           791:     for (list = types.root; list; list = list->next) {
        !           792:        if (list->map && list->min + 3 < list->max) {
        !           793:            u_int32_t r = list->map;
        !           794:
        !           795:            fprintf(stderr, "%04x:%2d", list->min, r & 0xff);
        !           796:
        !           797:            fprintf(stderr, " %4s", (r & _RUNETYPE_A) ? "alph" : "");
        !           798:            fprintf(stderr, " %4s", (r & _RUNETYPE_C) ? "ctrl" : "");
        !           799:            fprintf(stderr, " %4s", (r & _RUNETYPE_D) ? "dig" : "");
        !           800:            fprintf(stderr, " %4s", (r & _RUNETYPE_G) ? "graf" : "");
        !           801:            fprintf(stderr, " %4s", (r & _RUNETYPE_L) ? "low" : "");
        !           802:            fprintf(stderr, " %4s", (r & _RUNETYPE_P) ? "punc" : "");
        !           803:            fprintf(stderr, " %4s", (r & _RUNETYPE_S) ? "spac" : "");
        !           804:            fprintf(stderr, " %4s", (r & _RUNETYPE_U) ? "upp" : "");
        !           805:            fprintf(stderr, " %4s", (r & _RUNETYPE_X) ? "xdig" : "");
        !           806:            fprintf(stderr, " %4s", (r & _RUNETYPE_B) ? "blnk" : "");
        !           807:            fprintf(stderr, " %4s", (r & _RUNETYPE_R) ? "prnt" : "");
        !           808:            fprintf(stderr, " %4s", (r & _RUNETYPE_I) ? "ideo" : "");
        !           809:            fprintf(stderr, " %4s", (r & _RUNETYPE_T) ? "spec" : "");
        !           810:            fprintf(stderr, " %4s", (r & _RUNETYPE_Q) ? "phon" : "");
        !           811:            fprintf(stderr, "\n...\n");
        !           812:
        !           813:            fprintf(stderr, "%04x:%2d", list->max, r & 0xff);
        !           814:
        !           815:            fprintf(stderr, " %4s", (r & _RUNETYPE_A) ? "alph" : "");
        !           816:            fprintf(stderr, " %4s", (r & _RUNETYPE_C) ? "ctrl" : "");
        !           817:            fprintf(stderr, " %4s", (r & _RUNETYPE_D) ? "dig" : "");
        !           818:            fprintf(stderr, " %4s", (r & _RUNETYPE_G) ? "graf" : "");
        !           819:            fprintf(stderr, " %4s", (r & _RUNETYPE_L) ? "low" : "");
        !           820:            fprintf(stderr, " %4s", (r & _RUNETYPE_P) ? "punc" : "");
        !           821:            fprintf(stderr, " %4s", (r & _RUNETYPE_S) ? "spac" : "");
        !           822:            fprintf(stderr, " %4s", (r & _RUNETYPE_U) ? "upp" : "");
        !           823:            fprintf(stderr, " %4s", (r & _RUNETYPE_X) ? "xdig" : "");
        !           824:            fprintf(stderr, " %4s", (r & _RUNETYPE_B) ? "blnk" : "");
        !           825:            fprintf(stderr, " %4s", (r & _RUNETYPE_R) ? "prnt" : "");
        !           826:            fprintf(stderr, " %4s", (r & _RUNETYPE_I) ? "ideo" : "");
        !           827:            fprintf(stderr, " %4s", (r & _RUNETYPE_T) ? "spec" : "");
        !           828:            fprintf(stderr, " %4s", (r & _RUNETYPE_Q) ? "phon" : "");
        !           829:             fprintf(stderr, " %1u", (unsigned)((r & _RUNETYPE_SWM)>>_RUNETYPE_SWS));
        !           830:            fprintf(stderr, "\n");
        !           831:        } else
        !           832:        for (x = list->min; x <= list->max; ++x) {
        !           833:            u_int32_t r = ntohl(list->types[x - list->min]);
        !           834:
        !           835:            if (r) {
        !           836:                fprintf(stderr, "%04x:%2d", x, (int)(r & 0xff));
        !           837:
        !           838:                fprintf(stderr, " %4s", (r & _RUNETYPE_A) ? "alph" : "");
        !           839:                fprintf(stderr, " %4s", (r & _RUNETYPE_C) ? "ctrl" : "");
        !           840:                fprintf(stderr, " %4s", (r & _RUNETYPE_D) ? "dig" : "");
        !           841:                fprintf(stderr, " %4s", (r & _RUNETYPE_G) ? "graf" : "");
        !           842:                fprintf(stderr, " %4s", (r & _RUNETYPE_L) ? "low" : "");
        !           843:                fprintf(stderr, " %4s", (r & _RUNETYPE_P) ? "punc" : "");
        !           844:                fprintf(stderr, " %4s", (r & _RUNETYPE_S) ? "spac" : "");
        !           845:                fprintf(stderr, " %4s", (r & _RUNETYPE_U) ? "upp" : "");
        !           846:                fprintf(stderr, " %4s", (r & _RUNETYPE_X) ? "xdig" : "");
        !           847:                fprintf(stderr, " %4s", (r & _RUNETYPE_B) ? "blnk" : "");
        !           848:                fprintf(stderr, " %4s", (r & _RUNETYPE_R) ? "prnt" : "");
        !           849:                fprintf(stderr, " %4s", (r & _RUNETYPE_I) ? "ideo" : "");
        !           850:                fprintf(stderr, " %4s", (r & _RUNETYPE_T) ? "spec" : "");
        !           851:                fprintf(stderr, " %4s", (r & _RUNETYPE_Q) ? "phon" : "");
        !           852:                 fprintf(stderr, " %1u", (unsigned)((r & _RUNETYPE_SWM)>>_RUNETYPE_SWS));
        !           853:                fprintf(stderr, "\n");
        !           854:            }
        !           855:        }
        !           856:     }
        !           857: }