Annotation of embedaddon/lrzsz/intl/l10nflist.c, revision 1.1

1.1     ! misho       1: /* Handle list of needed message catalogs
        !             2:    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
        !             3:    Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
        !             4: 
        !             5:    This program is free software; you can redistribute it and/or modify
        !             6:    it under the terms of the GNU General Public License as published by
        !             7:    the Free Software Foundation; either version 2, or (at your option)
        !             8:    any later version.
        !             9: 
        !            10:    This program is distributed in the hope that it will be useful,
        !            11:    but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            12:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            13:    GNU General Public License for more details.
        !            14: 
        !            15:    You should have received a copy of the GNU General Public License
        !            16:    along with this program; if not, write to the Free Software Foundation,
        !            17:    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
        !            18: 
        !            19: #ifdef HAVE_CONFIG_H
        !            20: # include <config.h>
        !            21: #endif
        !            22: 
        !            23: 
        !            24: #if defined HAVE_STRING_H || defined _LIBC
        !            25: # ifndef _GNU_SOURCE
        !            26: #  define _GNU_SOURCE  1
        !            27: # endif
        !            28: # include <string.h>
        !            29: #else
        !            30: # include <strings.h>
        !            31: # ifndef memcpy
        !            32: #  define memcpy(Dst, Src, Num) bcopy (Src, Dst, Num)
        !            33: # endif
        !            34: #endif
        !            35: #if !HAVE_STRCHR && !defined _LIBC
        !            36: # ifndef strchr
        !            37: #  define strchr index
        !            38: # endif
        !            39: #endif
        !            40: 
        !            41: #if defined _LIBC || defined HAVE_ARGZ_H
        !            42: # include <argz.h>
        !            43: #endif
        !            44: #include <ctype.h>
        !            45: #include <sys/types.h>
        !            46: 
        !            47: #if defined STDC_HEADERS || defined _LIBC
        !            48: # include <stdlib.h>
        !            49: #endif
        !            50: 
        !            51: #include "loadinfo.h"
        !            52: 
        !            53: /* On some strange systems still no definition of NULL is found.  Sigh!  */
        !            54: #ifndef NULL
        !            55: # if defined __STDC__ && __STDC__
        !            56: #  define NULL ((void *) 0)
        !            57: # else
        !            58: #  define NULL 0
        !            59: # endif
        !            60: #endif
        !            61: 
        !            62: /* @@ end of prolog @@ */
        !            63: 
        !            64: #ifdef _LIBC
        !            65: /* Rename the non ANSI C functions.  This is required by the standard
        !            66:    because some ANSI C functions will require linking with this object
        !            67:    file and the name space must not be polluted.  */
        !            68: # define stpcpy(dest, src) __stpcpy(dest, src)
        !            69: #else
        !            70: # ifndef HAVE_STPCPY
        !            71: static char *stpcpy PARAMS ((char *dest, const char *src));
        !            72: # endif
        !            73: #endif
        !            74: 
        !            75: /* Define function which are usually not available.  */
        !            76: 
        !            77: #if !defined _LIBC && !defined HAVE___ARGZ_COUNT
        !            78: /* Returns the number of strings in ARGZ.  */
        !            79: static size_t argz_count__ PARAMS ((const char *argz, size_t len));
        !            80: 
        !            81: static size_t
        !            82: argz_count__ (argz, len)
        !            83:      const char *argz;
        !            84:      size_t len;
        !            85: {
        !            86:   size_t count = 0;
        !            87:   while (len > 0)
        !            88:     {
        !            89:       size_t part_len = strlen (argz);
        !            90:       argz += part_len + 1;
        !            91:       len -= part_len + 1;
        !            92:       count++;
        !            93:     }
        !            94:   return count;
        !            95: }
        !            96: # undef __argz_count
        !            97: # define __argz_count(argz, len) argz_count__ (argz, len)
        !            98: #endif /* !_LIBC && !HAVE___ARGZ_COUNT */
        !            99: 
        !           100: #if !defined _LIBC && !defined HAVE___ARGZ_STRINGIFY
        !           101: /* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
        !           102:    except the last into the character SEP.  */
        !           103: static void argz_stringify__ PARAMS ((char *argz, size_t len, int sep));
        !           104: 
        !           105: static void
        !           106: argz_stringify__ (argz, len, sep)
        !           107:      char *argz;
        !           108:      size_t len;
        !           109:      int sep;
        !           110: {
        !           111:   while (len > 0)
        !           112:     {
        !           113:       size_t part_len = strlen (argz);
        !           114:       argz += part_len;
        !           115:       len -= part_len + 1;
        !           116:       if (len > 0)
        !           117:        *argz++ = sep;
        !           118:     }
        !           119: }
        !           120: # undef __argz_stringify
        !           121: # define __argz_stringify(argz, len, sep) argz_stringify__ (argz, len, sep)
        !           122: #endif /* !_LIBC && !HAVE___ARGZ_STRINGIFY */
        !           123: 
        !           124: #if !defined _LIBC && !defined HAVE___ARGZ_NEXT
        !           125: static char *argz_next__ PARAMS ((char *argz, size_t argz_len,
        !           126:                                  const char *entry));
        !           127: 
        !           128: static char *
        !           129: argz_next__ (argz, argz_len, entry)
        !           130:      char *argz;
        !           131:      size_t argz_len;
        !           132:      const char *entry;
        !           133: {
        !           134:   if (entry)
        !           135:     {
        !           136:       if (entry < argz + argz_len)
        !           137:         entry = strchr (entry, '\0') + 1;
        !           138: 
        !           139:       return entry >= argz + argz_len ? NULL : (char *) entry;
        !           140:     }
        !           141:   else
        !           142:     if (argz_len > 0)
        !           143:       return argz;
        !           144:     else
        !           145:       return 0;
        !           146: }
        !           147: # undef __argz_next
        !           148: # define __argz_next(argz, len, entry) argz_next__ (argz, len, entry)
        !           149: #endif /* !_LIBC && !HAVE___ARGZ_NEXT */
        !           150: 
        !           151: 
        !           152: /* Return number of bits set in X.  */
        !           153: static int pop PARAMS ((int x));
        !           154: 
        !           155: static inline int
        !           156: pop (x)
        !           157:      int x;
        !           158: {
        !           159:   /* We assume that no more than 16 bits are used.  */
        !           160:   x = ((x & ~0x5555) >> 1) + (x & 0x5555);
        !           161:   x = ((x & ~0x3333) >> 2) + (x & 0x3333);
        !           162:   x = ((x >> 4) + x) & 0x0f0f;
        !           163:   x = ((x >> 8) + x) & 0xff;
        !           164: 
        !           165:   return x;
        !           166: }
        !           167: 
        !           168: 
        !           169: struct loaded_l10nfile *
        !           170: _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
        !           171:                    territory, codeset, normalized_codeset, modifier, special,
        !           172:                    sponsor, revision, filename, do_allocate)
        !           173:      struct loaded_l10nfile **l10nfile_list;
        !           174:      const char *dirlist;
        !           175:      size_t dirlist_len;
        !           176:      int mask;
        !           177:      const char *language;
        !           178:      const char *territory;
        !           179:      const char *codeset;
        !           180:      const char *normalized_codeset;
        !           181:      const char *modifier;
        !           182:      const char *special;
        !           183:      const char *sponsor;
        !           184:      const char *revision;
        !           185:      const char *filename;
        !           186:      int do_allocate;
        !           187: {
        !           188:   char *abs_filename;
        !           189:   struct loaded_l10nfile *last = NULL;
        !           190:   struct loaded_l10nfile *retval;
        !           191:   char *cp;
        !           192:   size_t entries;
        !           193:   int cnt;
        !           194: 
        !           195:   /* Allocate room for the full file name.  */
        !           196:   abs_filename = (char *) malloc (dirlist_len
        !           197:                                  + strlen (language)
        !           198:                                  + ((mask & TERRITORY) != 0
        !           199:                                     ? strlen (territory) + 1 : 0)
        !           200:                                  + ((mask & XPG_CODESET) != 0
        !           201:                                     ? strlen (codeset) + 1 : 0)
        !           202:                                  + ((mask & XPG_NORM_CODESET) != 0
        !           203:                                     ? strlen (normalized_codeset) + 1 : 0)
        !           204:                                  + (((mask & XPG_MODIFIER) != 0
        !           205:                                      || (mask & CEN_AUDIENCE) != 0)
        !           206:                                     ? strlen (modifier) + 1 : 0)
        !           207:                                  + ((mask & CEN_SPECIAL) != 0
        !           208:                                     ? strlen (special) + 1 : 0)
        !           209:                                  + (((mask & CEN_SPONSOR) != 0
        !           210:                                      || (mask & CEN_REVISION) != 0)
        !           211:                                     ? (1 + ((mask & CEN_SPONSOR) != 0
        !           212:                                             ? strlen (sponsor) + 1 : 0)
        !           213:                                        + ((mask & CEN_REVISION) != 0
        !           214:                                           ? strlen (revision) + 1 : 0)) : 0)
        !           215:                                  + 1 + strlen (filename) + 1);
        !           216: 
        !           217:   if (abs_filename == NULL)
        !           218:     return NULL;
        !           219: 
        !           220:   retval = NULL;
        !           221:   last = NULL;
        !           222: 
        !           223:   /* Construct file name.  */
        !           224:   memcpy (abs_filename, dirlist, dirlist_len);
        !           225:   __argz_stringify (abs_filename, dirlist_len, ':');
        !           226:   cp = abs_filename + (dirlist_len - 1);
        !           227:   *cp++ = '/';
        !           228:   cp = stpcpy (cp, language);
        !           229: 
        !           230:   if ((mask & TERRITORY) != 0)
        !           231:     {
        !           232:       *cp++ = '_';
        !           233:       cp = stpcpy (cp, territory);
        !           234:     }
        !           235:   if ((mask & XPG_CODESET) != 0)
        !           236:     {
        !           237:       *cp++ = '.';
        !           238:       cp = stpcpy (cp, codeset);
        !           239:     }
        !           240:   if ((mask & XPG_NORM_CODESET) != 0)
        !           241:     {
        !           242:       *cp++ = '.';
        !           243:       cp = stpcpy (cp, normalized_codeset);
        !           244:     }
        !           245:   if ((mask & (XPG_MODIFIER | CEN_AUDIENCE)) != 0)
        !           246:     {
        !           247:       /* This component can be part of both syntaces but has different
        !           248:         leading characters.  For CEN we use `+', else `@'.  */
        !           249:       *cp++ = (mask & CEN_AUDIENCE) != 0 ? '+' : '@';
        !           250:       cp = stpcpy (cp, modifier);
        !           251:     }
        !           252:   if ((mask & CEN_SPECIAL) != 0)
        !           253:     {
        !           254:       *cp++ = '+';
        !           255:       cp = stpcpy (cp, special);
        !           256:     }
        !           257:   if ((mask & (CEN_SPONSOR | CEN_REVISION)) != 0)
        !           258:     {
        !           259:       *cp++ = ',';
        !           260:       if ((mask & CEN_SPONSOR) != 0)
        !           261:        cp = stpcpy (cp, sponsor);
        !           262:       if ((mask & CEN_REVISION) != 0)
        !           263:        {
        !           264:          *cp++ = '_';
        !           265:          cp = stpcpy (cp, revision);
        !           266:        }
        !           267:     }
        !           268: 
        !           269:   *cp++ = '/';
        !           270:   stpcpy (cp, filename);
        !           271: 
        !           272:   /* Look in list of already loaded domains whether it is already
        !           273:      available.  */
        !           274:   last = NULL;
        !           275:   for (retval = *l10nfile_list; retval != NULL; retval = retval->next)
        !           276:     if (retval->filename != NULL)
        !           277:       {
        !           278:        int compare = strcmp (retval->filename, abs_filename);
        !           279:        if (compare == 0)
        !           280:          /* We found it!  */
        !           281:          break;
        !           282:        if (compare < 0)
        !           283:          {
        !           284:            /* It's not in the list.  */
        !           285:            retval = NULL;
        !           286:            break;
        !           287:          }
        !           288: 
        !           289:        last = retval;
        !           290:       }
        !           291: 
        !           292:   if (retval != NULL || do_allocate == 0)
        !           293:     {
        !           294:       free (abs_filename);
        !           295:       return retval;
        !           296:     }
        !           297: 
        !           298:   retval = (struct loaded_l10nfile *)
        !           299:     malloc (sizeof (*retval) + (__argz_count (dirlist, dirlist_len)
        !           300:                                * (1 << pop (mask))
        !           301:                                * sizeof (struct loaded_l10nfile *)));
        !           302:   if (retval == NULL)
        !           303:     return NULL;
        !           304: 
        !           305:   retval->filename = abs_filename;
        !           306:   retval->decided = (__argz_count (dirlist, dirlist_len) != 1
        !           307:                     || ((mask & XPG_CODESET) != 0
        !           308:                         && (mask & XPG_NORM_CODESET) != 0));
        !           309:   retval->data = NULL;
        !           310: 
        !           311:   if (last == NULL)
        !           312:     {
        !           313:       retval->next = *l10nfile_list;
        !           314:       *l10nfile_list = retval;
        !           315:     }
        !           316:   else
        !           317:     {
        !           318:       retval->next = last->next;
        !           319:       last->next = retval;
        !           320:     }
        !           321: 
        !           322:   entries = 0;
        !           323:   /* If the DIRLIST is a real list the RETVAL entry corresponds not to
        !           324:      a real file.  So we have to use the DIRLIST separation mechanism
        !           325:      of the inner loop.  */
        !           326:   cnt = __argz_count (dirlist, dirlist_len) == 1 ? mask - 1 : mask;
        !           327:   for (; cnt >= 0; --cnt)
        !           328:     if ((cnt & ~mask) == 0
        !           329:        && ((cnt & CEN_SPECIFIC) == 0 || (cnt & XPG_SPECIFIC) == 0)
        !           330:        && ((cnt & XPG_CODESET) == 0 || (cnt & XPG_NORM_CODESET) == 0))
        !           331:       {
        !           332:        /* Iterate over all elements of the DIRLIST.  */
        !           333:        char *dir = NULL;
        !           334: 
        !           335:        while ((dir = __argz_next ((char *) dirlist, dirlist_len, dir))
        !           336:               != NULL)
        !           337:          retval->successor[entries++]
        !           338:            = _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
        !           339:                                  language, territory, codeset,
        !           340:                                  normalized_codeset, modifier, special,
        !           341:                                  sponsor, revision, filename, 1);
        !           342:       }
        !           343:   retval->successor[entries] = NULL;
        !           344: 
        !           345:   return retval;
        !           346: }
        !           347: 
        !           348: /* Normalize codeset name.  There is no standard for the codeset
        !           349:    names.  Normalization allows the user to use any of the common
        !           350:    names.  */
        !           351: const char *
        !           352: _nl_normalize_codeset (codeset, name_len)
        !           353:      const char *codeset;
        !           354:      size_t name_len;
        !           355: {
        !           356:   int len = 0;
        !           357:   int only_digit = 1;
        !           358:   char *retval;
        !           359:   char *wp;
        !           360:   size_t cnt;
        !           361: 
        !           362:   for (cnt = 0; cnt < name_len; ++cnt)
        !           363:     if (isalnum (codeset[cnt]))
        !           364:       {
        !           365:        ++len;
        !           366: 
        !           367:        if (isalpha (codeset[cnt]))
        !           368:          only_digit = 0;
        !           369:       }
        !           370: 
        !           371:   retval = (char *) malloc ((only_digit ? 3 : 0) + len + 1);
        !           372: 
        !           373:   if (retval != NULL)
        !           374:     {
        !           375:       if (only_digit)
        !           376:        wp = stpcpy (retval, "iso");
        !           377:       else
        !           378:        wp = retval;
        !           379: 
        !           380:       for (cnt = 0; cnt < name_len; ++cnt)
        !           381:        if (isalpha (codeset[cnt]))
        !           382:          *wp++ = tolower (codeset[cnt]);
        !           383:        else if (isdigit (codeset[cnt]))
        !           384:          *wp++ = codeset[cnt];
        !           385: 
        !           386:       *wp = '\0';
        !           387:     }
        !           388: 
        !           389:   return (const char *) retval;
        !           390: }
        !           391: 
        !           392: 
        !           393: /* @@ begin of epilog @@ */
        !           394: 
        !           395: /* We don't want libintl.a to depend on any other library.  So we
        !           396:    avoid the non-standard function stpcpy.  In GNU C Library this
        !           397:    function is available, though.  Also allow the symbol HAVE_STPCPY
        !           398:    to be defined.  */
        !           399: #if !_LIBC && !HAVE_STPCPY
        !           400: static char *
        !           401: stpcpy (dest, src)
        !           402:      char *dest;
        !           403:      const char *src;
        !           404: {
        !           405:   while ((*dest++ = *src++) != '\0')
        !           406:     /* Do nothing. */ ;
        !           407:   return dest - 1;
        !           408: }
        !           409: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>