lcDB.c revision 1ab64890
11ab64890Smrg/* $Xorg: lcDB.c,v 1.6 2000/08/17 19:45:17 cpqbld Exp $ */
21ab64890Smrg/*
31ab64890Smrg *
41ab64890Smrg * Copyright IBM Corporation 1993
51ab64890Smrg *
61ab64890Smrg * All Rights Reserved
71ab64890Smrg *
81ab64890Smrg * License to use, copy, modify, and distribute this software and its
91ab64890Smrg * documentation for any purpose and without fee is hereby granted,
101ab64890Smrg * provided that the above copyright notice appear in all copies and that
111ab64890Smrg * both that copyright notice and this permission notice appear in
121ab64890Smrg * supporting documentation, and that the name of IBM not be
131ab64890Smrg * used in advertising or publicity pertaining to distribution of the
141ab64890Smrg * software without specific, written prior permission.
151ab64890Smrg *
161ab64890Smrg * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
171ab64890Smrg * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND
181ab64890Smrg * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL
191ab64890Smrg * IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
201ab64890Smrg * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
211ab64890Smrg * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
221ab64890Smrg * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
231ab64890Smrg * SOFTWARE.
241ab64890Smrg *
251ab64890Smrg*/
261ab64890Smrg/*
271ab64890Smrg *  (c) Copyright 1995 FUJITSU LIMITED
281ab64890Smrg *  This is source code modified by FUJITSU LIMITED under the Joint
291ab64890Smrg *  Development Agreement for the CDE/Motif PST.
301ab64890Smrg */
311ab64890Smrg/* $XFree86: xc/lib/X11/lcDB.c,v 3.15tsi Exp $ */
321ab64890Smrg
331ab64890Smrg
341ab64890Smrg
351ab64890Smrg#ifndef	NOT_X_ENV
361ab64890Smrg
371ab64890Smrg#ifdef HAVE_CONFIG_H
381ab64890Smrg#include <config.h>
391ab64890Smrg#endif
401ab64890Smrg#include <X11/Xlib.h>
411ab64890Smrg#include <X11/Xresource.h>
421ab64890Smrg#include "Xlibint.h"
431ab64890Smrg#include "XlcPubI.h"
441ab64890Smrg
451ab64890Smrg#else	/* NOT_X_ENV */
461ab64890Smrg
471ab64890Smrg#define	Xmalloc	malloc
481ab64890Smrg#define	Xrealloc	realloc
491ab64890Smrg#define	Xfree	free
501ab64890Smrg
511ab64890Smrg#endif	/* NOT_X_ENV */
521ab64890Smrg
531ab64890Smrg/* specifying NOT_X_ENV allows users to just use
541ab64890Smrg   the database parsing routine. */
551ab64890Smrg/* For UDC/VW */
561ab64890Smrg#ifndef	BUFSIZE
571ab64890Smrg#define	BUFSIZE	2048
581ab64890Smrg#endif
591ab64890Smrg
601ab64890Smrg#ifdef COMMENT
611ab64890Smrg#ifdef  BUFSIZE
621ab64890Smrg#undef BUFSIZE
631ab64890Smrg#endif
641ab64890Smrg#define BUFSIZE 6144 /* 2048*3 */
651ab64890Smrg#endif
661ab64890Smrg
671ab64890Smrg#include <stdio.h>
681ab64890Smrg
691ab64890Smrgtypedef struct _DatabaseRec {
701ab64890Smrg    char *category;
711ab64890Smrg    char *name;
721ab64890Smrg    char **value;
731ab64890Smrg    int value_num;
741ab64890Smrg    struct _DatabaseRec *next;
751ab64890Smrg} DatabaseRec, *Database;
761ab64890Smrg
771ab64890Smrgtypedef enum {
781ab64890Smrg    S_NULL,	/* outside category */
791ab64890Smrg    S_CATEGORY,	/* inside category */
801ab64890Smrg    S_NAME,	/* has name, expecting values */
811ab64890Smrg    S_VALUE
821ab64890Smrg} ParseState;
831ab64890Smrg
841ab64890Smrgtypedef enum {
851ab64890Smrg    T_NEWLINE,
861ab64890Smrg    T_COMMENT,
871ab64890Smrg    T_SEMICOLON,
881ab64890Smrg    T_DOUBLE_QUOTE,
891ab64890Smrg    T_LEFT_BRACE,
901ab64890Smrg    T_RIGHT_BRACE,
911ab64890Smrg    T_SPACE,
921ab64890Smrg    T_TAB,
931ab64890Smrg    T_BACKSLASH,
941ab64890Smrg    T_NUMERIC_HEX,
951ab64890Smrg    T_NUMERIC_DEC,
961ab64890Smrg    T_NUMERIC_OCT,
971ab64890Smrg    T_DEFAULT
981ab64890Smrg} Token;
991ab64890Smrg
1001ab64890Smrgtypedef struct {
1011ab64890Smrg    Token token;	/* token id */
1021ab64890Smrg    int len;		/* length of token sequence */
1031ab64890Smrg} TokenTable;
1041ab64890Smrg
1051ab64890Smrgstatic int f_newline (const char *str, Token token, Database *db);
1061ab64890Smrgstatic int f_comment (const char *str, Token token, Database *db);
1071ab64890Smrgstatic int f_semicolon (const char *str, Token token, Database *db);
1081ab64890Smrgstatic int f_double_quote (const char *str, Token token, Database *db);
1091ab64890Smrgstatic int f_left_brace (const char *str, Token token, Database *db);
1101ab64890Smrgstatic int f_right_brace (const char *str, Token token, Database *db);
1111ab64890Smrgstatic int f_white (const char *str, Token token, Database *db);
1121ab64890Smrgstatic int f_backslash (const char *str, Token token, Database *db);
1131ab64890Smrgstatic int f_numeric (const char *str, Token token, Database *db);
1141ab64890Smrgstatic int f_default (const char *str, Token token, Database *db);
1151ab64890Smrg
1161ab64890Smrgstatic const TokenTable token_tbl[] = {
1171ab64890Smrg    { T_NEWLINE,      1 },
1181ab64890Smrg    { T_COMMENT,      1 },
1191ab64890Smrg    { T_SEMICOLON,    1 },
1201ab64890Smrg    { T_DOUBLE_QUOTE, 1 },
1211ab64890Smrg    { T_LEFT_BRACE,   1 },
1221ab64890Smrg    { T_RIGHT_BRACE,  1 },
1231ab64890Smrg    { T_SPACE,        1 },
1241ab64890Smrg    { T_TAB,          1 },
1251ab64890Smrg    { T_BACKSLASH,    1 },
1261ab64890Smrg    { T_NUMERIC_HEX,  2 },
1271ab64890Smrg    { T_NUMERIC_DEC,  2 },
1281ab64890Smrg    { T_NUMERIC_OCT,  2 },
1291ab64890Smrg    { T_DEFAULT,      1 } /* any character */
1301ab64890Smrg};
1311ab64890Smrg
1321ab64890Smrg#define	SYM_CR          '\r'
1331ab64890Smrg#define	SYM_NEWLINE	'\n'
1341ab64890Smrg#define	SYM_COMMENT	'#'
1351ab64890Smrg#define	SYM_SEMICOLON	';'
1361ab64890Smrg#define	SYM_DOUBLE_QUOTE	'"'
1371ab64890Smrg#define	SYM_LEFT_BRACE	'{'
1381ab64890Smrg#define	SYM_RIGHT_BRACE	'}'
1391ab64890Smrg#define	SYM_SPACE	' '
1401ab64890Smrg#define	SYM_TAB		'\t'
1411ab64890Smrg#define	SYM_BACKSLASH	'\\'
1421ab64890Smrg
1431ab64890Smrg/************************************************************************/
1441ab64890Smrg
1451ab64890Smrg#define MAX_NAME_NEST	64
1461ab64890Smrg
1471ab64890Smrgtypedef struct {
1481ab64890Smrg    ParseState pre_state;
1491ab64890Smrg    char *category;
1501ab64890Smrg    char *name[MAX_NAME_NEST];
1511ab64890Smrg    int nest_depth;
1521ab64890Smrg    char **value;
1531ab64890Smrg    int value_len;
1541ab64890Smrg    int value_num;
1551ab64890Smrg    int bufsize;        /* bufMaxSize >= bufsize >= 0 */
1561ab64890Smrg    int bufMaxSize;     /* default : BUFSIZE */
1571ab64890Smrg    char *buf;
1581ab64890Smrg} DBParseInfo;
1591ab64890Smrg
1601ab64890Smrgstatic DBParseInfo parse_info;
1611ab64890Smrg
1621ab64890Smrgstatic void
1631ab64890Smrginit_parse_info (void)
1641ab64890Smrg{
1651ab64890Smrg    static int allocated /* = 0 */;
1661ab64890Smrg    char *ptr;
1671ab64890Smrg    int size;
1681ab64890Smrg    if (!allocated) {
1691ab64890Smrg	bzero(&parse_info, sizeof(DBParseInfo));
1701ab64890Smrg	parse_info.buf = (char *)Xmalloc(BUFSIZE);
1711ab64890Smrg	parse_info.bufMaxSize = BUFSIZE;
1721ab64890Smrg	allocated = 1;
1731ab64890Smrg	return;
1741ab64890Smrg    }
1751ab64890Smrg    ptr = parse_info.buf;
1761ab64890Smrg    size = parse_info.bufMaxSize;
1771ab64890Smrg    bzero(&parse_info, sizeof(DBParseInfo));
1781ab64890Smrg    parse_info.buf = ptr;
1791ab64890Smrg    parse_info.bufMaxSize = size;
1801ab64890Smrg}
1811ab64890Smrg
1821ab64890Smrgstatic void
1831ab64890Smrgclear_parse_info (void)
1841ab64890Smrg{
1851ab64890Smrg    int i;
1861ab64890Smrg    char *ptr;
1871ab64890Smrg    int size;
1881ab64890Smrg    parse_info.pre_state = S_NULL;
1891ab64890Smrg    if (parse_info.category != NULL) {
1901ab64890Smrg	Xfree(parse_info.category);
1911ab64890Smrg    }
1921ab64890Smrg    for (i = 0; i <= parse_info.nest_depth; ++i) {
1931ab64890Smrg	if (parse_info.name[i]) {
1941ab64890Smrg	    Xfree(parse_info.name[i]);
1951ab64890Smrg	}
1961ab64890Smrg    }
1971ab64890Smrg    if (parse_info.value) {
1981ab64890Smrg	if (*parse_info.value) {
1991ab64890Smrg	    Xfree(*parse_info.value);
2001ab64890Smrg	}
2011ab64890Smrg	Xfree((char *)parse_info.value);
2021ab64890Smrg    }
2031ab64890Smrg    ptr = parse_info.buf;
2041ab64890Smrg    size = parse_info.bufMaxSize;
2051ab64890Smrg    bzero(&parse_info, sizeof(DBParseInfo));
2061ab64890Smrg    parse_info.buf = ptr;
2071ab64890Smrg    parse_info.bufMaxSize = size;
2081ab64890Smrg}
2091ab64890Smrg
2101ab64890Smrgstatic Bool
2111ab64890Smrgrealloc_parse_info(
2121ab64890Smrg    int len)
2131ab64890Smrg{
2141ab64890Smrg    char *p;
2151ab64890Smrg
2161ab64890Smrg    parse_info.bufMaxSize = BUFSIZE * ((parse_info.bufsize + len)/BUFSIZE + 1);
2171ab64890Smrg    p = (char *)Xrealloc(parse_info.buf, parse_info.bufMaxSize);
2181ab64890Smrg    if (p == NULL)
2191ab64890Smrg        return False;
2201ab64890Smrg    parse_info.buf = p;
2211ab64890Smrg
2221ab64890Smrg    return True;
2231ab64890Smrg}
2241ab64890Smrg
2251ab64890Smrg/************************************************************************/
2261ab64890Smrg
2271ab64890Smrgtypedef struct _Line {
2281ab64890Smrg    char *str;
2291ab64890Smrg    int cursize;
2301ab64890Smrg    int maxsize;
2311ab64890Smrg    int seq;
2321ab64890Smrg} Line;
2331ab64890Smrg
2341ab64890Smrgstatic void
2351ab64890Smrgfree_line(
2361ab64890Smrg    Line *line)
2371ab64890Smrg{
2381ab64890Smrg    if (line->str != NULL) {
2391ab64890Smrg	Xfree(line->str);
2401ab64890Smrg    }
2411ab64890Smrg    bzero(line, sizeof(Line));
2421ab64890Smrg}
2431ab64890Smrg
2441ab64890Smrgstatic int
2451ab64890Smrgrealloc_line(
2461ab64890Smrg    Line *line,
2471ab64890Smrg    int size)
2481ab64890Smrg{
2491ab64890Smrg    char *str = line->str;
2501ab64890Smrg
2511ab64890Smrg    if (str != NULL) {
2521ab64890Smrg	str = (char *)Xrealloc(str, size);
2531ab64890Smrg    } else {
2541ab64890Smrg	str = (char *)Xmalloc(size);
2551ab64890Smrg    }
2561ab64890Smrg    if (str == NULL) {
2571ab64890Smrg	/* malloc error */
2581ab64890Smrg	if (line->str != NULL) {
2591ab64890Smrg	    Xfree(line->str);
2601ab64890Smrg	}
2611ab64890Smrg	bzero(line, sizeof(Line));
2621ab64890Smrg	return 0;
2631ab64890Smrg    }
2641ab64890Smrg    line->str = str;
2651ab64890Smrg    line->maxsize = size;
2661ab64890Smrg    return 1;
2671ab64890Smrg}
2681ab64890Smrg
2691ab64890Smrg#define	iswhite(ch)	((ch) == SYM_SPACE   || (ch) == SYM_TAB)
2701ab64890Smrg
2711ab64890Smrgstatic void
2721ab64890Smrgzap_comment(
2731ab64890Smrg    char *str,
2741ab64890Smrg    int *quoted)
2751ab64890Smrg{
2761ab64890Smrg    char *p = str;
2771ab64890Smrg#ifdef	never
2781ab64890Smrg    *quoted = 0;
2791ab64890Smrg    if (*p == SYM_COMMENT) {
2801ab64890Smrg	int len = strlen(str);
2811ab64890Smrg	if (p[len - 1] == SYM_NEWLINE || p[len - 1] == SYM_CR) {
2821ab64890Smrg	    *p++ = SYM_NEWLINE;
2831ab64890Smrg	}
2841ab64890Smrg	*p = '\0';
2851ab64890Smrg    }
2861ab64890Smrg#else
2871ab64890Smrg    while (*p) {
2881ab64890Smrg	if (*p == SYM_DOUBLE_QUOTE) {
2891ab64890Smrg	    if (p == str || p[-1] != SYM_BACKSLASH) {
2901ab64890Smrg		/* unescaped double quote changes quoted state. */
2911ab64890Smrg		*quoted = *quoted ? 0 : 1;
2921ab64890Smrg	    }
2931ab64890Smrg	}
2941ab64890Smrg	if (*p == SYM_COMMENT && !*quoted) {
2951ab64890Smrg	    int pos = p - str;
2961ab64890Smrg	    if (pos == 0 ||
2971ab64890Smrg	        (iswhite(p[-1]) && (pos == 1 || p[-2] != SYM_BACKSLASH))) {
2981ab64890Smrg		int len = strlen(p);
2991ab64890Smrg		if (len > 0 && (p[len - 1] == SYM_NEWLINE || p[len-1] == SYM_CR)) {
3001ab64890Smrg		    /* newline is the identifier for finding end of value.
3011ab64890Smrg		       therefore, it should not be removed. */
3021ab64890Smrg		    *p++ = SYM_NEWLINE;
3031ab64890Smrg		}
3041ab64890Smrg		*p = '\0';
3051ab64890Smrg		break;
3061ab64890Smrg	    }
3071ab64890Smrg	}
3081ab64890Smrg	++p;
3091ab64890Smrg    }
3101ab64890Smrg#endif
3111ab64890Smrg}
3121ab64890Smrg
3131ab64890Smrgstatic int
3141ab64890Smrgread_line(
3151ab64890Smrg    FILE *fd,
3161ab64890Smrg    Line *line)
3171ab64890Smrg{
3181ab64890Smrg    char buf[BUFSIZE], *p;
3191ab64890Smrg    int len;
3201ab64890Smrg    int quoted = 0;	/* quoted by double quote? */
3211ab64890Smrg    char *str;
3221ab64890Smrg    int cur;
3231ab64890Smrg
3241ab64890Smrg    str = line->str;
3251ab64890Smrg    cur = line->cursize = 0;
3261ab64890Smrg
3271ab64890Smrg    while ((p = fgets(buf, BUFSIZE, fd)) != NULL) {
3281ab64890Smrg	++line->seq;
3291ab64890Smrg	zap_comment(p, &quoted);	/* remove comment line */
3301ab64890Smrg	len = strlen(p);
3311ab64890Smrg	if (len == 0) {
3321ab64890Smrg	    if (cur > 0) {
3331ab64890Smrg		break;
3341ab64890Smrg	    }
3351ab64890Smrg	    continue;
3361ab64890Smrg	}
3371ab64890Smrg	if (cur + len + 1 > line->maxsize) {
3381ab64890Smrg	    /* need to reallocate buffer. */
3391ab64890Smrg	    if (! realloc_line(line, line->maxsize + BUFSIZE)) {
3401ab64890Smrg		return -1;	/* realloc error. */
3411ab64890Smrg	    }
3421ab64890Smrg	    str = line->str;
3431ab64890Smrg	}
3441ab64890Smrg	strncpy(str + cur, p, len);
3451ab64890Smrg
3461ab64890Smrg	cur += len;
3471ab64890Smrg	str[cur] = '\0';
3481ab64890Smrg#ifdef __UNIXOS2__  /* Take out carriage returns under OS/2 */
3491ab64890Smrg	if (cur>1) {
3501ab64890Smrg	   if (str[cur-2] == '\r' && str[cur-1] == '\n') {
3511ab64890Smrg	      str[cur-2] = '\n';
3521ab64890Smrg	      str[cur-1] = '\0';
3531ab64890Smrg	      cur--;
3541ab64890Smrg	   }
3551ab64890Smrg	}
3561ab64890Smrg#endif
3571ab64890Smrg	if (!quoted && cur > 1 && str[cur - 2] == SYM_BACKSLASH &&
3581ab64890Smrg	    (str[cur - 1] == SYM_NEWLINE || str[cur-1] == SYM_CR)) {
3591ab64890Smrg	    /* the line is ended backslash followed by newline.
3601ab64890Smrg	       need to concatinate the next line. */
3611ab64890Smrg	    cur -= 2;
3621ab64890Smrg	    str[cur] = '\0';
3631ab64890Smrg	} else if (len < BUFSIZE - 1 || buf[len - 1] == SYM_NEWLINE ||
3641ab64890Smrg		   buf[len - 1] == SYM_CR) {
3651ab64890Smrg	    /* the line is shorter than BUFSIZE. */
3661ab64890Smrg	    break;
3671ab64890Smrg	}
3681ab64890Smrg    }
3691ab64890Smrg    if (quoted) {
3701ab64890Smrg	/* error.  still in quoted state. */
3711ab64890Smrg	return -1;
3721ab64890Smrg    }
3731ab64890Smrg    return line->cursize = cur;
3741ab64890Smrg}
3751ab64890Smrg
3761ab64890Smrg/************************************************************************/
3771ab64890Smrg
3781ab64890Smrgstatic Token
3791ab64890Smrgget_token(
3801ab64890Smrg    const char *str)
3811ab64890Smrg{
3821ab64890Smrg    switch (*str) {
3831ab64890Smrg    case SYM_NEWLINE:
3841ab64890Smrg    case SYM_CR:		return T_NEWLINE;
3851ab64890Smrg    case SYM_COMMENT:		return T_COMMENT;
3861ab64890Smrg    case SYM_SEMICOLON:		return T_SEMICOLON;
3871ab64890Smrg    case SYM_DOUBLE_QUOTE:	return T_DOUBLE_QUOTE;
3881ab64890Smrg    case SYM_LEFT_BRACE:	return T_LEFT_BRACE;
3891ab64890Smrg    case SYM_RIGHT_BRACE:	return T_RIGHT_BRACE;
3901ab64890Smrg    case SYM_SPACE:		return T_SPACE;
3911ab64890Smrg    case SYM_TAB:		return T_TAB;
3921ab64890Smrg    case SYM_BACKSLASH:
3931ab64890Smrg	switch (str[1]) {
3941ab64890Smrg	case 'x': return T_NUMERIC_HEX;
3951ab64890Smrg	case 'd': return T_NUMERIC_DEC;
3961ab64890Smrg	case 'o': return T_NUMERIC_OCT;
3971ab64890Smrg	}
3981ab64890Smrg	return T_BACKSLASH;
3991ab64890Smrg    default:
4001ab64890Smrg	return T_DEFAULT;
4011ab64890Smrg    }
4021ab64890Smrg}
4031ab64890Smrg
4041ab64890Smrgstatic int
4051ab64890Smrgget_word(
4061ab64890Smrg    const char *str,
4071ab64890Smrg    char *word)
4081ab64890Smrg{
4091ab64890Smrg    const char *p = str;
4101ab64890Smrg    char *w = word;
4111ab64890Smrg    Token token;
4121ab64890Smrg    int token_len;
4131ab64890Smrg
4141ab64890Smrg    while (*p != '\0') {
4151ab64890Smrg	token = get_token(p);
4161ab64890Smrg	token_len = token_tbl[token].len;
4171ab64890Smrg	if (token == T_BACKSLASH) {
4181ab64890Smrg	    p += token_len;
4191ab64890Smrg	    if (*p == '\0')
4201ab64890Smrg		break;
4211ab64890Smrg	    token = get_token(p);
4221ab64890Smrg	    token_len = token_tbl[token].len;
4231ab64890Smrg	} else if (token != T_COMMENT && token != T_DEFAULT) {
4241ab64890Smrg	    break;
4251ab64890Smrg	}
4261ab64890Smrg	strncpy(w, p, token_len);
4271ab64890Smrg	p += token_len; w += token_len;
4281ab64890Smrg    }
4291ab64890Smrg    *w = '\0';
4301ab64890Smrg    return p - str;	/* return number of scanned chars */
4311ab64890Smrg}
4321ab64890Smrg
4331ab64890Smrgstatic int
4341ab64890Smrgget_quoted_word(
4351ab64890Smrg    const char *str,
4361ab64890Smrg    char *word)
4371ab64890Smrg{
4381ab64890Smrg    const char *p = str;
4391ab64890Smrg    char *w = word;
4401ab64890Smrg    Token token;
4411ab64890Smrg    int token_len;
4421ab64890Smrg
4431ab64890Smrg    if (*p == SYM_DOUBLE_QUOTE) {
4441ab64890Smrg	++p;
4451ab64890Smrg    }
4461ab64890Smrg    while (*p != '\0') {
4471ab64890Smrg	token = get_token(p);
4481ab64890Smrg	token_len = token_tbl[token].len;
4491ab64890Smrg	if (token == T_DOUBLE_QUOTE) {
4501ab64890Smrg	    p += token_len;
4511ab64890Smrg	    goto found;
4521ab64890Smrg	}
4531ab64890Smrg	if (token == T_BACKSLASH) {
4541ab64890Smrg	    p += token_len;
4551ab64890Smrg	    if (*p == '\0') {
4561ab64890Smrg		break;
4571ab64890Smrg	    }
4581ab64890Smrg	    token = get_token(p);
4591ab64890Smrg	    token_len = token_tbl[token].len;
4601ab64890Smrg	}
4611ab64890Smrg	strncpy(w, p, token_len);
4621ab64890Smrg	p += token_len; w += token_len;
4631ab64890Smrg    }
4641ab64890Smrg    /* error. cannot detect next double quote */
4651ab64890Smrg    return 0;
4661ab64890Smrg
4671ab64890Smrg found:;
4681ab64890Smrg    *w = '\0';
4691ab64890Smrg    return p - str;
4701ab64890Smrg}
4711ab64890Smrg
4721ab64890Smrg/************************************************************************/
4731ab64890Smrg
4741ab64890Smrgstatic int
4751ab64890Smrgappend_value_list (void)
4761ab64890Smrg{
4771ab64890Smrg    char **value_list = parse_info.value;
4781ab64890Smrg    char *value;
4791ab64890Smrg    int value_num = parse_info.value_num;
4801ab64890Smrg    int value_len = parse_info.value_len;
4811ab64890Smrg    char *str = parse_info.buf;
4821ab64890Smrg    int len = parse_info.bufsize;
4831ab64890Smrg    char *p;
4841ab64890Smrg
4851ab64890Smrg    if (len < 1) {
4861ab64890Smrg	return 1; /* return with no error */
4871ab64890Smrg    }
4881ab64890Smrg
4891ab64890Smrg    if (value_list == (char **)NULL) {
4901ab64890Smrg	value_list = (char **)Xmalloc(sizeof(char *) * 2);
4911ab64890Smrg	*value_list = NULL;
4921ab64890Smrg    } else {
4931ab64890Smrg	char **prev_list = value_list;
4941ab64890Smrg
4951ab64890Smrg	value_list = (char **)
4961ab64890Smrg	    Xrealloc(value_list, sizeof(char *) * (value_num + 2));
4971ab64890Smrg	if (value_list == NULL) {
4981ab64890Smrg	    Xfree(prev_list);
4991ab64890Smrg	}
5001ab64890Smrg    }
5011ab64890Smrg    if (value_list == (char **)NULL)
5021ab64890Smrg	goto err2;
5031ab64890Smrg
5041ab64890Smrg    value = *value_list;
5051ab64890Smrg    if (value == NULL) {
5061ab64890Smrg	value = (char *)Xmalloc(value_len + len + 1);
5071ab64890Smrg    } else {
5081ab64890Smrg	char *prev_value = value;
5091ab64890Smrg
5101ab64890Smrg	value = (char *)Xrealloc(value, value_len + len + 1);
5111ab64890Smrg	if (value == NULL) {
5121ab64890Smrg	    Xfree(prev_value);
5131ab64890Smrg	}
5141ab64890Smrg    }
5151ab64890Smrg    if (value == NULL) {
5161ab64890Smrg	goto err1;
5171ab64890Smrg    }
5181ab64890Smrg    if (value != *value_list) {
5191ab64890Smrg	int i;
5201ab64890Smrg	ssize_t delta;
5211ab64890Smrg	delta = value - *value_list;
5221ab64890Smrg	*value_list = value;
5231ab64890Smrg	for (i = 1; i < value_num; ++i) {
5241ab64890Smrg	    value_list[i] += delta;
5251ab64890Smrg	}
5261ab64890Smrg    }
5271ab64890Smrg
5281ab64890Smrg    value_list[value_num] = p = &value[value_len];
5291ab64890Smrg    value_list[value_num + 1] = NULL;
5301ab64890Smrg    strncpy(p, str, len);
5311ab64890Smrg    p[len] = 0;
5321ab64890Smrg
5331ab64890Smrg    parse_info.value = value_list;
5341ab64890Smrg    parse_info.value_num = value_num + 1;
5351ab64890Smrg    parse_info.value_len = value_len + len + 1;
5361ab64890Smrg    parse_info.bufsize = 0;
5371ab64890Smrg    return 1;
5381ab64890Smrg
5391ab64890Smrg err1:
5401ab64890Smrg    if (value_list) {
5411ab64890Smrg	Xfree((char **)value_list);
5421ab64890Smrg    }
5431ab64890Smrg    if (value) {
5441ab64890Smrg	Xfree(value);
5451ab64890Smrg    }
5461ab64890Smrg err2:
5471ab64890Smrg    parse_info.value = (char **)NULL;
5481ab64890Smrg    parse_info.value_num = 0;
5491ab64890Smrg    parse_info.value_len = 0;
5501ab64890Smrg    parse_info.bufsize = 0;
5511ab64890Smrg    return 0;
5521ab64890Smrg}
5531ab64890Smrg
5541ab64890Smrgstatic int
5551ab64890Smrgconstruct_name(
5561ab64890Smrg    char *name,
5571ab64890Smrg    int size)
5581ab64890Smrg{
5591ab64890Smrg    int i;
5601ab64890Smrg    int len = 0;
5611ab64890Smrg    char *p = name;
5621ab64890Smrg
5631ab64890Smrg    for (i = 0; i <= parse_info.nest_depth; ++i) {
5641ab64890Smrg	len += strlen(parse_info.name[i]) + 1;
5651ab64890Smrg    }
5661ab64890Smrg    if (len >= size)
5671ab64890Smrg	return 0;
5681ab64890Smrg
5691ab64890Smrg    strcpy(p, parse_info.name[0]);
5701ab64890Smrg    p += strlen(parse_info.name[0]);
5711ab64890Smrg    for (i = 1; i <= parse_info.nest_depth; ++i) {
5721ab64890Smrg	*p++ = '.';
5731ab64890Smrg	strcpy(p, parse_info.name[i]);
5741ab64890Smrg	p += strlen(parse_info.name[i]);
5751ab64890Smrg    }
5761ab64890Smrg    return *name != '\0';
5771ab64890Smrg}
5781ab64890Smrg
5791ab64890Smrgstatic int
5801ab64890Smrgstore_to_database(
5811ab64890Smrg    Database *db)
5821ab64890Smrg{
5831ab64890Smrg    Database new = (Database)NULL;
5841ab64890Smrg    char name[BUFSIZE];
5851ab64890Smrg
5861ab64890Smrg    if (parse_info.pre_state == S_VALUE) {
5871ab64890Smrg	if (! append_value_list()) {
5881ab64890Smrg	    goto err;
5891ab64890Smrg	}
5901ab64890Smrg    }
5911ab64890Smrg
5921ab64890Smrg    if (parse_info.name[parse_info.nest_depth] == NULL) {
5931ab64890Smrg	goto err;
5941ab64890Smrg    }
5951ab64890Smrg
5961ab64890Smrg    new = (Database)Xmalloc(sizeof(DatabaseRec));
5971ab64890Smrg    if (new == (Database)NULL) {
5981ab64890Smrg	goto err;
5991ab64890Smrg    }
6001ab64890Smrg    bzero(new, sizeof(DatabaseRec));
6011ab64890Smrg
6021ab64890Smrg    new->category = (char *)Xmalloc(strlen(parse_info.category) + 1);
6031ab64890Smrg    if (new->category == NULL) {
6041ab64890Smrg	goto err;
6051ab64890Smrg    }
6061ab64890Smrg    strcpy(new->category, parse_info.category);
6071ab64890Smrg
6081ab64890Smrg    if (! construct_name(name, sizeof(name))) {
6091ab64890Smrg	goto err;
6101ab64890Smrg    }
6111ab64890Smrg    new->name = (char *)Xmalloc(strlen(name) + 1);
6121ab64890Smrg    if (new->name == NULL) {
6131ab64890Smrg	goto err;
6141ab64890Smrg    }
6151ab64890Smrg    strcpy(new->name, name);
6161ab64890Smrg    new->next = *db;
6171ab64890Smrg    new->value = parse_info.value;
6181ab64890Smrg    new->value_num = parse_info.value_num;
6191ab64890Smrg    *db = new;
6201ab64890Smrg
6211ab64890Smrg    Xfree(parse_info.name[parse_info.nest_depth]);
6221ab64890Smrg    parse_info.name[parse_info.nest_depth] = NULL;
6231ab64890Smrg
6241ab64890Smrg    parse_info.value = (char **)NULL;
6251ab64890Smrg    parse_info.value_num = 0;
6261ab64890Smrg    parse_info.value_len = 0;
6271ab64890Smrg
6281ab64890Smrg    return 1;
6291ab64890Smrg
6301ab64890Smrg err:
6311ab64890Smrg    if (new) {
6321ab64890Smrg	if (new->category) {
6331ab64890Smrg	    Xfree(new->category);
6341ab64890Smrg	}
6351ab64890Smrg	if (new->name) {
6361ab64890Smrg	    Xfree(new->name);
6371ab64890Smrg	}
6381ab64890Smrg	Xfree(new);
6391ab64890Smrg    }
6401ab64890Smrg    if (parse_info.value) {
6411ab64890Smrg	if (*parse_info.value) {
6421ab64890Smrg	    Xfree(*parse_info.value);
6431ab64890Smrg	}
6441ab64890Smrg	Xfree((char **)parse_info.value);
6451ab64890Smrg	parse_info.value = (char **)NULL;
6461ab64890Smrg	parse_info.value_num = 0;
6471ab64890Smrg	parse_info.value_len = 0;
6481ab64890Smrg    }
6491ab64890Smrg    return 0;
6501ab64890Smrg}
6511ab64890Smrg
6521ab64890Smrg#define END_MARK	"END"
6531ab64890Smrg#define	END_MARK_LEN	3 /*strlen(END_MARK)*/
6541ab64890Smrg
6551ab64890Smrgstatic int
6561ab64890Smrgcheck_category_end(
6571ab64890Smrg    const char *str)
6581ab64890Smrg{
6591ab64890Smrg    const char *p;
6601ab64890Smrg    int len;
6611ab64890Smrg
6621ab64890Smrg    p = str;
6631ab64890Smrg    if (strncmp(p, END_MARK, END_MARK_LEN)) {
6641ab64890Smrg	return 0;
6651ab64890Smrg    }
6661ab64890Smrg    p += END_MARK_LEN;
6671ab64890Smrg
6681ab64890Smrg    while (iswhite(*p)) {
6691ab64890Smrg	++p;
6701ab64890Smrg    }
6711ab64890Smrg    len = strlen(parse_info.category);
6721ab64890Smrg    if (strncmp(p, parse_info.category, len)) {
6731ab64890Smrg	return 0;
6741ab64890Smrg    }
6751ab64890Smrg    p += len;
6761ab64890Smrg    return p - str;
6771ab64890Smrg}
6781ab64890Smrg
6791ab64890Smrg/************************************************************************/
6801ab64890Smrg
6811ab64890Smrgstatic int
6821ab64890Smrgf_newline(
6831ab64890Smrg    const char *str,
6841ab64890Smrg    Token token,
6851ab64890Smrg    Database *db)
6861ab64890Smrg{
6871ab64890Smrg    switch (parse_info.pre_state) {
6881ab64890Smrg    case S_NULL:
6891ab64890Smrg    case S_CATEGORY:
6901ab64890Smrg	break;
6911ab64890Smrg    case S_NAME:
6921ab64890Smrg	return 0; /* no value */
6931ab64890Smrg    case S_VALUE:
6941ab64890Smrg	if (!store_to_database(db))
6951ab64890Smrg	    return 0;
6961ab64890Smrg	parse_info.pre_state = S_CATEGORY;
6971ab64890Smrg	break;
6981ab64890Smrg    default:
6991ab64890Smrg	return 0;
7001ab64890Smrg    }
7011ab64890Smrg    return token_tbl[token].len;
7021ab64890Smrg}
7031ab64890Smrg
7041ab64890Smrgstatic int
7051ab64890Smrgf_comment(
7061ab64890Smrg    const char *str,
7071ab64890Smrg    Token token,
7081ab64890Smrg    Database *db)
7091ab64890Smrg{
7101ab64890Smrg    /* NOTE: comment is already handled in read_line(),
7111ab64890Smrg       so this function is not necessary. */
7121ab64890Smrg
7131ab64890Smrg    const char *p = str;
7141ab64890Smrg
7151ab64890Smrg    while (*p != SYM_NEWLINE && *p != SYM_CR && *p != '\0') {
7161ab64890Smrg	++p;	/* zap to the end of line */
7171ab64890Smrg    }
7181ab64890Smrg    return p - str;
7191ab64890Smrg}
7201ab64890Smrg
7211ab64890Smrgstatic int
7221ab64890Smrgf_white(
7231ab64890Smrg    const char *str,
7241ab64890Smrg    Token token,
7251ab64890Smrg    Database *db)
7261ab64890Smrg{
7271ab64890Smrg    const char *p = str;
7281ab64890Smrg
7291ab64890Smrg    while (iswhite(*p)) {
7301ab64890Smrg	++p;
7311ab64890Smrg    }
7321ab64890Smrg    return p - str;
7331ab64890Smrg}
7341ab64890Smrg
7351ab64890Smrgstatic int
7361ab64890Smrgf_semicolon(
7371ab64890Smrg    const char *str,
7381ab64890Smrg    Token token,
7391ab64890Smrg    Database *db)
7401ab64890Smrg{
7411ab64890Smrg    switch (parse_info.pre_state) {
7421ab64890Smrg    case S_NULL:
7431ab64890Smrg    case S_CATEGORY:
7441ab64890Smrg    case S_NAME:
7451ab64890Smrg	return 0;
7461ab64890Smrg    case S_VALUE:
7471ab64890Smrg	if (! append_value_list())
7481ab64890Smrg	    return 0;
7491ab64890Smrg	parse_info.pre_state = S_VALUE;
7501ab64890Smrg	break;
7511ab64890Smrg    default:
7521ab64890Smrg	return 0;
7531ab64890Smrg    }
7541ab64890Smrg    return token_tbl[token].len;
7551ab64890Smrg}
7561ab64890Smrg
7571ab64890Smrgstatic int
7581ab64890Smrgf_left_brace(
7591ab64890Smrg    const char *str,
7601ab64890Smrg    Token token,
7611ab64890Smrg    Database *db)
7621ab64890Smrg{
7631ab64890Smrg    switch (parse_info.pre_state) {
7641ab64890Smrg    case S_NULL:
7651ab64890Smrg    case S_CATEGORY:
7661ab64890Smrg    case S_VALUE:
7671ab64890Smrg	return 0;
7681ab64890Smrg    case S_NAME:
7691ab64890Smrg	if (parse_info.name[parse_info.nest_depth] == NULL
7701ab64890Smrg	    || parse_info.nest_depth + 1 > MAX_NAME_NEST)
7711ab64890Smrg	    return 0;
7721ab64890Smrg	++parse_info.nest_depth;
7731ab64890Smrg	parse_info.pre_state = S_CATEGORY;
7741ab64890Smrg	break;
7751ab64890Smrg    default:
7761ab64890Smrg	return 0;
7771ab64890Smrg    }
7781ab64890Smrg    return token_tbl[token].len;
7791ab64890Smrg}
7801ab64890Smrg
7811ab64890Smrgstatic int
7821ab64890Smrgf_right_brace(
7831ab64890Smrg    const char *str,
7841ab64890Smrg    Token token,
7851ab64890Smrg    Database *db)
7861ab64890Smrg{
7871ab64890Smrg    if (parse_info.nest_depth < 1)
7881ab64890Smrg	return 0;
7891ab64890Smrg
7901ab64890Smrg    switch (parse_info.pre_state) {
7911ab64890Smrg    case S_NULL:
7921ab64890Smrg    case S_NAME:
7931ab64890Smrg	return 0;
7941ab64890Smrg    case S_VALUE:
7951ab64890Smrg	if (! store_to_database(db))
7961ab64890Smrg	    return 0;
7971ab64890Smrg	/* fall into next case */
7981ab64890Smrg    case S_CATEGORY:
7991ab64890Smrg	if (parse_info.name[parse_info.nest_depth] != NULL) {
8001ab64890Smrg	    Xfree(parse_info.name[parse_info.nest_depth]);
8011ab64890Smrg	    parse_info.name[parse_info.nest_depth] = NULL;
8021ab64890Smrg	}
8031ab64890Smrg	--parse_info.nest_depth;
8041ab64890Smrg	parse_info.pre_state = S_CATEGORY;
8051ab64890Smrg	break;
8061ab64890Smrg    default:
8071ab64890Smrg	return 0;
8081ab64890Smrg    }
8091ab64890Smrg    return token_tbl[token].len;
8101ab64890Smrg}
8111ab64890Smrg
8121ab64890Smrgstatic int
8131ab64890Smrgf_double_quote(
8141ab64890Smrg    const char *str,
8151ab64890Smrg    Token token,
8161ab64890Smrg    Database *db)
8171ab64890Smrg{
8181ab64890Smrg    char word[BUFSIZE];
8191ab64890Smrg    char* wordp;
8201ab64890Smrg    int len;
8211ab64890Smrg
8221ab64890Smrg    if ((len = strlen (str)) < sizeof word)
8231ab64890Smrg	wordp = word;
8241ab64890Smrg    else
8251ab64890Smrg	wordp = Xmalloc (len + 1);
8261ab64890Smrg    if (wordp == NULL)
8271ab64890Smrg	return 0;
8281ab64890Smrg
8291ab64890Smrg    len = 0;
8301ab64890Smrg    switch (parse_info.pre_state) {
8311ab64890Smrg    case S_NULL:
8321ab64890Smrg    case S_CATEGORY:
8331ab64890Smrg	goto err;
8341ab64890Smrg    case S_NAME:
8351ab64890Smrg    case S_VALUE:
8361ab64890Smrg	len = get_quoted_word(str, wordp);
8371ab64890Smrg	if (len < 1)
8381ab64890Smrg	    goto err;
8391ab64890Smrg	if ((parse_info.bufsize + (int)strlen(wordp) + 1)
8401ab64890Smrg					>= parse_info.bufMaxSize) {
8411ab64890Smrg	    if (realloc_parse_info(strlen(wordp)+1) == False) {
8421ab64890Smrg		goto err;
8431ab64890Smrg	    }
8441ab64890Smrg	}
8451ab64890Smrg	strcpy(&parse_info.buf[parse_info.bufsize], wordp);
8461ab64890Smrg	parse_info.bufsize += strlen(wordp);
8471ab64890Smrg	parse_info.pre_state = S_VALUE;
8481ab64890Smrg	break;
8491ab64890Smrg    default:
8501ab64890Smrg	goto err;
8511ab64890Smrg    }
8521ab64890Smrg    if (wordp != word)
8531ab64890Smrg	Xfree (wordp);
8541ab64890Smrg    return len;	/* including length of token */
8551ab64890Smrg
8561ab64890Smrgerr:
8571ab64890Smrg    if (wordp != word)
8581ab64890Smrg	Xfree (wordp);
8591ab64890Smrg    return 0;
8601ab64890Smrg}
8611ab64890Smrg
8621ab64890Smrgstatic int
8631ab64890Smrgf_backslash(
8641ab64890Smrg    const char *str,
8651ab64890Smrg    Token token,
8661ab64890Smrg    Database *db)
8671ab64890Smrg{
8681ab64890Smrg    return f_default(str, token, db);
8691ab64890Smrg}
8701ab64890Smrg
8711ab64890Smrgstatic int
8721ab64890Smrgf_numeric(
8731ab64890Smrg    const char *str,
8741ab64890Smrg    Token token,
8751ab64890Smrg    Database *db)
8761ab64890Smrg{
8771ab64890Smrg    char word[BUFSIZE];
8781ab64890Smrg    const char *p;
8791ab64890Smrg    char* wordp;
8801ab64890Smrg    int len;
8811ab64890Smrg    int token_len;
8821ab64890Smrg
8831ab64890Smrg    if ((len = strlen (str)) < sizeof word)
8841ab64890Smrg	wordp = word;
8851ab64890Smrg    else
8861ab64890Smrg	wordp = Xmalloc (len + 1);
8871ab64890Smrg    if (wordp == NULL)
8881ab64890Smrg	return 0;
8891ab64890Smrg
8901ab64890Smrg    switch (parse_info.pre_state) {
8911ab64890Smrg    case S_NULL:
8921ab64890Smrg    case S_CATEGORY:
8931ab64890Smrg	goto err;
8941ab64890Smrg    case S_NAME:
8951ab64890Smrg    case S_VALUE:
8961ab64890Smrg	token_len = token_tbl[token].len;
8971ab64890Smrg	p = str + token_len;
8981ab64890Smrg	len = get_word(p, wordp);
8991ab64890Smrg	if (len < 1)
9001ab64890Smrg	    goto err;
9011ab64890Smrg	if ((parse_info.bufsize + token_len + (int)strlen(wordp) + 1)
9021ab64890Smrg					>= parse_info.bufMaxSize) {
9031ab64890Smrg	    if (realloc_parse_info(token_len + strlen(wordp) + 1) == False)
9041ab64890Smrg		goto err;
9051ab64890Smrg	}
9061ab64890Smrg	strncpy(&parse_info.buf[parse_info.bufsize], str, token_len);
9071ab64890Smrg	strcpy(&parse_info.buf[parse_info.bufsize + token_len], wordp);
9081ab64890Smrg	parse_info.bufsize += token_len + strlen(wordp);
9091ab64890Smrg	parse_info.pre_state = S_VALUE;
9101ab64890Smrg	break;
9111ab64890Smrg    default:
9121ab64890Smrg	goto err;
9131ab64890Smrg    }
9141ab64890Smrg    if (wordp != word)
9151ab64890Smrg	Xfree (wordp);
9161ab64890Smrg    return len + token_len;
9171ab64890Smrg
9181ab64890Smrgerr:
9191ab64890Smrg    if (wordp != word)
9201ab64890Smrg	Xfree (wordp);
9211ab64890Smrg    return 0;
9221ab64890Smrg}
9231ab64890Smrg
9241ab64890Smrgstatic int
9251ab64890Smrgf_default(
9261ab64890Smrg    const char *str,
9271ab64890Smrg    Token token,
9281ab64890Smrg    Database *db)
9291ab64890Smrg{
9301ab64890Smrg    char word[BUFSIZE], *p;
9311ab64890Smrg    char* wordp;
9321ab64890Smrg    int len;
9331ab64890Smrg
9341ab64890Smrg    if ((len = strlen (str)) < sizeof word)
9351ab64890Smrg	wordp = word;
9361ab64890Smrg    else
9371ab64890Smrg	wordp = Xmalloc (len + 1);
9381ab64890Smrg    if (wordp == NULL)
9391ab64890Smrg	return 0;
9401ab64890Smrg
9411ab64890Smrg    len = get_word(str, wordp);
9421ab64890Smrg    if (len < 1)
9431ab64890Smrg	goto err;
9441ab64890Smrg
9451ab64890Smrg    switch (parse_info.pre_state) {
9461ab64890Smrg    case S_NULL:
9471ab64890Smrg	if (parse_info.category != NULL)
9481ab64890Smrg	    goto err;
9491ab64890Smrg	p = (char *)Xmalloc(strlen(wordp) + 1);
9501ab64890Smrg	if (p == NULL)
9511ab64890Smrg	    goto err;
9521ab64890Smrg	strcpy(p, wordp);
9531ab64890Smrg	parse_info.category = p;
9541ab64890Smrg	parse_info.pre_state = S_CATEGORY;
9551ab64890Smrg	break;
9561ab64890Smrg    case S_CATEGORY:
9571ab64890Smrg	if (parse_info.nest_depth == 0) {
9581ab64890Smrg	    if (check_category_end(str)) {
9591ab64890Smrg		/* end of category is detected.
9601ab64890Smrg		   clear context and zap to end of this line */
9611ab64890Smrg		clear_parse_info();
9621ab64890Smrg		len = strlen(str);
9631ab64890Smrg		break;
9641ab64890Smrg	    }
9651ab64890Smrg	}
9661ab64890Smrg	p = (char *)Xmalloc(strlen(wordp) + 1);
9671ab64890Smrg	if (p == NULL)
9681ab64890Smrg	    goto err;
9691ab64890Smrg	strcpy(p, wordp);
9701ab64890Smrg	if (parse_info.name[parse_info.nest_depth] != NULL) {
9711ab64890Smrg	    Xfree(parse_info.name[parse_info.nest_depth]);
9721ab64890Smrg	}
9731ab64890Smrg	parse_info.name[parse_info.nest_depth] = p;
9741ab64890Smrg	parse_info.pre_state = S_NAME;
9751ab64890Smrg	break;
9761ab64890Smrg    case S_NAME:
9771ab64890Smrg    case S_VALUE:
9781ab64890Smrg	if ((parse_info.bufsize + (int)strlen(wordp) + 1)
9791ab64890Smrg					>= parse_info.bufMaxSize) {
9801ab64890Smrg	    if (realloc_parse_info(strlen(wordp) + 1) == False)
9811ab64890Smrg		goto err;
9821ab64890Smrg	}
9831ab64890Smrg	strcpy(&parse_info.buf[parse_info.bufsize], wordp);
9841ab64890Smrg	parse_info.bufsize += strlen(wordp);
9851ab64890Smrg	parse_info.pre_state = S_VALUE;
9861ab64890Smrg	break;
9871ab64890Smrg    default:
9881ab64890Smrg	goto err;
9891ab64890Smrg    }
9901ab64890Smrg    if (wordp != word)
9911ab64890Smrg	Xfree (wordp);
9921ab64890Smrg    return len;
9931ab64890Smrg
9941ab64890Smrgerr:
9951ab64890Smrg    if (wordp != word)
9961ab64890Smrg	Xfree (wordp);
9971ab64890Smrg    return 0;
9981ab64890Smrg}
9991ab64890Smrg
10001ab64890Smrg/************************************************************************/
10011ab64890Smrg
10021ab64890Smrg#ifdef DEBUG
10031ab64890Smrgstatic void
10041ab64890SmrgPrintDatabase(
10051ab64890Smrg    Database db)
10061ab64890Smrg{
10071ab64890Smrg    Database p = db;
10081ab64890Smrg    int i = 0, j;
10091ab64890Smrg
10101ab64890Smrg    printf("***\n*** BEGIN Database\n***\n");
10111ab64890Smrg    while (p) {
10121ab64890Smrg	printf("%3d: ", i++);
10131ab64890Smrg	printf("%s, %s, ", p->category, p->name);
10141ab64890Smrg	printf("\t[%d: ", p->value_num);
10151ab64890Smrg	for (j = 0; j < p->value_num; ++j) {
10161ab64890Smrg	    printf("%s, ", p->value[j]);
10171ab64890Smrg	}
10181ab64890Smrg	printf("]\n");
10191ab64890Smrg	p = p->next;
10201ab64890Smrg    }
10211ab64890Smrg    printf("***\n*** END   Database\n***\n");
10221ab64890Smrg}
10231ab64890Smrg#endif
10241ab64890Smrg
10251ab64890Smrgstatic void
10261ab64890SmrgDestroyDatabase(
10271ab64890Smrg    Database db)
10281ab64890Smrg{
10291ab64890Smrg    Database p = db;
10301ab64890Smrg
10311ab64890Smrg    while (p) {
10321ab64890Smrg	if (p->category != NULL) {
10331ab64890Smrg	    Xfree(p->category);
10341ab64890Smrg	}
10351ab64890Smrg	if (p->name != NULL) {
10361ab64890Smrg	    Xfree(p->name);
10371ab64890Smrg	}
10381ab64890Smrg	if (p->value != (char **)NULL) {
10391ab64890Smrg	    if (*p->value != NULL) {
10401ab64890Smrg		Xfree(*p->value);
10411ab64890Smrg	    }
10421ab64890Smrg	    Xfree((char *)p->value);
10431ab64890Smrg	}
10441ab64890Smrg	db = p->next;
10451ab64890Smrg	Xfree((char *)p);
10461ab64890Smrg	p = db;
10471ab64890Smrg    }
10481ab64890Smrg}
10491ab64890Smrg
10501ab64890Smrgstatic int
10511ab64890SmrgCountDatabase(
10521ab64890Smrg    Database db)
10531ab64890Smrg{
10541ab64890Smrg    Database p = db;
10551ab64890Smrg    int cnt = 0;
10561ab64890Smrg
10571ab64890Smrg    while (p) {
10581ab64890Smrg	++cnt;
10591ab64890Smrg	p = p->next;
10601ab64890Smrg    }
10611ab64890Smrg    return cnt;
10621ab64890Smrg}
10631ab64890Smrg
10641ab64890Smrgstatic Database
10651ab64890SmrgCreateDatabase(
10661ab64890Smrg    char *dbfile)
10671ab64890Smrg{
10681ab64890Smrg    Database db = (Database)NULL;
10691ab64890Smrg    FILE *fd;
10701ab64890Smrg    Line line;
10711ab64890Smrg    char *p;
10721ab64890Smrg    Token token;
10731ab64890Smrg    int len;
10741ab64890Smrg    int error = 0;
10751ab64890Smrg
10761ab64890Smrg    fd = _XFopenFile(dbfile, "r");
10771ab64890Smrg    if (fd == (FILE *)NULL)
10781ab64890Smrg	return NULL;
10791ab64890Smrg
10801ab64890Smrg    bzero(&line, sizeof(Line));
10811ab64890Smrg    init_parse_info();
10821ab64890Smrg
10831ab64890Smrg    do {
10841ab64890Smrg	int rc = read_line(fd, &line);
10851ab64890Smrg	if (rc < 0) {
10861ab64890Smrg	    error = 1;
10871ab64890Smrg	    break;
10881ab64890Smrg	} else if (rc == 0) {
10891ab64890Smrg	    break;
10901ab64890Smrg	}
10911ab64890Smrg	p = line.str;
10921ab64890Smrg	while (*p) {
10931ab64890Smrg            int (*parse_proc)(const char *str, Token token, Database *db) = NULL;
10941ab64890Smrg
10951ab64890Smrg	    token = get_token(p);
10961ab64890Smrg
10971ab64890Smrg            switch (token_tbl[token].token) {
10981ab64890Smrg            case T_NEWLINE:
10991ab64890Smrg                parse_proc = f_newline;
11001ab64890Smrg                break;
11011ab64890Smrg            case T_COMMENT:
11021ab64890Smrg                parse_proc = f_comment;
11031ab64890Smrg                break;
11041ab64890Smrg            case T_SEMICOLON:
11051ab64890Smrg                parse_proc = f_semicolon;
11061ab64890Smrg                break;
11071ab64890Smrg            case T_DOUBLE_QUOTE:
11081ab64890Smrg                parse_proc = f_double_quote;
11091ab64890Smrg                break;
11101ab64890Smrg            case T_LEFT_BRACE:
11111ab64890Smrg                parse_proc = f_left_brace;
11121ab64890Smrg                break;
11131ab64890Smrg            case T_RIGHT_BRACE:
11141ab64890Smrg                parse_proc = f_right_brace;
11151ab64890Smrg                break;
11161ab64890Smrg            case T_SPACE:
11171ab64890Smrg            case T_TAB:
11181ab64890Smrg                parse_proc = f_white;
11191ab64890Smrg                break;
11201ab64890Smrg            case T_BACKSLASH:
11211ab64890Smrg                parse_proc = f_backslash;
11221ab64890Smrg                break;
11231ab64890Smrg            case T_NUMERIC_HEX:
11241ab64890Smrg            case T_NUMERIC_DEC:
11251ab64890Smrg            case T_NUMERIC_OCT:
11261ab64890Smrg                parse_proc = f_numeric;
11271ab64890Smrg                break;
11281ab64890Smrg            case T_DEFAULT:
11291ab64890Smrg                parse_proc = f_default;
11301ab64890Smrg                break;
11311ab64890Smrg            }
11321ab64890Smrg
11331ab64890Smrg            len = parse_proc(p, token, &db);
11341ab64890Smrg
11351ab64890Smrg	    if (len < 1) {
11361ab64890Smrg		error = 1;
11371ab64890Smrg		break;
11381ab64890Smrg	    }
11391ab64890Smrg	    p += len;
11401ab64890Smrg	}
11411ab64890Smrg    } while (!error);
11421ab64890Smrg
11431ab64890Smrg    if (parse_info.pre_state != S_NULL) {
11441ab64890Smrg	clear_parse_info();
11451ab64890Smrg	error = 1;
11461ab64890Smrg    }
11471ab64890Smrg    if (error) {
11481ab64890Smrg#ifdef	DEBUG
11491ab64890Smrg	fprintf(stderr, "database format error at line %d.\n", line.seq);
11501ab64890Smrg#endif
11511ab64890Smrg	DestroyDatabase(db);
11521ab64890Smrg	db = (Database)NULL;
11531ab64890Smrg    }
11541ab64890Smrg
11551ab64890Smrg    fclose(fd);
11561ab64890Smrg    free_line(&line);
11571ab64890Smrg
11581ab64890Smrg#ifdef	DEBUG
11591ab64890Smrg    PrintDatabase(db);
11601ab64890Smrg#endif
11611ab64890Smrg
11621ab64890Smrg    return db;
11631ab64890Smrg}
11641ab64890Smrg
11651ab64890Smrg/************************************************************************/
11661ab64890Smrg
11671ab64890Smrg#ifndef	NOT_X_ENV
11681ab64890Smrg
11691ab64890Smrg/* locale framework functions */
11701ab64890Smrg
11711ab64890Smrgtypedef struct _XlcDatabaseRec {
11721ab64890Smrg    XrmQuark category_q;
11731ab64890Smrg    XrmQuark name_q;
11741ab64890Smrg    Database db;
11751ab64890Smrg    struct _XlcDatabaseRec *next;
11761ab64890Smrg} XlcDatabaseRec, *XlcDatabase;
11771ab64890Smrg
11781ab64890Smrgtypedef	struct _XlcDatabaseListRec {
11791ab64890Smrg    XrmQuark name_q;
11801ab64890Smrg    XlcDatabase lc_db;
11811ab64890Smrg    Database database;
11821ab64890Smrg    int ref_count;
11831ab64890Smrg    struct _XlcDatabaseListRec *next;
11841ab64890Smrg} XlcDatabaseListRec, *XlcDatabaseList;
11851ab64890Smrg
11861ab64890Smrg/* database cache list (per file) */
11871ab64890Smrgstatic XlcDatabaseList _db_list = (XlcDatabaseList)NULL;
11881ab64890Smrg
11891ab64890Smrg/************************************************************************/
11901ab64890Smrg/*	_XlcGetResource(lcd, category, class, value, count)		*/
11911ab64890Smrg/*----------------------------------------------------------------------*/
11921ab64890Smrg/*	This function retrieves XLocale database information.		*/
11931ab64890Smrg/************************************************************************/
11941ab64890Smrgvoid
11951ab64890Smrg_XlcGetResource(
11961ab64890Smrg    XLCd lcd,
11971ab64890Smrg    const char *category,
11981ab64890Smrg    const char *class,
11991ab64890Smrg    char ***value,
12001ab64890Smrg    int *count)
12011ab64890Smrg{
12021ab64890Smrg    XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd);
12031ab64890Smrg
12041ab64890Smrg    (*methods->get_resource)(lcd, category, class, value, count);
12051ab64890Smrg    return;
12061ab64890Smrg}
12071ab64890Smrg
12081ab64890Smrg/************************************************************************/
12091ab64890Smrg/*	_XlcGetLocaleDataBase(lcd, category, class, value, count)	*/
12101ab64890Smrg/*----------------------------------------------------------------------*/
12111ab64890Smrg/*	This function retrieves XLocale database information.		*/
12121ab64890Smrg/************************************************************************/
12131ab64890Smrgvoid
12141ab64890Smrg_XlcGetLocaleDataBase(
12151ab64890Smrg    XLCd lcd,
12161ab64890Smrg    const char *category,
12171ab64890Smrg    const char *name,
12181ab64890Smrg    char ***value,
12191ab64890Smrg    int *count)
12201ab64890Smrg{
12211ab64890Smrg    XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
12221ab64890Smrg    XrmQuark category_q, name_q;
12231ab64890Smrg
12241ab64890Smrg    category_q = XrmStringToQuark(category);
12251ab64890Smrg    name_q = XrmStringToQuark(name);
12261ab64890Smrg    for (; lc_db->db; ++lc_db) {
12271ab64890Smrg	if (category_q == lc_db->category_q && name_q == lc_db->name_q) {
12281ab64890Smrg	    *value = lc_db->db->value;
12291ab64890Smrg	    *count = lc_db->db->value_num;
12301ab64890Smrg	    return;
12311ab64890Smrg	}
12321ab64890Smrg    }
12331ab64890Smrg    *value = (char **)NULL;
12341ab64890Smrg    *count = 0;
12351ab64890Smrg}
12361ab64890Smrg
12371ab64890Smrg/************************************************************************/
12381ab64890Smrg/*	_XlcDestroyLocaleDataBase(lcd)					*/
12391ab64890Smrg/*----------------------------------------------------------------------*/
12401ab64890Smrg/*	This function destroy the XLocale Database that bound to the 	*/
12411ab64890Smrg/*	specified lcd.  If the XLocale Database is refered from some 	*/
12421ab64890Smrg/*	other lcd, this function just decreases reference count of 	*/
12431ab64890Smrg/*	the database.  If no locale refers the database, this function	*/
12441ab64890Smrg/*	remove it from the cache list and free work area.		*/
12451ab64890Smrg/************************************************************************/
12461ab64890Smrgvoid
12471ab64890Smrg_XlcDestroyLocaleDataBase(
12481ab64890Smrg    XLCd lcd)
12491ab64890Smrg{
12501ab64890Smrg    XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
12511ab64890Smrg    XlcDatabaseList p, prev;
12521ab64890Smrg
12531ab64890Smrg    for (p = _db_list, prev = (XlcDatabaseList)NULL; p;
12541ab64890Smrg	 prev = p, p = p->next) {
12551ab64890Smrg	if (p->lc_db == lc_db) {
12561ab64890Smrg	    if ((-- p->ref_count) < 1) {
12571ab64890Smrg		if (p->lc_db != (XlcDatabase)NULL) {
12581ab64890Smrg		    Xfree((char *)p->lc_db);
12591ab64890Smrg		}
12601ab64890Smrg		DestroyDatabase(p->database);
12611ab64890Smrg		if (prev == (XlcDatabaseList)NULL) {
12621ab64890Smrg		    _db_list = p->next;
12631ab64890Smrg		} else {
12641ab64890Smrg		    prev->next = p->next;
12651ab64890Smrg		}
12661ab64890Smrg		Xfree((char*)p);
12671ab64890Smrg	    }
12681ab64890Smrg	    break;
12691ab64890Smrg	}
12701ab64890Smrg    }
12711ab64890Smrg    XLC_PUBLIC(lcd, xlocale_db) = (XPointer)NULL;
12721ab64890Smrg}
12731ab64890Smrg
12741ab64890Smrg/************************************************************************/
12751ab64890Smrg/*	_XlcCreateLocaleDataBase(lcd)					*/
12761ab64890Smrg/*----------------------------------------------------------------------*/
12771ab64890Smrg/*	This function create an XLocale database which correspond to	*/
12781ab64890Smrg/*	the specified XLCd.						*/
12791ab64890Smrg/************************************************************************/
12801ab64890SmrgXPointer
12811ab64890Smrg_XlcCreateLocaleDataBase(
12821ab64890Smrg    XLCd lcd)
12831ab64890Smrg{
12841ab64890Smrg    XlcDatabaseList list, new;
12851ab64890Smrg    Database p, database = (Database)NULL;
12861ab64890Smrg    XlcDatabase lc_db = (XlcDatabase)NULL;
12871ab64890Smrg    XrmQuark name_q;
12881ab64890Smrg    char *name;
12891ab64890Smrg    int i, n;
12901ab64890Smrg
12911ab64890Smrg    name = _XlcFileName(lcd, "locale");
12921ab64890Smrg    if (name == NULL)
12931ab64890Smrg	return (XPointer)NULL;
12941ab64890Smrg
12951ab64890Smrg#ifndef __UNIXOS2__
12961ab64890Smrg    name_q = XrmStringToQuark(name);
12971ab64890Smrg#else
12981ab64890Smrg    name_q = XrmStringToQuark((char*)__XOS2RedirRoot(name));
12991ab64890Smrg#endif
13001ab64890Smrg    for (list = _db_list; list; list = list->next) {
13011ab64890Smrg	if (name_q == list->name_q) {
13021ab64890Smrg	    list->ref_count++;
13031ab64890Smrg	    Xfree (name);
13041ab64890Smrg	    return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)list->lc_db;
13051ab64890Smrg	}
13061ab64890Smrg    }
13071ab64890Smrg
13081ab64890Smrg    database = CreateDatabase(name);
13091ab64890Smrg    if (database == (Database)NULL) {
13101ab64890Smrg	Xfree (name);
13111ab64890Smrg	return (XPointer)NULL;
13121ab64890Smrg    }
13131ab64890Smrg    n = CountDatabase(database);
13141ab64890Smrg    lc_db = (XlcDatabase)Xmalloc(sizeof(XlcDatabaseRec) * (n + 1));
13151ab64890Smrg    if (lc_db == (XlcDatabase)NULL)
13161ab64890Smrg	goto err;
13171ab64890Smrg    bzero(lc_db, sizeof(XlcDatabaseRec) * (n + 1));
13181ab64890Smrg    for (p = database, i = 0; p && i < n; p = p->next, ++i) {
13191ab64890Smrg	lc_db[i].category_q = XrmStringToQuark(p->category);
13201ab64890Smrg	lc_db[i].name_q = XrmStringToQuark(p->name);
13211ab64890Smrg	lc_db[i].db = p;
13221ab64890Smrg    }
13231ab64890Smrg
13241ab64890Smrg    new = (XlcDatabaseList)Xmalloc(sizeof(XlcDatabaseListRec));
13251ab64890Smrg    if (new == (XlcDatabaseList)NULL) {
13261ab64890Smrg	goto err;
13271ab64890Smrg    }
13281ab64890Smrg    new->name_q = name_q;
13291ab64890Smrg    new->lc_db = lc_db;
13301ab64890Smrg    new->database = database;
13311ab64890Smrg    new->ref_count = 1;
13321ab64890Smrg    new->next = _db_list;
13331ab64890Smrg    _db_list = new;
13341ab64890Smrg
13351ab64890Smrg    Xfree (name);
13361ab64890Smrg    return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)lc_db;
13371ab64890Smrg
13381ab64890Smrg err:
13391ab64890Smrg    DestroyDatabase(database);
13401ab64890Smrg    if (lc_db != (XlcDatabase)NULL) {
13411ab64890Smrg	Xfree((char *)lc_db);
13421ab64890Smrg    }
13431ab64890Smrg    Xfree (name);
13441ab64890Smrg    return (XPointer)NULL;
13451ab64890Smrg}
13461ab64890Smrg
13471ab64890Smrg#endif	/* NOT_X_ENV */
1348