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, "ed); /* 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