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