/***********************************************************************
* *
* This software is part of the ast package *
* Copyright (c) 1985-2011 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
* *
* A copy of the License is available at *
* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
* *
* Information and Software Systems Research *
* AT&T Research *
* Florham Park NJ *
* *
* Glenn Fowler <gsf@research.att.com> *
* David Korn <dgk@research.att.com> *
* Phong Vo <kpv@research.att.com> *
* *
***********************************************************************/
#pragma prototyped
/*
* Glenn Fowler
* AT&T Research
*
* machine independent binary message catalog implementation
*/
#include "sfhdr.h"
#include "lclib.h"
#include <iconv.h>
#define _MC_PRIVATE_ \
#include <vmalloc.h>
#include <error.h>
#include <mc.h>
#include <nl_types.h>
/*
* find the binary message catalog path for <locale,catalog>
* result placed in path of size PATH_MAX
* pointer to path returned
* catalog==0 tests for category directory or file
* nls!=0 enables NLSPATH+LANG hack (not implemented yet)
*/
char*
{
register int c;
register char* s;
register char* e;
register char* p;
register const char* v;
int i;
int first;
int next;
int last;
int oerrno;
return 0;
return 0;
{
if (i)
return 0;
return path;
}
i = 0;
if ((p = getenv("NLSPATH")) && *p)
paths[i++] = p;
paths[i] = 0;
next = 1;
{
first = 1;
last = 0;
while (*p)
{
s = file;
for (;;)
{
switch (c = *p++)
{
case 0:
p--;
break;
case ':':
break;
case '%':
if (s < e)
{
switch (c = *p++)
{
case 0:
p--;
continue;
case 'N':
v = catalog;
break;
case 'L':
if (first)
{
first = 0;
if (next)
{
next = 0;
}
else
{
next = 1;
}
}
break;
case 'l':
break;
case 't':
break;
case 'c':
break;
case 'C':
if (!catalog)
last = 1;
break;
default:
*s++ = c;
continue;
}
if (v)
while (*v && s < e)
*s++ = *v++;
}
continue;
case '/':
if (last)
break;
if (category != AST_LC_MESSAGES && strneq(p, lc_messages, sizeof(lc_messages) - 1) && p[sizeof(lc_messages)-1] == '/')
{
p += sizeof(lc_messages) - 1;
goto case_C;
}
/*FALLTHROUGH*/
default:
if (s < e)
*s++ = c;
continue;
}
break;
}
if (s > file)
*s = 0;
else if (!catalog)
continue;
else
if (s = pathpath(file, "", (!catalog && category == AST_LC_MESSAGES) ? PATH_READ : (PATH_REGULAR|PATH_READ|PATH_ABSOLUTE), path, size))
{
return s;
}
}
}
return 0;
}
/*
* allocate and read the binary message catalog ip
* if ip==0 then space is allocated for mcput()
* 0 returned on any error
*/
Mc_t*
{
register char** mp;
register char* sp;
char* rp;
int i;
int j;
int oerrno;
size_t n;
if (ip)
{
/*
* check the magic
*/
{
return 0;
}
return 0;
}
/*
* allocate the region
*/
{
return 0;
}
if (ip)
{
/*
* read the translation record
*/
goto bad;
/*
* read the optional header records
*/
do
{
goto bad;
} while (*sp);
/*
* get the component dimensions
*/
goto bad;
}
goto bad;
/*
* allocate the remaining space
*/
goto bad;
if (!ip)
return mc;
goto bad;
goto bad;
/*
* get the set dimensions and initialize the msg pointers
*/
{
goto bad;
mp += n + 1;
}
/*
* read the msg sizes and set up the msg pointers
*/
{
sp += n;
}
/*
* read the string table
*/
goto bad;
goto bad;
return mc;
bad:
return 0;
}
/*
* return the <set,num> message in mc
* msg returned on error
* utf message text converted to ucs
*/
char*
{
char* s;
size_t n;
int p;
if (!mc || set < 0 || set > mc->num || num < 1 || num > mc->set[set].num || !(s = mc->set[set].msg[num]))
return (char*)msg;
return s;
{
p = 0;
}
n = strlen(s) + 1;
}
/*
* set message <set,num> to msg
* msg==0 deletes the message
* the message and set counts are adjusted
* 0 returned on success, -1 otherwise
*/
int
{
register int i;
register char* s;
register char** mp;
/*
* validate the arguments
*/
return -1;
/*
* deletions don't kick in allocations (duh)
*/
if (!msg)
{
{
/*
* decrease the string table size
*/
{
/*
* decrease the max msg num
*/
{
/*
* decrease the max set num
*/
}
}
}
return 0;
}
/*
* keep track of the highest set and allocate if necessary
*/
{
{
i = MC_SET_MAX;
return -1;
}
}
/*
* keep track of the highest msg and allocate if necessary
*/
{
{
{
if (i <= num)
i = 2 * num;
if (i > MC_NUM_MAX)
i = MC_NUM_MAX;
return -1;
}
else
{
if (i > MC_NUM_MAX)
i = MC_NUM_MAX;
return -1;
}
}
}
/*
* decrease the string table size
*/
{
/*
* no-op if no change
*/
return 0;
}
/*
* allocate, add and adjust the string table size
*/
return -1;
return 0;
}
/*
* dump message catalog mc to op
* 0 returned on success, -1 otherwise
*/
int
{
register int i;
register int j;
register int n;
register char* s;
/*
* write the magic
*/
return -1;
/*
* write the translation record
*/
/* optional header records here */
/*
* end of optional header records
*/
/*
* write the global dimensions
*/
/*
* write the set dimensions
*/
{
}
/*
* write the message sizes
*/
{
{
}
}
/*
* write the string table
*/
{
}
/*
* sync and return
*/
}
/*
* parse <set,msg> number from s
* e!=0 is set to the next char after the parse
* set!=0 is set to message set number
* msg!=0 is set to message number
* the message set number is returned
*
* the base 36 hash gives reasonable values for these:
*
* "ast" : ((((36#a^36#s^36#t)-9)&63)+1) = 3
* "gnu" : ((((36#g^36#n^36#u)-9)&63)+1) = 17
* "sgi" : ((((36#s^36#g^36#i)-9)&63)+1) = 22
* "sun" : ((((36#s^36#u^36#n)-9)&63)+1) = 13
*/
int
{
register int c;
register int m;
register int n;
register int r;
register unsigned char* cv;
char* t;
m = 0;
n = strtol(s, &t, 0);
if (t == (char*)s)
{
SFCVINIT();
for (n = m = 0; (c = cv[*s]) < 36; s++)
{
m++;
n ^= c;
}
m = (m <= 3) ? 63 : ((1 << (m + 3)) - 1);
n = ((n - 9) & m) + 1;
}
else
s = (const char*)t;
r = n;
if (*s)
m = strtol(s + 1, e, 0);
else
{
if (e)
*e = (char*)s;
if (m)
m = 0;
else
{
m = n;
n = 1;
}
}
if (set)
*set = n;
if (msg)
*msg = m;
return r;
}
/*
* close the message catalog mc
*/
int
{
if (!mc)
return -1;
return 0;
}