home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
evbl0627.zip
/
everblue_20010627.zip
/
x11
/
Xlc_DB.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-11-02
|
31KB
|
1,362 lines
/* $TOG: lcDB.c /main/12 1997/06/02 17:27:50 kaleb $ */
/*
*
* Copyright IBM Corporation 1993
*
* All Rights Reserved
*
* License to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation, and that the name of IBM not be
* used in advertising or publicity pertaining to distribution of the
* software without specific, written prior permission.
*
* IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
* ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND
* NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL
* IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
* ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
* WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
*/
/*
* (c) Copyright 1995 FUJITSU LIMITED
* This is source code modified by FUJITSU LIMITED under the Joint
* Development Agreement for the CDE/Motif PST.
*/
/* $XFree86: xc/lib/X11/lcDB.c,v 3.3.2.4 1998/10/04 13:36:24 hohndel Exp $ */
#ifndef NOT_X_ENV
#include <X11/Xlib.h>
#include <X11/Xresource.h>
#include "Xlib_private.h"
#include "XlcPubI.h"
#else /* NOT_X_ENV */
#define Xmalloc malloc
#define Xrealloc realloc
#define Xfree free
#endif /* NOT_X_ENV */
/* specifying NOT_X_ENV allows users to just use
the database parsing routine. */
/* For UDC/VW */
#ifndef BUFSIZE
#define BUFSIZE 2048
#endif
#ifdef COMMENT
#ifdef BUFSIZE
#undef BUFSIZE
#endif
#define BUFSIZE 6144 /* 2048*3 */
#endif
#include <stdio.h>
typedef struct _DatabaseRec {
char *category;
char *name;
char **value;
int value_num;
struct _DatabaseRec *next;
} DatabaseRec, *Database;
typedef enum {
S_NULL, /* outside category */
S_CATEGORY, /* inside category */
S_NAME, /* has name, expecting values */
S_VALUE
} ParseState;
typedef enum {
T_NEWLINE,
T_COMMENT,
T_SEMICOLON,
T_DOUBLE_QUOTE,
T_LEFT_BRACE,
T_RIGHT_BRACE,
T_SPACE,
T_TAB,
T_BACKSLASH,
T_NUMERIC_HEX,
T_NUMERIC_DEC,
T_NUMERIC_OCT,
T_DEFAULT
} Token;
typedef struct {
Token token; /* token id */
char *name; /* token sequence */
int len; /* length of token sequence */
int (*parse_proc)(); /* parsing procedure */
} TokenTable;
static int f_newline();
static int f_comment();
static int f_semicolon();
static int f_double_quote();
static int f_left_brace();
static int f_right_brace();
static int f_white();
static int f_backslash();
static int f_numeric();
static int f_default();
static TokenTable token_tbl[] = {
{ T_NEWLINE, "\n", 1, f_newline },
{ T_COMMENT, "#", 1, f_comment },
{ T_SEMICOLON, ";", 1, f_semicolon },
{ T_DOUBLE_QUOTE, "\"", 1, f_double_quote },
{ T_LEFT_BRACE, "{", 1, f_left_brace },
{ T_RIGHT_BRACE, "}", 1, f_right_brace },
{ T_SPACE, " ", 1, f_white },
{ T_TAB, "\t", 1, f_white },
{ T_BACKSLASH, "\\", 1, f_backslash },
{ T_NUMERIC_HEX, "\\x", 2, f_numeric },
{ T_NUMERIC_DEC, "\\d", 2, f_numeric },
{ T_NUMERIC_OCT, "\\o", 2, f_numeric },
{ T_DEFAULT, " ", 1, f_default }, /* any character */
0
};
#define SYM_CR '\r'
#define SYM_NEWLINE '\n'
#define SYM_COMMENT '#'
#define SYM_SEMICOLON ';'
#define SYM_DOUBLE_QUOTE '"'
#define SYM_LEFT_BRACE '{'
#define SYM_RIGHT_BRACE '}'
#define SYM_SPACE ' '
#define SYM_TAB '\t'
#define SYM_BACKSLASH '\\'
/************************************************************************/
#define MAX_NAME_NEST 64
typedef struct {
ParseState pre_state;
char *category;
char *name[MAX_NAME_NEST];
int nest_depth;
char **value;
int value_len;
int value_num;
int bufsize; /* bufMaxSize >= bufsize >= 0 */
int bufMaxSize; /* default : BUFSIZE */
char *buf;
} DBParseInfo;
static DBParseInfo parse_info;
static void init_parse_info()
{
DBUG_ENTER("init_parse_info")
static int first = 1;
char *ptr;
int size;
if(first == 1){
bzero(&parse_info, sizeof(DBParseInfo));
parse_info.buf = (char *)Xmalloc(BUFSIZE);
parse_info.bufMaxSize = BUFSIZE;
first = 0;
DBUG_VOID_RETURN;
}
ptr = parse_info.buf;
size = parse_info.bufMaxSize;
bzero(&parse_info, sizeof(DBParseInfo));
parse_info.buf = ptr;
parse_info.bufMaxSize = size;
DBUG_VOID_RETURN;
}
static void
clear_parse_info()
{
DBUG_ENTER("clear_parse_info")
int i;
char *ptr;
int size;
parse_info.pre_state = S_NULL;
if(parse_info.category != NULL){
Xfree(parse_info.category);
}
for(i = 0; i <= parse_info.nest_depth; ++i){
if(parse_info.name[i]){
Xfree(parse_info.name[i]);
}
}
if(parse_info.value){
if(*parse_info.value){
Xfree(*parse_info.value);
}
Xfree((char *)parse_info.value);
}
ptr = parse_info.buf;
size = parse_info.bufMaxSize;
bzero(&parse_info, sizeof(DBParseInfo));
parse_info.buf = ptr;
parse_info.bufMaxSize = size;
DBUG_VOID_RETURN;
}
static Bool
realloc_parse_info(len)
int len;
{
DBUG_ENTER("realloc_parse_info")
char *p;
parse_info.bufMaxSize = BUFSIZE *
((parse_info.bufsize + len)/BUFSIZE + 1);
p = (char *)Xrealloc(parse_info.buf, parse_info.bufMaxSize);
if(p == NULL){
DBUG_RETURN(False);
}
parse_info.buf = p;
DBUG_RETURN(True);
}
/************************************************************************/
typedef struct _Line {
char *str;
int cursize;
int maxsize;
int seq;
} Line;
static void
free_line(line)
Line *line;
{
DBUG_ENTER("free_line")
if(line->str != NULL){
Xfree(line->str);
}
bzero(line, sizeof(Line));
DBUG_VOID_RETURN;
}
static int
realloc_line(line, size)
Line *line;
int size;
{
DBUG_ENTER("realloc_line")
char *str = line->str;
if(str != NULL){
str = (char *)Xrealloc(str, size);
}else{
str = (char *)Xmalloc(size);
}
if(str == NULL){
/* malloc error */
if (line->str != NULL) {
Xfree(line->str);
}
bzero(line, sizeof(Line));
DBUG_RETURN(0);
}
line->str = str;
line->maxsize = size;
DBUG_RETURN(1);
}
#define iswhite(ch) ((ch) == SYM_SPACE || (ch) == SYM_TAB)
static void
zap_comment(str, quoted)
char *str;
int *quoted;
{
DBUG_ENTER("zap_comment")
char *p = str;
#ifdef never
*quoted = 0;
if(*p == SYM_COMMENT){
int len = strlen(str);
if(p[len - 1] == SYM_NEWLINE || p[len - 1] == SYM_CR){
*p++ = SYM_NEWLINE;
}
*p = '\0';
}
#else
while(*p){
if(*p == SYM_DOUBLE_QUOTE){
if(p == str || p[-1] != SYM_BACKSLASH){
/* unescaped double quote changes quoted state. */
*quoted = *quoted ? 0 : 1;
}
}
if(*p == SYM_COMMENT && !*quoted){
int pos = p - str;
if(pos == 0 ||
iswhite(p[-1]) && (pos == 1 || p[-2] != SYM_BACKSLASH)){
int len = strlen(p);
if(len > 0 && (p[len - 1] == SYM_NEWLINE || p[len-1] == SYM_CR)) {
/* newline is the identifier for finding end of value.
therefore, it should not be removed. */
*p++ = SYM_NEWLINE;
}
*p = '\0';
break;
}
}
++p;
}
#endif
DBUG_VOID_RETURN;
}
static int
read_line(fd, line)
FILE *fd;
Line *line;
{
DBUG_ENTER("read_line")
char buf[BUFSIZE], *p;
int len;
int quoted = 0; /* quoted by double quote? */
char *str;
int cur;
str = line->str;
cur = line->cursize = 0;
while((p = fgets(buf, BUFSIZE, fd)) != NULL){
++line->seq;
zap_comment(p, "ed); /* remove comment line */
len = strlen(p);
if(len == 0){
if(cur > 0){
break;
}
continue;
}
if(cur + len + 1 > line->maxsize){
/* need to reallocate buffer. */
if(! realloc_line(line, line->maxsize + BUFSIZE)){
goto err; /* realloc error. */
}
str = line->str;
}
strncpy(str + cur, p, len);
cur += len;
str[cur] = '\0';
#ifdef __EMX__ /* Take out carriage returns under OS/2 */
if(cur>1) {
if(str[cur-2] == '\r' && str[cur-1] == '\n'){
str[cur-2] = '\n';
str[cur-1] = '\0';
cur--;
}
}
#endif
if(!quoted){
if(cur > 1 && str[cur - 2] == SYM_BACKSLASH &&
(str[cur - 1] == SYM_NEWLINE || str[cur-1] == SYM_CR)){
/* the line is ended backslash followed by newline.
need to concatinate the next line. */
cur -= 2;
str[cur] = '\0';
}else{
break;
}
}
}
if(quoted){
/* error. still in quoted state. */
goto err;
}
line->cursize = cur;
DBUG_RETURN(cur);
err:;
DBUG_RETURN(-1);
}
/************************************************************************/
static Token
get_token(str)
char *str;
{
DBUG_ENTER("get_token")
switch(*str){
case SYM_NEWLINE:
case SYM_CR: DBUG_RETURN(T_NEWLINE);
case SYM_COMMENT: DBUG_RETURN(T_COMMENT);
case SYM_SEMICOLON: DBUG_RETURN(T_SEMICOLON);
case SYM_DOUBLE_QUOTE: DBUG_RETURN(T_DOUBLE_QUOTE);
case SYM_LEFT_BRACE: DBUG_RETURN(T_LEFT_BRACE);
case SYM_RIGHT_BRACE: DBUG_RETURN(T_RIGHT_BRACE);
case SYM_SPACE: DBUG_RETURN(T_SPACE);
case SYM_TAB: DBUG_RETURN(T_TAB);
case SYM_BACKSLASH:
switch(str[1]){
case 'x': DBUG_RETURN(T_NUMERIC_HEX);
case 'd': DBUG_RETURN(T_NUMERIC_DEC);
case 'o': DBUG_RETURN(T_NUMERIC_OCT);
}
DBUG_RETURN(T_BACKSLASH);
default:
DBUG_RETURN(T_DEFAULT);
}
}
#define CHECKWORD(n) \
if (w - word + (n) >= size - 1) {*word = 0; return 0;} else
static int
get_word(str, word, size)
char *str;
char *word;
int size;
{
DBUG_ENTER("get_word")
char *p = str, *w = word;
Token token;
int token_len;
while(*p != '\0'){
token = get_token(p);
token_len = token_tbl[token].len;
if(token == T_BACKSLASH){
p += token_len;
if(*p == '\0'){
break;
}
token = get_token(p);
token_len = token_tbl[token].len;
}else if(token != T_COMMENT &&
token != T_DEFAULT){
break;
}
CHECKWORD(token_len);
strncpy(w, p, token_len);
p += token_len; w += token_len;
}
*w = '\0';
DBUG_RETURN(p - str); /* return number of scanned chars */
}
static int
get_quoted_word(str, word, size)
char *str;
char *word;
int size;
{
DBUG_ENTER("get_quoted_word")
char *p = str, *w = word;
Token token;
int token_len;
if(*p == SYM_DOUBLE_QUOTE){
++p;
}
while(*p != '\0'){
token = get_token(p);
token_len = token_tbl[token].len;
if(token == T_DOUBLE_QUOTE){
p += token_len;
goto found;
}
if(token == T_BACKSLASH){
p += token_len;
if(*p == '\0'){
break;
}
token = get_token(p);
token_len = token_tbl[token].len;
}
CHECKWORD(token_len);
strncpy(w, p, token_len);
p += token_len; w += token_len;
}
/* error. cannot detect next double quote */
DBUG_RETURN(0);
found:;
*w = '\0';
DBUG_RETURN(p - str);
}
/************************************************************************/
static int
append_value_list()
{
DBUG_ENTER("append_value_list")
char **value_list = parse_info.value;
char *value;
int value_num = parse_info.value_num;
int value_len = parse_info.value_len;
char *str = parse_info.buf;
int len = parse_info.bufsize;
char *p;
if(len < 1){
DBUG_RETURN(1); /* return with no error */
}
if(value_list == (char **)NULL){
value_list = (char **)Xmalloc(sizeof(char *) * 2);
*value_list = NULL;
}else{
char **prev_list = value_list;
value_list = (char **)
Xrealloc(value_list, sizeof(char *) * (value_num + 2));
if (value_list == NULL){
Xfree(prev_list);
}
}
if(value_list == (char **)NULL){
goto err;
}
value = *value_list;
if(value == NULL){
value = (char *)Xmalloc(value_len + len + 1);
}else{
char *prev_value = value;
value = (char *)Xrealloc(value, value_len + len + 1);
if (value == NULL){
Xfree(prev_value);
}
}
if(value == NULL){
goto err;
}
if(value != *value_list){
int delta, i;
delta = value - *value_list;
*value_list = value;
for(i = 1; i < value_num; ++i){
value_list[i] += delta;
}
}
value_list[value_num] = p = &value[value_len];
value_list[value_num + 1] = NULL;
strncpy(p, str, len);
p[len] = 0;
parse_info.value = value_list;
parse_info.value_num = value_num + 1;
parse_info.value_len = value_len + len + 1;
parse_info.bufsize = 0;
DBUG_RETURN(1);
err:;
if(value_list){
Xfree((char **)value_list);
}
if(value){
Xfree(value);
}
parse_info.value = (char **)NULL;
parse_info.value_num = 0;
parse_info.value_len = 0;
parse_info.bufsize = 0;
DBUG_RETURN(0);
}
static int
construct_name(name, size)
char *name;
int size;
{
DBUG_ENTER("construct_name")
register int i, len = 0;
char *p = name;
for(i = 0; i <= parse_info.nest_depth; ++i){
len += strlen(parse_info.name[i]) + 1;
}
if (len >= size)
DBUG_RETURN(0);
strcpy(p, parse_info.name[0]);
p += strlen(parse_info.name[0]);
for(i = 1; i <= parse_info.nest_depth; ++i){
*p++ = '.';
strcpy(p, parse_info.name[i]);
p += strlen(parse_info.name[i]);
}
DBUG_RETURN(*name != '\0');
}
static int
store_to_database(db)
Database *db;
{
DBUG_ENTER("store_to_database")
Database new = (Database)NULL;
char name[BUFSIZE];
if(parse_info.pre_state == S_VALUE){
if(! append_value_list()){
goto err;
}
}
if(parse_info.name[parse_info.nest_depth] == NULL){
goto err;
}
new = (Database)Xmalloc(sizeof(DatabaseRec));
if(new == (Database)NULL){
goto err;
}
bzero(new, sizeof(DatabaseRec));
new->category = (char *)Xmalloc(strlen(parse_info.category) + 1);
if(new->category == NULL){
goto err;
}
strcpy(new->category, parse_info.category);
if(! construct_name(name, sizeof(name))){
goto err;
}
new->name = (char *)Xmalloc(strlen(name) + 1);
if(new->name == NULL){
goto err;
}
strcpy(new->name, name);
new->next = *db;
new->value = parse_info.value;
new->value_num = parse_info.value_num;
*db = new;
Xfree(parse_info.name[parse_info.nest_depth]);
parse_info.name[parse_info.nest_depth] = NULL;
parse_info.value = (char **)NULL;
parse_info.value_num = 0;
parse_info.value_len = 0;
DBUG_RETURN(1);
err:;
if(new){
if(new->category){
Xfree(new->category);
}
if(new->name){
Xfree(new->name);
}
}
if(parse_info.value){
if(*parse_info.value){
Xfree(*parse_info.value);
}
Xfree((char **)parse_info.value);
parse_info.value = (char **)NULL;
parse_info.value_num = 0;
parse_info.value_len = 0;
}
DBUG_RETURN(0);
}
#define END_MARK "END"
#define END_MARK_LEN 3 /*strlen(END_MARK)*/
static int
check_category_end(str)
char *str;
{
DBUG_ENTER("check_category_end")
char *p;
int len;
p = str;
if(strncmp(p, END_MARK, END_MARK_LEN)){
DBUG_RETURN(0);
}
p += END_MARK_LEN;
while(iswhite(*p)){
++p;
}
len = strlen(parse_info.category);
if(strncmp(p, parse_info.category, len)){
DBUG_RETURN(0);
}
p += len;
DBUG_RETURN(p - str);
}
/************************************************************************/
static int
f_newline(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_newline")
switch(parse_info.pre_state){
case S_NULL:
case S_CATEGORY:
break;
case S_NAME:
goto err; /* no value */
case S_VALUE:
if(!store_to_database(db)){
goto err;
}
parse_info.pre_state = S_CATEGORY;
break;
default:
goto err;
}
DBUG_RETURN(token_tbl[token].len);
err:;
DBUG_RETURN(0);
}
static int
f_comment(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_comment")
/* NOTE: comment is already handled in read_line(),
so this function is not necessary. */
char *p = str;
while(*p != SYM_NEWLINE && *p != SYM_CR && *p != '\0'){
++p; /* zap to the end of line */
}
DBUG_RETURN(p - str);
}
static int
f_white(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_white")
char *p = str;
while(iswhite(*p)){
++p;
}
DBUG_RETURN(p - str);
}
static int
f_semicolon(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_semicolon")
switch(parse_info.pre_state){
case S_NULL:
case S_CATEGORY:
case S_NAME:
goto err;
case S_VALUE:
if(! append_value_list()){
goto err;
}
parse_info.pre_state = S_VALUE;
break;
default:
goto err;
}
DBUG_RETURN(token_tbl[token].len);
err:;
DBUG_RETURN(0);
}
static int
f_left_brace(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_left_brace")
switch(parse_info.pre_state){
case S_NULL:
case S_CATEGORY:
goto err;
case S_NAME:
if(parse_info.name[parse_info.nest_depth] == NULL ||
parse_info.nest_depth + 1 > MAX_NAME_NEST){
goto err;
}
++parse_info.nest_depth;
parse_info.pre_state = S_CATEGORY;
break;
case S_VALUE:
default:
goto err;
}
DBUG_RETURN(token_tbl[token].len);
err:
DBUG_RETURN(0);
}
static int
f_right_brace(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_right_brace")
if(parse_info.nest_depth < 1){
goto err;
}
switch(parse_info.pre_state){
case S_NULL:
case S_NAME:
goto err;
case S_VALUE:
if(! store_to_database(db)){
goto err;
}
/* fall into next case */
case S_CATEGORY:
if(parse_info.name[parse_info.nest_depth] != NULL){
Xfree(parse_info.name[parse_info.nest_depth]);
parse_info.name[parse_info.nest_depth] = NULL;
}
--parse_info.nest_depth;
parse_info.pre_state = S_CATEGORY;
break;
default:
goto err;
}
DBUG_RETURN(token_tbl[token].len);
err:;
DBUG_RETURN(0);
}
static int
f_double_quote(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_double_quote")
char word[BUFSIZE];
int len = 0;
switch(parse_info.pre_state){
case S_NULL:
case S_CATEGORY:
goto err;
case S_NAME:
case S_VALUE:
len = get_quoted_word(str, word, sizeof(word));
if(len < 1){
goto err;
}
if( (parse_info.bufsize + (int)strlen(word) +1)
>= parse_info.bufMaxSize){
if(realloc_parse_info(strlen(word) +1) == False){
goto err;
}
}
strcpy(&parse_info.buf[parse_info.bufsize], word);
parse_info.bufsize += strlen(word);
parse_info.pre_state = S_VALUE;
break;
default:
goto err;
}
DBUG_RETURN(len); /* including length of token */
err:;
DBUG_RETURN(0);
}
static int
f_backslash(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_backslash")
int result = f_default(str, token, db);
DBUG_RETURN(result);
}
static int
f_numeric(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_numeric")
char word[BUFSIZE], *p;
int len;
int token_len;
switch(parse_info.pre_state){
case S_NULL:
case S_CATEGORY:
goto err;
case S_NAME:
case S_VALUE:
token_len = token_tbl[token].len;
p = str + token_len;
len = get_word(p, word, sizeof(word));
if(len < 1){
goto err;
}
if( (parse_info.bufsize + token_len + (int)strlen(word) +1)
>= parse_info.bufMaxSize){
if(realloc_parse_info(token_len + strlen(word) +1) == False){
goto err;
}
}
strncpy(&parse_info.buf[parse_info.bufsize], str, token_len);
strcpy(&parse_info.buf[parse_info.bufsize + token_len], word);
parse_info.bufsize += token_len + strlen(word);
parse_info.pre_state = S_VALUE;
break;
default:
goto err;
}
DBUG_RETURN(len + token_len);
err:;
DBUG_RETURN(0);
}
static int
f_default(str, token, db)
char *str;
Token token;
Database *db;
{
DBUG_ENTER("f_default")
char word[BUFSIZE], *p;
int len;
len = get_word(str, word, sizeof(word));
if(len < 1){
goto err;
}
switch(parse_info.pre_state){
case S_NULL:
if(parse_info.category != NULL){
goto err;
}
p = (char *)Xmalloc(strlen(word) + 1);
if(p == NULL){
goto err;
}
strcpy(p, word);
parse_info.category = p;
parse_info.pre_state = S_CATEGORY;
break;
case S_CATEGORY:
if(parse_info.nest_depth == 0){
if(check_category_end(str)){
/* end of category is detected.
clear context and zap to end of this line */
clear_parse_info();
len = strlen(str);
break;
}
}
p = (char *)Xmalloc(strlen(word) + 1);
if(p == NULL){
goto err;
}
strcpy(p, word);
if(parse_info.name[parse_info.nest_depth] != NULL){
Xfree(parse_info.name[parse_info.nest_depth]);
}
parse_info.name[parse_info.nest_depth] = p;
parse_info.pre_state = S_NAME;
break;
case S_NAME:
case S_VALUE:
if( (parse_info.bufsize + (int)strlen(word) +1 )
>= parse_info.bufMaxSize){
if(realloc_parse_info(strlen(word) +1) == False){
goto err;
}
}
strcpy(&parse_info.buf[parse_info.bufsize], word);
parse_info.bufsize += strlen(word);
parse_info.pre_state = S_VALUE;
break;
default:
goto err;
}
DBUG_RETURN(len);
err:;
DBUG_RETURN(0);
}
/************************************************************************/
#ifdef DEBUG
static void
PrintDatabase(db)
Database db;
{
DBUG_ENTER("PrintDatabase")
#ifdef VERBOSE
Database p = db;
int i = 0, j;
printf("***\n*** BEGIN Database\n***\n");
while(p){
printf("%3d: ", i++);
printf("%s, %s, ", p->category, p->name);
printf("\t[%d: ", p->value_num);
for(j = 0; j < p->value_num; ++j){
printf("%s, ", p->value[j]);
}
printf("]\n");
p = p->next;
}
printf("***\n*** END Database\n***\n");
#endif
DBUG_VOID_RETURN;
}
#endif
static void
DestroyDatabase(db)
Database db;
{
DBUG_ENTER("DestroyDatabase")
Database p = db;
while(p){
if(p->category != NULL){
Xfree(p->category);
}
if(p->name != NULL){
Xfree(p->name);
}
if(p->value != (char **)NULL){
if(*p->value != NULL){
Xfree(*p->value);
}
Xfree((char *)p->value);
}
db = p->next;
Xfree((char *)p);
p = db;
}
DBUG_VOID_RETURN;
}
static int
CountDatabase(db)
Database db;
{
DBUG_ENTER("CountDatabase")
Database p = db;
int cnt = 0;
while(p){
++cnt;
p = p->next;
}
DBUG_RETURN(cnt);
}
static Database
CreateDatabase(dbfile)
char *dbfile;
{
DBUG_ENTER("CreateDatabase")
Database db = (Database)NULL;
FILE *fd;
Line line;
char *p;
Token token;
int len;
int error = 0;
fd = fopen(dbfile, "r");
if(fd == (FILE *)NULL){
DBUG_RETURN(NULL);
}
bzero(&line, sizeof(Line));
init_parse_info();
do {
int rc = read_line(fd, &line);
if(rc < 0){
error = 1;
break;
}else if(rc == 0){
break;
}
p = line.str;
while(*p){
token = get_token(p);
len = (*token_tbl[token].parse_proc)(p, token, &db);
if(len < 1){
error = 1;
break;
}
p += len;
}
} while (!error);
if(parse_info.pre_state != S_NULL){
clear_parse_info();
error = 1;
}
if(error){
#if defined(DEBUG) && defined(VERBOSE)
fprintf(stderr, "database format error at line %d.\n", line.seq);
#endif
DestroyDatabase(db);
db = (Database)NULL;
}
fclose(fd);
free_line(&line);
#ifdef DEBUG
PrintDatabase(db);
#endif
DBUG_RETURN(db);
}
/************************************************************************/
#ifndef NOT_X_ENV
/* locale framework functions */
typedef struct _XlcDatabaseRec {
XrmQuark category_q;
XrmQuark name_q;
Database db;
struct _XlcDatabaseRec *next;
} XlcDatabaseRec, *XlcDatabase;
typedef struct _XlcDatabaseListRec {
XrmQuark name_q;
XlcDatabase lc_db;
Database database;
int ref_count;
struct _XlcDatabaseListRec *next;
} XlcDatabaseListRec, *XlcDatabaseList;
/* database cache list (per file) */
static XlcDatabaseList _db_list = (XlcDatabaseList)NULL;
/************************************************************************/
/* _XlcGetResource(lcd, category, class, value, count) */
/*----------------------------------------------------------------------*/
/* This function retrieves XLocale database information. */
/************************************************************************/
void
_XlcGetResource(lcd, category, class, value, count)
XLCd lcd;
char *category;
char *class;
char ***value;
int *count;
{
DBUG_ENTER("_XlcGetResource")
XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd);
(*methods->get_resource)(lcd, category, class, value, count);
DBUG_VOID_RETURN;
}
/************************************************************************/
/* _XlcGetLocaleDataBase(lcd, category, class, value, count) */
/*----------------------------------------------------------------------*/
/* This function retrieves XLocale database information. */
/************************************************************************/
void
_XlcGetLocaleDataBase(lcd, category, name, value, count)
XLCd lcd;
char *category;
char *name;
char ***value;
int *count;
{
DBUG_ENTER("_XlcGetLocaleDataBase")
XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
XrmQuark category_q, name_q;
category_q = XrmStringToQuark(category);
name_q = XrmStringToQuark(name);
for(; lc_db->db; ++lc_db){
if(category_q == lc_db->category_q && name_q == lc_db->name_q){
*value = lc_db->db->value;
*count = lc_db->db->value_num;
DBUG_VOID_RETURN;
}
}
*value = (char **)NULL;
*count = 0;
DBUG_VOID_RETURN;
}
/************************************************************************/
/* _XlcDestroyLocaleDataBase(lcd) */
/*----------------------------------------------------------------------*/
/* This function destroy the XLocale Database that bound to the */
/* specified lcd. If the XLocale Database is refered from some */
/* other lcd, this function just decreases reference count of */
/* the database. If no locale refers the database, this function */
/* remove it from the cache list and free work area. */
/************************************************************************/
void
_XlcDestroyLocaleDataBase(lcd)
XLCd lcd;
{
DBUG_ENTER("_XlcDestroyLocaleDataBase")
XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
XlcDatabaseList p, prev;
for(p = _db_list, prev = (XlcDatabaseList)NULL; p;
prev = p, p = p->next){
if(p->lc_db == lc_db){
if((-- p->ref_count) < 1){
if(p->lc_db != (XlcDatabase)NULL){
Xfree((char *)p->lc_db);
}
DestroyDatabase(p->database);
if(prev == (XlcDatabaseList)NULL){
_db_list = p->next;
}else{
prev->next = p->next;
}
Xfree((char*)p);
}
break;
}
}
XLC_PUBLIC(lcd, xlocale_db) = (XPointer)NULL;
DBUG_VOID_RETURN;
}
/************************************************************************/
/* _XlcCreateLocaleDataBase(lcd) */
/*----------------------------------------------------------------------*/
/* This function create an XLocale database which correspond to */
/* the specified XLCd. */
/************************************************************************/
XPointer
_XlcCreateLocaleDataBase(lcd)
XLCd lcd;
{
DBUG_ENTER("_XlcCreateLocaleDataBase")
XlcDatabaseList list, new;
Database p, database = (Database)NULL;
XlcDatabase lc_db = (XlcDatabase)NULL;
XrmQuark name_q;
char *name;
int i, n;
name = _XlcFileName(lcd, "locale");
if(name == NULL){
#if defined(DEBUG) && defined(VERBOSE)
fprintf(stderr,"_XlcCreateLocaleDataBase: _XlcFileName() failed!\n");
#endif
DBUG_RETURN((XPointer)NULL);
}
#ifndef __EMX__
name_q = XrmStringToQuark(name);
#else
name_q = XrmStringToQuark((char*)__XOS2RedirRoot(name));
#endif
for(list = _db_list; list; list = list->next){
if(name_q == list->name_q){
list->ref_count++;
Xfree (name);
XLC_PUBLIC(lcd, xlocale_db) = (XPointer)list->lc_db;
DBUG_RETURN((XPointer)list->lc_db);
}
}
database = CreateDatabase(name);
if(database == (Database)NULL){
#if defined(DEBUG) && defined(VERBOSE)
fprintf(stderr,"_XlcCreateLocaleDataBase: CreateDatabase() failed!\n");
#endif
Xfree (name);
DBUG_RETURN((XPointer)NULL);
}
n = CountDatabase(database);
lc_db = (XlcDatabase)Xmalloc(sizeof(XlcDatabaseRec) * (n + 1));
if(lc_db == (XlcDatabase)NULL){
#if defined(DEBUG) && defined(VERBOSE)
fprintf(stderr,"_XlcCreateLocaleDataBase: malloc for lc_db failed!\n");
#endif
goto err;
}
bzero(lc_db, sizeof(XlcDatabaseRec) * (n + 1));
for(p = database, i = 0; p && i < n; p = p->next, ++i){
lc_db[i].category_q = XrmStringToQuark(p->category);
lc_db[i].name_q = XrmStringToQuark(p->name);
lc_db[i].db = p;
}
new = (XlcDatabaseList)Xmalloc(sizeof(XlcDatabaseListRec));
if(new == (XlcDatabaseList)NULL){
#if defined(DEBUG) && defined(VERBOSE)
fprintf(stderr,"_XlcCreateLocaleDataBase: malloc for new failed!\n");
#endif
goto err;
}
new->name_q = name_q;
new->lc_db = lc_db;
new->database = database;
new->ref_count = 1;
new->next = _db_list;
_db_list = new;
Xfree (name);
XLC_PUBLIC(lcd, xlocale_db) = (XPointer)lc_db;
DBUG_RETURN((XPointer)lc_db);
err:
DestroyDatabase(database);
if(lc_db != (XlcDatabase)NULL){
Xfree((char *)lc_db);
}
Xfree (name);
DBUG_RETURN((XPointer)NULL);
}
#endif /* NOT_X_ENV */