|
Packit Service |
a8c26c |
/***********************************************************************
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* This software is part of the ast package *
|
|
Packit Service |
a8c26c |
* Copyright (c) 1985-2011 AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* and is licensed under the *
|
|
Packit Service |
a8c26c |
* Eclipse Public License, Version 1.0 *
|
|
Packit Service |
a8c26c |
* by AT&T Intellectual Property *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* A copy of the License is available at *
|
|
Packit Service |
a8c26c |
* http://www.eclipse.org/org/documents/epl-v10.html *
|
|
Packit Service |
a8c26c |
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Information and Software Systems Research *
|
|
Packit Service |
a8c26c |
* AT&T Research *
|
|
Packit Service |
a8c26c |
* Florham Park NJ *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
* Glenn Fowler <gsf@research.att.com> *
|
|
Packit Service |
a8c26c |
* David Korn <dgk@research.att.com> *
|
|
Packit Service |
a8c26c |
* Phong Vo <kpv@research.att.com> *
|
|
Packit Service |
a8c26c |
* *
|
|
Packit Service |
a8c26c |
***********************************************************************/
|
|
Packit Service |
a8c26c |
#pragma prototyped
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* Glenn Fowler
|
|
Packit Service |
a8c26c |
* AT&T Research
|
|
Packit Service |
a8c26c |
*
|
|
Packit Service |
a8c26c |
* machine independent binary message catalog implementation
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include "sfhdr.h"
|
|
Packit Service |
a8c26c |
#include "lclib.h"
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include <iconv.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#define _MC_PRIVATE_ \
|
|
Packit Service |
a8c26c |
size_t nstrs; \
|
|
Packit Service |
a8c26c |
size_t nmsgs; \
|
|
Packit Service |
a8c26c |
iconv_t cvt; \
|
|
Packit Service |
a8c26c |
Sfio_t* tmp; \
|
|
Packit Service |
a8c26c |
Vmalloc_t* vm;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
#include <vmalloc.h>
|
|
Packit Service |
a8c26c |
#include <error.h>
|
|
Packit Service |
a8c26c |
#include <mc.h>
|
|
Packit Service |
a8c26c |
#include <nl_types.h>
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* find the binary message catalog path for <locale,catalog>
|
|
Packit Service |
a8c26c |
* result placed in path of size PATH_MAX
|
|
Packit Service |
a8c26c |
* pointer to path returned
|
|
Packit Service |
a8c26c |
* catalog==0 tests for category directory or file
|
|
Packit Service |
a8c26c |
* nls!=0 enables NLSPATH+LANG hack (not implemented yet)
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
char*
|
|
Packit Service |
a8c26c |
mcfind(const char* locale, const char* catalog, int category, int nls, char* path, size_t size)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
register int c;
|
|
Packit Service |
a8c26c |
register char* s;
|
|
Packit Service |
a8c26c |
register char* e;
|
|
Packit Service |
a8c26c |
register char* p;
|
|
Packit Service |
a8c26c |
register const char* v;
|
|
Packit Service |
a8c26c |
int i;
|
|
Packit Service |
a8c26c |
int first;
|
|
Packit Service |
a8c26c |
int next;
|
|
Packit Service |
a8c26c |
int last;
|
|
Packit Service |
a8c26c |
int oerrno;
|
|
Packit Service |
a8c26c |
Lc_t* lc;
|
|
Packit Service |
a8c26c |
char file[PATH_MAX];
|
|
Packit Service |
a8c26c |
char* paths[5];
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
static char lc_messages[] = "LC_MESSAGES";
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if ((category = lcindex(category, 1)) < 0)
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
if (!(lc = locale ? lcmake(locale) : locales[category]))
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
oerrno = errno;
|
|
Packit Service |
a8c26c |
if (catalog && *catalog == '/')
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
i = eaccess(catalog, R_OK);
|
|
Packit Service |
a8c26c |
errno = oerrno;
|
|
Packit Service |
a8c26c |
if (i)
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
strlcpy(path, catalog, size);
|
|
Packit Service |
a8c26c |
return path;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
i = 0;
|
|
Packit Service |
a8c26c |
if ((p = getenv("NLSPATH")) && *p)
|
|
Packit Service |
a8c26c |
paths[i++] = p;
|
|
Packit Service |
a8c26c |
paths[i++] = "share/lib/locale/%l/%C/%N";
|
|
Packit Service |
a8c26c |
paths[i++] = "share/locale/%l/%C/%N";
|
|
Packit Service |
a8c26c |
paths[i++] = "lib/locale/%l/%C/%N";
|
|
Packit Service |
a8c26c |
paths[i] = 0;
|
|
Packit Service |
a8c26c |
next = 1;
|
|
Packit Service |
a8c26c |
for (i = 0; p = paths[i]; i += next)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
first = 1;
|
|
Packit Service |
a8c26c |
last = 0;
|
|
Packit Service |
a8c26c |
e = &file[elementsof(file) - 1];
|
|
Packit Service |
a8c26c |
while (*p)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
s = file;
|
|
Packit Service |
a8c26c |
for (;;)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
switch (c = *p++)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
case 0:
|
|
Packit Service |
a8c26c |
p--;
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
case ':':
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
case '%':
|
|
Packit Service |
a8c26c |
if (s < e)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
switch (c = *p++)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
case 0:
|
|
Packit Service |
a8c26c |
p--;
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
case 'N':
|
|
Packit Service |
a8c26c |
v = catalog;
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
case 'L':
|
|
Packit Service |
a8c26c |
if (first)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
first = 0;
|
|
Packit Service |
a8c26c |
if (next)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
v = lc->code;
|
|
Packit Service |
a8c26c |
if (lc->code != lc->language->code)
|
|
Packit Service |
a8c26c |
next = 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
next = 1;
|
|
Packit Service |
a8c26c |
v = lc->language->code;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
case 'l':
|
|
Packit Service |
a8c26c |
v = lc->language->code;
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
case 't':
|
|
Packit Service |
a8c26c |
v = lc->territory->code;
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
case 'c':
|
|
Packit Service |
a8c26c |
v = lc->charset->code;
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
case 'C':
|
|
Packit Service |
a8c26c |
case_C:
|
|
Packit Service |
a8c26c |
if (!catalog)
|
|
Packit Service |
a8c26c |
last = 1;
|
|
Packit Service |
a8c26c |
v = lc_categories[category].name;
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
default:
|
|
Packit Service |
a8c26c |
*s++ = c;
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (v)
|
|
Packit Service |
a8c26c |
while (*v && s < e)
|
|
Packit Service |
a8c26c |
*s++ = *v++;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
case '/':
|
|
Packit Service |
a8c26c |
if (last)
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
if (category != AST_LC_MESSAGES && strneq(p, lc_messages, sizeof(lc_messages) - 1) && p[sizeof(lc_messages)-1] == '/')
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
p += sizeof(lc_messages) - 1;
|
|
Packit Service |
a8c26c |
goto case_C;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
/*FALLTHROUGH*/
|
|
Packit Service |
a8c26c |
default:
|
|
Packit Service |
a8c26c |
if (s < e)
|
|
Packit Service |
a8c26c |
*s++ = c;
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
break;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (s > file)
|
|
Packit Service |
a8c26c |
*s = 0;
|
|
Packit Service |
a8c26c |
else if (!catalog)
|
|
Packit Service |
a8c26c |
continue;
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
strlcpy(file, catalog, elementsof(file));
|
|
Packit Service |
a8c26c |
if (ast.locale.set & AST_LC_find)
|
|
Packit Service |
a8c26c |
sfprintf(sfstderr, "locale find %s\n", file);
|
|
Packit Service |
a8c26c |
if (s = pathpath(file, "", (!catalog && category == AST_LC_MESSAGES) ? PATH_READ : (PATH_REGULAR|PATH_READ|PATH_ABSOLUTE), path, size))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (ast.locale.set & (AST_LC_find|AST_LC_setlocale))
|
|
Packit Service |
a8c26c |
sfprintf(sfstderr, "locale path %s\n", s);
|
|
Packit Service |
a8c26c |
errno = oerrno;
|
|
Packit Service |
a8c26c |
return s;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
errno = oerrno;
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* allocate and read the binary message catalog ip
|
|
Packit Service |
a8c26c |
* if ip==0 then space is allocated for mcput()
|
|
Packit Service |
a8c26c |
* 0 returned on any error
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
Mc_t*
|
|
Packit Service |
a8c26c |
mcopen(register Sfio_t* ip)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
register Mc_t* mc;
|
|
Packit Service |
a8c26c |
register char** mp;
|
|
Packit Service |
a8c26c |
register char* sp;
|
|
Packit Service |
a8c26c |
Vmalloc_t* vm;
|
|
Packit Service |
a8c26c |
char* rp;
|
|
Packit Service |
a8c26c |
int i;
|
|
Packit Service |
a8c26c |
int j;
|
|
Packit Service |
a8c26c |
int oerrno;
|
|
Packit Service |
a8c26c |
size_t n;
|
|
Packit Service |
a8c26c |
char buf[MC_MAGIC_SIZE];
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
oerrno = errno;
|
|
Packit Service |
a8c26c |
if (ip)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* check the magic
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (sfread(ip, buf, MC_MAGIC_SIZE) != MC_MAGIC_SIZE)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
errno = oerrno;
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (memcmp(buf, MC_MAGIC, MC_MAGIC_SIZE))
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* allocate the region
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (!(vm = vmopen(Vmdcheap, Vmbest, 0)) || !(mc = vmnewof(vm, 0, Mc_t, 1, 0)))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
errno = oerrno;
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
mc->vm = vm;
|
|
Packit Service |
a8c26c |
mc->cvt = (iconv_t)(-1);
|
|
Packit Service |
a8c26c |
if (ip)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* read the translation record
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (!(sp = sfgetr(ip, 0, 0)) || !(mc->translation = vmstrdup(vm, sp)))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* read the optional header records
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
do
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (!(sp = sfgetr(ip, 0, 0)))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
} while (*sp);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* get the component dimensions
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
mc->nstrs = sfgetu(ip);
|
|
Packit Service |
a8c26c |
mc->nmsgs = sfgetu(ip);
|
|
Packit Service |
a8c26c |
mc->num = sfgetu(ip);
|
|
Packit Service |
a8c26c |
if (sfeof(ip))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else if (!(mc->translation = vmnewof(vm, 0, char, 1, 0)))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* allocate the remaining space
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (!(mc->set = vmnewof(vm, 0, Mcset_t, mc->num + 1, 0)))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
if (!ip)
|
|
Packit Service |
a8c26c |
return mc;
|
|
Packit Service |
a8c26c |
if (!(mp = vmnewof(vm, 0, char*, mc->nmsgs + mc->num + 1, 0)))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
if (!(rp = sp = vmalloc(vm, mc->nstrs + 1)))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* get the set dimensions and initialize the msg pointers
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
while (i = sfgetu(ip))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (i > mc->num)
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
n = sfgetu(ip);
|
|
Packit Service |
a8c26c |
mc->set[i].num = n;
|
|
Packit Service |
a8c26c |
mc->set[i].msg = mp;
|
|
Packit Service |
a8c26c |
mp += n + 1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* read the msg sizes and set up the msg pointers
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for (i = 1; i <= mc->num; i++)
|
|
Packit Service |
a8c26c |
for (j = 1; j <= mc->set[i].num; j++)
|
|
Packit Service |
a8c26c |
if (n = sfgetu(ip))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
mc->set[i].msg[j] = sp;
|
|
Packit Service |
a8c26c |
sp += n;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* read the string table
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (sfread(ip, rp, mc->nstrs) != mc->nstrs || sfgetc(ip) != EOF)
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
if (!(mc->tmp = sfstropen()))
|
|
Packit Service |
a8c26c |
goto bad;
|
|
Packit Service |
a8c26c |
mc->cvt = iconv_open("", "utf");
|
|
Packit Service |
a8c26c |
errno = oerrno;
|
|
Packit Service |
a8c26c |
return mc;
|
|
Packit Service |
a8c26c |
bad:
|
|
Packit Service |
a8c26c |
vmclose(vm);
|
|
Packit Service |
a8c26c |
errno = oerrno;
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* return the <set,num> message in mc
|
|
Packit Service |
a8c26c |
* msg returned on error
|
|
Packit Service |
a8c26c |
* utf message text converted to ucs
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
char*
|
|
Packit Service |
a8c26c |
mcget(register Mc_t* mc, int set, int num, const char* msg)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
char* s;
|
|
Packit Service |
a8c26c |
size_t n;
|
|
Packit Service |
a8c26c |
int p;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (!mc || set < 0 || set > mc->num || num < 1 || num > mc->set[set].num || !(s = mc->set[set].msg[num]))
|
|
Packit Service |
a8c26c |
return (char*)msg;
|
|
Packit Service |
a8c26c |
if (mc->cvt == (iconv_t)(-1))
|
|
Packit Service |
a8c26c |
return s;
|
|
Packit Service |
a8c26c |
if ((p = sfstrtell(mc->tmp)) > sfstrsize(mc->tmp) / 2)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
p = 0;
|
|
Packit Service |
a8c26c |
sfstrseek(mc->tmp, p, SEEK_SET);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
n = strlen(s) + 1;
|
|
Packit Service |
a8c26c |
iconv_write(mc->cvt, mc->tmp, &s, &n, NiL);
|
|
Packit Service |
a8c26c |
return sfstrbase(mc->tmp) + p;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* set message <set,num> to msg
|
|
Packit Service |
a8c26c |
* msg==0 deletes the message
|
|
Packit Service |
a8c26c |
* the message and set counts are adjusted
|
|
Packit Service |
a8c26c |
* 0 returned on success, -1 otherwise
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
int
|
|
Packit Service |
a8c26c |
mcput(register Mc_t* mc, int set, int num, const char* msg)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
register int i;
|
|
Packit Service |
a8c26c |
register char* s;
|
|
Packit Service |
a8c26c |
register Mcset_t* sp;
|
|
Packit Service |
a8c26c |
register char** mp;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* validate the arguments
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (!mc || set > MC_SET_MAX || num > MC_NUM_MAX)
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* deletions don't kick in allocations (duh)
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (!msg)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (set <= mc->num && num <= mc->set[set].num && (s = mc->set[set].msg[num]))
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* decrease the string table size
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
mc->set[set].msg[num] = 0;
|
|
Packit Service |
a8c26c |
mc->nstrs -= strlen(s) + 1;
|
|
Packit Service |
a8c26c |
if (mc->set[set].num == num)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* decrease the max msg num
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
mp = mc->set[set].msg + num;
|
|
Packit Service |
a8c26c |
while (num && !mp[--num]);
|
|
Packit Service |
a8c26c |
mc->nmsgs -= mc->set[set].num - num;
|
|
Packit Service |
a8c26c |
if (!(mc->set[set].num = num) && mc->num == set)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* decrease the max set num
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
while (num && !mc->set[--num].num);
|
|
Packit Service |
a8c26c |
mc->num = num;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* keep track of the highest set and allocate if necessary
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (set > mc->num)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (set > mc->gen)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
i = MC_SET_MAX;
|
|
Packit Service |
a8c26c |
if (!(sp = vmnewof(mc->vm, 0, Mcset_t, i + 1, 0)))
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
mc->gen = i;
|
|
Packit Service |
a8c26c |
for (i = 1; i <= mc->num; i++)
|
|
Packit Service |
a8c26c |
sp[i] = mc->set[i];
|
|
Packit Service |
a8c26c |
mc->set = sp;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
mc->num = set;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
sp = mc->set + set;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* keep track of the highest msg and allocate if necessary
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (num > sp->num)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (num > sp->gen)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (!mc->gen)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
i = (MC_NUM_MAX + 1) / 32;
|
|
Packit Service |
a8c26c |
if (i <= num)
|
|
Packit Service |
a8c26c |
i = 2 * num;
|
|
Packit Service |
a8c26c |
if (i > MC_NUM_MAX)
|
|
Packit Service |
a8c26c |
i = MC_NUM_MAX;
|
|
Packit Service |
a8c26c |
if (!(mp = vmnewof(mc->vm, 0, char*, i + 1, 0)))
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
mc->gen = i;
|
|
Packit Service |
a8c26c |
sp->msg = mp;
|
|
Packit Service |
a8c26c |
for (i = 1; i <= sp->num; i++)
|
|
Packit Service |
a8c26c |
mp[i] = sp->msg[i];
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
i = 2 * mc->gen;
|
|
Packit Service |
a8c26c |
if (i > MC_NUM_MAX)
|
|
Packit Service |
a8c26c |
i = MC_NUM_MAX;
|
|
Packit Service |
a8c26c |
if (!(mp = vmnewof(mc->vm, sp->msg, char*, i + 1, 0)))
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
sp->gen = i;
|
|
Packit Service |
a8c26c |
sp->msg = mp;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
mc->nmsgs += num - sp->num;
|
|
Packit Service |
a8c26c |
sp->num = num;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* decrease the string table size
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (s = sp->msg[num])
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* no-op if no change
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (streq(s, msg))
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
mc->nstrs -= strlen(s) + 1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* allocate, add and adjust the string table size
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (!(s = vmstrdup(mc->vm, msg)))
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
sp->msg[num] = s;
|
|
Packit Service |
a8c26c |
mc->nstrs += strlen(s) + 1;
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* dump message catalog mc to op
|
|
Packit Service |
a8c26c |
* 0 returned on success, -1 otherwise
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
int
|
|
Packit Service |
a8c26c |
mcdump(register Mc_t* mc, register Sfio_t* op)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
register int i;
|
|
Packit Service |
a8c26c |
register int j;
|
|
Packit Service |
a8c26c |
register int n;
|
|
Packit Service |
a8c26c |
register char* s;
|
|
Packit Service |
a8c26c |
register Mcset_t* sp;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* write the magic
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
if (sfwrite(op, MC_MAGIC, MC_MAGIC_SIZE) != MC_MAGIC_SIZE)
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* write the translation record
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
sfputr(op, mc->translation, 0);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/* optional header records here */
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* end of optional header records
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
sfputu(op, 0);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* write the global dimensions
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
sfputu(op, mc->nstrs);
|
|
Packit Service |
a8c26c |
sfputu(op, mc->nmsgs);
|
|
Packit Service |
a8c26c |
sfputu(op, mc->num);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* write the set dimensions
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for (i = 1; i <= mc->num; i++)
|
|
Packit Service |
a8c26c |
if (mc->set[i].num)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
sfputu(op, i);
|
|
Packit Service |
a8c26c |
sfputu(op, mc->set[i].num);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
sfputu(op, 0);
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* write the message sizes
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for (i = 1; i <= mc->num; i++)
|
|
Packit Service |
a8c26c |
if (mc->set[i].num)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
sp = mc->set + i;
|
|
Packit Service |
a8c26c |
for (j = 1; j <= sp->num; j++)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
n = (s = sp->msg[j]) ? (strlen(s) + 1) : 0;
|
|
Packit Service |
a8c26c |
sfputu(op, n);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* write the string table
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
for (i = 1; i <= mc->num; i++)
|
|
Packit Service |
a8c26c |
if (mc->set[i].num)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
sp = mc->set + i;
|
|
Packit Service |
a8c26c |
for (j = 1; j <= sp->num; j++)
|
|
Packit Service |
a8c26c |
if (s = sp->msg[j])
|
|
Packit Service |
a8c26c |
sfputr(op, s, 0);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* sync and return
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
return sfsync(op);
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* parse <set,msg> number from s
|
|
Packit Service |
a8c26c |
* e!=0 is set to the next char after the parse
|
|
Packit Service |
a8c26c |
* set!=0 is set to message set number
|
|
Packit Service |
a8c26c |
* msg!=0 is set to message number
|
|
Packit Service |
a8c26c |
* the message set number is returned
|
|
Packit Service |
a8c26c |
*
|
|
Packit Service |
a8c26c |
* the base 36 hash gives reasonable values for these:
|
|
Packit Service |
a8c26c |
*
|
|
Packit Service |
a8c26c |
* "ast" : ((((36#a^36#s^36#t)-9)&63)+1) = 3
|
|
Packit Service |
a8c26c |
* "gnu" : ((((36#g^36#n^36#u)-9)&63)+1) = 17
|
|
Packit Service |
a8c26c |
* "sgi" : ((((36#s^36#g^36#i)-9)&63)+1) = 22
|
|
Packit Service |
a8c26c |
* "sun" : ((((36#s^36#u^36#n)-9)&63)+1) = 13
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
int
|
|
Packit Service |
a8c26c |
mcindex(register const char* s, char** e, int* set, int* msg)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
register int c;
|
|
Packit Service |
a8c26c |
register int m;
|
|
Packit Service |
a8c26c |
register int n;
|
|
Packit Service |
a8c26c |
register int r;
|
|
Packit Service |
a8c26c |
register unsigned char* cv;
|
|
Packit Service |
a8c26c |
char* t;
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
m = 0;
|
|
Packit Service |
a8c26c |
n = strtol(s, &t, 0);
|
|
Packit Service |
a8c26c |
if (t == (char*)s)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
SFCVINIT();
|
|
Packit Service |
a8c26c |
cv = _Sfcv36;
|
|
Packit Service |
a8c26c |
for (n = m = 0; (c = cv[*s]) < 36; s++)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
m++;
|
|
Packit Service |
a8c26c |
n ^= c;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
m = (m <= 3) ? 63 : ((1 << (m + 3)) - 1);
|
|
Packit Service |
a8c26c |
n = ((n - 9) & m) + 1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
s = (const char*)t;
|
|
Packit Service |
a8c26c |
r = n;
|
|
Packit Service |
a8c26c |
if (*s)
|
|
Packit Service |
a8c26c |
m = strtol(s + 1, e, 0);
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (e)
|
|
Packit Service |
a8c26c |
*e = (char*)s;
|
|
Packit Service |
a8c26c |
if (m)
|
|
Packit Service |
a8c26c |
m = 0;
|
|
Packit Service |
a8c26c |
else
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
m = n;
|
|
Packit Service |
a8c26c |
n = 1;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
if (set)
|
|
Packit Service |
a8c26c |
*set = n;
|
|
Packit Service |
a8c26c |
if (msg)
|
|
Packit Service |
a8c26c |
*msg = m;
|
|
Packit Service |
a8c26c |
return r;
|
|
Packit Service |
a8c26c |
}
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
/*
|
|
Packit Service |
a8c26c |
* close the message catalog mc
|
|
Packit Service |
a8c26c |
*/
|
|
Packit Service |
a8c26c |
|
|
Packit Service |
a8c26c |
int
|
|
Packit Service |
a8c26c |
mcclose(register Mc_t* mc)
|
|
Packit Service |
a8c26c |
{
|
|
Packit Service |
a8c26c |
if (!mc)
|
|
Packit Service |
a8c26c |
return -1;
|
|
Packit Service |
a8c26c |
if (mc->tmp)
|
|
Packit Service |
a8c26c |
sfclose(mc->tmp);
|
|
Packit Service |
a8c26c |
if (mc->cvt != (iconv_t)(-1))
|
|
Packit Service |
a8c26c |
iconv_close(mc->cvt);
|
|
Packit Service |
a8c26c |
vmclose(mc->vm);
|
|
Packit Service |
a8c26c |
return 0;
|
|
Packit Service |
a8c26c |
}
|