lcDB.c revision 9c019ec5
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" 42258a0ebeSmrg#include "reallocarray.h" 431ab64890Smrg 441ab64890Smrg#else /* NOT_X_ENV */ 451ab64890Smrg 461ab64890Smrg#define Xmalloc malloc 471ab64890Smrg#define Xrealloc realloc 481ab64890Smrg#define Xfree free 491ab64890Smrg 501ab64890Smrg#endif /* NOT_X_ENV */ 511ab64890Smrg 521ab64890Smrg/* specifying NOT_X_ENV allows users to just use 531ab64890Smrg the database parsing routine. */ 541ab64890Smrg/* For UDC/VW */ 551ab64890Smrg#ifndef BUFSIZE 561ab64890Smrg#define BUFSIZE 2048 571ab64890Smrg#endif 581ab64890Smrg 591ab64890Smrg#ifdef COMMENT 601ab64890Smrg#ifdef BUFSIZE 611ab64890Smrg#undef BUFSIZE 621ab64890Smrg#endif 631ab64890Smrg#define BUFSIZE 6144 /* 2048*3 */ 641ab64890Smrg#endif 651ab64890Smrg 661ab64890Smrg#include <stdio.h> 671ab64890Smrg 681ab64890Smrgtypedef struct _DatabaseRec { 691ab64890Smrg char *category; 701ab64890Smrg char *name; 711ab64890Smrg char **value; 721ab64890Smrg int value_num; 731ab64890Smrg struct _DatabaseRec *next; 741ab64890Smrg} DatabaseRec, *Database; 751ab64890Smrg 761ab64890Smrgtypedef enum { 771ab64890Smrg S_NULL, /* outside category */ 781ab64890Smrg S_CATEGORY, /* inside category */ 791ab64890Smrg S_NAME, /* has name, expecting values */ 801ab64890Smrg S_VALUE 811ab64890Smrg} ParseState; 821ab64890Smrg 831ab64890Smrgtypedef enum { 841ab64890Smrg T_NEWLINE, 851ab64890Smrg T_COMMENT, 861ab64890Smrg T_SEMICOLON, 871ab64890Smrg T_DOUBLE_QUOTE, 881ab64890Smrg T_LEFT_BRACE, 891ab64890Smrg T_RIGHT_BRACE, 901ab64890Smrg T_SPACE, 911ab64890Smrg T_TAB, 921ab64890Smrg T_BACKSLASH, 931ab64890Smrg T_NUMERIC_HEX, 941ab64890Smrg T_NUMERIC_DEC, 951ab64890Smrg T_NUMERIC_OCT, 961ab64890Smrg T_DEFAULT 971ab64890Smrg} Token; 981ab64890Smrg 991ab64890Smrgtypedef struct { 1001ab64890Smrg Token token; /* token id */ 1011ab64890Smrg int len; /* length of token sequence */ 1021ab64890Smrg} TokenTable; 1031ab64890Smrg 1041ab64890Smrgstatic int f_newline (const char *str, Token token, Database *db); 1051ab64890Smrgstatic int f_comment (const char *str, Token token, Database *db); 1061ab64890Smrgstatic int f_semicolon (const char *str, Token token, Database *db); 1071ab64890Smrgstatic int f_double_quote (const char *str, Token token, Database *db); 1081ab64890Smrgstatic int f_left_brace (const char *str, Token token, Database *db); 1091ab64890Smrgstatic int f_right_brace (const char *str, Token token, Database *db); 1101ab64890Smrgstatic int f_white (const char *str, Token token, Database *db); 1111ab64890Smrgstatic int f_backslash (const char *str, Token token, Database *db); 1121ab64890Smrgstatic int f_numeric (const char *str, Token token, Database *db); 1131ab64890Smrgstatic int f_default (const char *str, Token token, Database *db); 1141ab64890Smrg 1151ab64890Smrgstatic const TokenTable token_tbl[] = { 1161ab64890Smrg { T_NEWLINE, 1 }, 1171ab64890Smrg { T_COMMENT, 1 }, 1181ab64890Smrg { T_SEMICOLON, 1 }, 1191ab64890Smrg { T_DOUBLE_QUOTE, 1 }, 1201ab64890Smrg { T_LEFT_BRACE, 1 }, 1211ab64890Smrg { T_RIGHT_BRACE, 1 }, 1221ab64890Smrg { T_SPACE, 1 }, 1231ab64890Smrg { T_TAB, 1 }, 1241ab64890Smrg { T_BACKSLASH, 1 }, 1251ab64890Smrg { T_NUMERIC_HEX, 2 }, 1261ab64890Smrg { T_NUMERIC_DEC, 2 }, 1271ab64890Smrg { T_NUMERIC_OCT, 2 }, 1281ab64890Smrg { T_DEFAULT, 1 } /* any character */ 1291ab64890Smrg}; 1301ab64890Smrg 1311ab64890Smrg#define SYM_CR '\r' 1321ab64890Smrg#define SYM_NEWLINE '\n' 1331ab64890Smrg#define SYM_COMMENT '#' 1341ab64890Smrg#define SYM_SEMICOLON ';' 1351ab64890Smrg#define SYM_DOUBLE_QUOTE '"' 1361ab64890Smrg#define SYM_LEFT_BRACE '{' 1371ab64890Smrg#define SYM_RIGHT_BRACE '}' 1381ab64890Smrg#define SYM_SPACE ' ' 1391ab64890Smrg#define SYM_TAB '\t' 1401ab64890Smrg#define SYM_BACKSLASH '\\' 1411ab64890Smrg 1421ab64890Smrg/************************************************************************/ 1431ab64890Smrg 1441ab64890Smrg#define MAX_NAME_NEST 64 1451ab64890Smrg 1461ab64890Smrgtypedef struct { 1471ab64890Smrg ParseState pre_state; 1481ab64890Smrg char *category; 1491ab64890Smrg char *name[MAX_NAME_NEST]; 1501ab64890Smrg int nest_depth; 1511ab64890Smrg char **value; 1521ab64890Smrg int value_len; 1531ab64890Smrg int value_num; 1541ab64890Smrg int bufsize; /* bufMaxSize >= bufsize >= 0 */ 1551ab64890Smrg int bufMaxSize; /* default : BUFSIZE */ 1561ab64890Smrg char *buf; 1571ab64890Smrg} DBParseInfo; 1581ab64890Smrg 1591ab64890Smrgstatic DBParseInfo parse_info; 1601ab64890Smrg 1611ab64890Smrgstatic void 1621ab64890Smrginit_parse_info (void) 1631ab64890Smrg{ 1641ab64890Smrg static int allocated /* = 0 */; 1651ab64890Smrg char *ptr; 1661ab64890Smrg int size; 1671ab64890Smrg if (!allocated) { 1681ab64890Smrg bzero(&parse_info, sizeof(DBParseInfo)); 169818534a1Smrg parse_info.buf = Xmalloc(BUFSIZE); 1701ab64890Smrg parse_info.bufMaxSize = BUFSIZE; 1711ab64890Smrg allocated = 1; 1721ab64890Smrg return; 1731ab64890Smrg } 1741ab64890Smrg ptr = parse_info.buf; 1751ab64890Smrg size = parse_info.bufMaxSize; 1761ab64890Smrg bzero(&parse_info, sizeof(DBParseInfo)); 1771ab64890Smrg parse_info.buf = ptr; 1781ab64890Smrg parse_info.bufMaxSize = size; 1791ab64890Smrg} 1801ab64890Smrg 1811ab64890Smrgstatic void 1821ab64890Smrgclear_parse_info (void) 1831ab64890Smrg{ 1841ab64890Smrg int i; 1851ab64890Smrg char *ptr; 1861ab64890Smrg int size; 1871ab64890Smrg parse_info.pre_state = S_NULL; 1881ab64890Smrg if (parse_info.category != NULL) { 1891ab64890Smrg Xfree(parse_info.category); 1901ab64890Smrg } 1911ab64890Smrg for (i = 0; i <= parse_info.nest_depth; ++i) { 1921ab64890Smrg if (parse_info.name[i]) { 1931ab64890Smrg Xfree(parse_info.name[i]); 1941ab64890Smrg } 1951ab64890Smrg } 1961ab64890Smrg if (parse_info.value) { 1971ab64890Smrg if (*parse_info.value) { 1981ab64890Smrg Xfree(*parse_info.value); 1991ab64890Smrg } 200818534a1Smrg Xfree(parse_info.value); 2011ab64890Smrg } 2021ab64890Smrg ptr = parse_info.buf; 2031ab64890Smrg size = parse_info.bufMaxSize; 2041ab64890Smrg bzero(&parse_info, sizeof(DBParseInfo)); 2051ab64890Smrg parse_info.buf = ptr; 2061ab64890Smrg parse_info.bufMaxSize = size; 2071ab64890Smrg} 2081ab64890Smrg 2091ab64890Smrgstatic Bool 2101ab64890Smrgrealloc_parse_info( 2111ab64890Smrg int len) 2121ab64890Smrg{ 2131ab64890Smrg char *p; 214818534a1Smrg int newsize = BUFSIZE * ((parse_info.bufsize + len)/BUFSIZE + 1); 2151ab64890Smrg 216818534a1Smrg p = Xrealloc(parse_info.buf, newsize); 2171ab64890Smrg if (p == NULL) 2181ab64890Smrg return False; 219818534a1Smrg parse_info.bufMaxSize = newsize; 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) { 252818534a1Smrg str = Xrealloc(str, size); 2531ab64890Smrg } else { 254818534a1Smrg str = 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))) { 2989c019ec5Smaya int len = (int) 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 */ 3309c019ec5Smaya len = (int) 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 } 3449c019ec5Smaya strncpy(str + cur, p, (size_t) 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 } 4269c019ec5Smaya strncpy(w, p, (size_t) 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 } 4619c019ec5Smaya strncpy(w, p, (size_t) 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) { 490818534a1Smrg value_list = Xmalloc(sizeof(char *) * 2); 4911ab64890Smrg *value_list = NULL; 4921ab64890Smrg } else { 4931ab64890Smrg char **prev_list = value_list; 4941ab64890Smrg 4951ab64890Smrg value_list = (char **) 496258a0ebeSmrg Xreallocarray(value_list, value_num + 2, sizeof(char *)); 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) { 506818534a1Smrg value = Xmalloc(value_len + len + 1); 5071ab64890Smrg } else { 5081ab64890Smrg char *prev_value = value; 5091ab64890Smrg 510818534a1Smrg value = 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; 5309c019ec5Smaya strncpy(p, str, (size_t) 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 55461b2299dSmrgstatic 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) { 5649c019ec5Smaya len = (int) ((size_t) 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 5966cc2b21fSmrg new = Xcalloc(1, sizeof(DatabaseRec)); 5971ab64890Smrg if (new == (Database)NULL) { 5981ab64890Smrg goto err; 5991ab64890Smrg } 6001ab64890Smrg 6016cc2b21fSmrg new->category = strdup(parse_info.category); 6021ab64890Smrg if (new->category == NULL) { 6031ab64890Smrg goto err; 6041ab64890Smrg } 6051ab64890Smrg 6061ab64890Smrg if (! construct_name(name, sizeof(name))) { 6071ab64890Smrg goto err; 6081ab64890Smrg } 6096cc2b21fSmrg new->name = strdup(name); 6101ab64890Smrg if (new->name == NULL) { 6111ab64890Smrg goto err; 6121ab64890Smrg } 6131ab64890Smrg new->next = *db; 6141ab64890Smrg new->value = parse_info.value; 6151ab64890Smrg new->value_num = parse_info.value_num; 6161ab64890Smrg *db = new; 6171ab64890Smrg 6181ab64890Smrg Xfree(parse_info.name[parse_info.nest_depth]); 6191ab64890Smrg parse_info.name[parse_info.nest_depth] = NULL; 6201ab64890Smrg 6211ab64890Smrg parse_info.value = (char **)NULL; 6221ab64890Smrg parse_info.value_num = 0; 6231ab64890Smrg parse_info.value_len = 0; 6241ab64890Smrg 6251ab64890Smrg return 1; 6261ab64890Smrg 6271ab64890Smrg err: 6281ab64890Smrg if (new) { 6291ab64890Smrg if (new->category) { 6301ab64890Smrg Xfree(new->category); 6311ab64890Smrg } 6321ab64890Smrg if (new->name) { 6331ab64890Smrg Xfree(new->name); 6341ab64890Smrg } 6351ab64890Smrg Xfree(new); 6361ab64890Smrg } 6371ab64890Smrg if (parse_info.value) { 6381ab64890Smrg if (*parse_info.value) { 6391ab64890Smrg Xfree(*parse_info.value); 6401ab64890Smrg } 6411ab64890Smrg Xfree((char **)parse_info.value); 6421ab64890Smrg parse_info.value = (char **)NULL; 6431ab64890Smrg parse_info.value_num = 0; 6441ab64890Smrg parse_info.value_len = 0; 6451ab64890Smrg } 6461ab64890Smrg return 0; 6471ab64890Smrg} 6481ab64890Smrg 6491ab64890Smrg#define END_MARK "END" 6501ab64890Smrg#define END_MARK_LEN 3 /*strlen(END_MARK)*/ 6511ab64890Smrg 6521ab64890Smrgstatic int 6531ab64890Smrgcheck_category_end( 6541ab64890Smrg const char *str) 6551ab64890Smrg{ 6561ab64890Smrg const char *p; 6571ab64890Smrg int len; 6581ab64890Smrg 6591ab64890Smrg p = str; 6601ab64890Smrg if (strncmp(p, END_MARK, END_MARK_LEN)) { 6611ab64890Smrg return 0; 6621ab64890Smrg } 6631ab64890Smrg p += END_MARK_LEN; 6641ab64890Smrg 6651ab64890Smrg while (iswhite(*p)) { 6661ab64890Smrg ++p; 6671ab64890Smrg } 6689c019ec5Smaya len = (int) strlen(parse_info.category); 6699c019ec5Smaya if (strncmp(p, parse_info.category, (size_t) len)) { 6701ab64890Smrg return 0; 6711ab64890Smrg } 6721ab64890Smrg p += len; 6731ab64890Smrg return p - str; 6741ab64890Smrg} 6751ab64890Smrg 6761ab64890Smrg/************************************************************************/ 6771ab64890Smrg 6781ab64890Smrgstatic int 6791ab64890Smrgf_newline( 6801ab64890Smrg const char *str, 6811ab64890Smrg Token token, 6821ab64890Smrg Database *db) 6831ab64890Smrg{ 6841ab64890Smrg switch (parse_info.pre_state) { 6851ab64890Smrg case S_NULL: 6861ab64890Smrg case S_CATEGORY: 6871ab64890Smrg break; 6881ab64890Smrg case S_NAME: 6891ab64890Smrg return 0; /* no value */ 6901ab64890Smrg case S_VALUE: 6911ab64890Smrg if (!store_to_database(db)) 6921ab64890Smrg return 0; 6931ab64890Smrg parse_info.pre_state = S_CATEGORY; 6941ab64890Smrg break; 6951ab64890Smrg default: 6961ab64890Smrg return 0; 6971ab64890Smrg } 6981ab64890Smrg return token_tbl[token].len; 6991ab64890Smrg} 7001ab64890Smrg 7011ab64890Smrgstatic int 7021ab64890Smrgf_comment( 7031ab64890Smrg const char *str, 7041ab64890Smrg Token token, 7051ab64890Smrg Database *db) 7061ab64890Smrg{ 7071ab64890Smrg /* NOTE: comment is already handled in read_line(), 7081ab64890Smrg so this function is not necessary. */ 7091ab64890Smrg 7101ab64890Smrg const char *p = str; 7111ab64890Smrg 7121ab64890Smrg while (*p != SYM_NEWLINE && *p != SYM_CR && *p != '\0') { 7131ab64890Smrg ++p; /* zap to the end of line */ 7141ab64890Smrg } 7151ab64890Smrg return p - str; 7161ab64890Smrg} 7171ab64890Smrg 7181ab64890Smrgstatic int 7191ab64890Smrgf_white( 7201ab64890Smrg const char *str, 7211ab64890Smrg Token token, 7221ab64890Smrg Database *db) 7231ab64890Smrg{ 7241ab64890Smrg const char *p = str; 7251ab64890Smrg 7261ab64890Smrg while (iswhite(*p)) { 7271ab64890Smrg ++p; 7281ab64890Smrg } 7291ab64890Smrg return p - str; 7301ab64890Smrg} 7311ab64890Smrg 7321ab64890Smrgstatic int 7331ab64890Smrgf_semicolon( 7341ab64890Smrg const char *str, 7351ab64890Smrg Token token, 7361ab64890Smrg Database *db) 7371ab64890Smrg{ 7381ab64890Smrg switch (parse_info.pre_state) { 7391ab64890Smrg case S_NULL: 7401ab64890Smrg case S_CATEGORY: 7411ab64890Smrg case S_NAME: 7421ab64890Smrg return 0; 7431ab64890Smrg case S_VALUE: 7441ab64890Smrg if (! append_value_list()) 7451ab64890Smrg return 0; 7461ab64890Smrg parse_info.pre_state = S_VALUE; 7471ab64890Smrg break; 7481ab64890Smrg default: 7491ab64890Smrg return 0; 7501ab64890Smrg } 7511ab64890Smrg return token_tbl[token].len; 7521ab64890Smrg} 7531ab64890Smrg 7541ab64890Smrgstatic int 7551ab64890Smrgf_left_brace( 7561ab64890Smrg const char *str, 7571ab64890Smrg Token token, 7581ab64890Smrg Database *db) 7591ab64890Smrg{ 7601ab64890Smrg switch (parse_info.pre_state) { 7611ab64890Smrg case S_NULL: 7621ab64890Smrg case S_CATEGORY: 7631ab64890Smrg case S_VALUE: 7641ab64890Smrg return 0; 7651ab64890Smrg case S_NAME: 7661ab64890Smrg if (parse_info.name[parse_info.nest_depth] == NULL 7671ab64890Smrg || parse_info.nest_depth + 1 > MAX_NAME_NEST) 7681ab64890Smrg return 0; 7691ab64890Smrg ++parse_info.nest_depth; 7701ab64890Smrg parse_info.pre_state = S_CATEGORY; 7711ab64890Smrg break; 7721ab64890Smrg default: 7731ab64890Smrg return 0; 7741ab64890Smrg } 7751ab64890Smrg return token_tbl[token].len; 7761ab64890Smrg} 7771ab64890Smrg 7781ab64890Smrgstatic int 7791ab64890Smrgf_right_brace( 7801ab64890Smrg const char *str, 7811ab64890Smrg Token token, 7821ab64890Smrg Database *db) 7831ab64890Smrg{ 7841ab64890Smrg if (parse_info.nest_depth < 1) 7851ab64890Smrg return 0; 7861ab64890Smrg 7871ab64890Smrg switch (parse_info.pre_state) { 7881ab64890Smrg case S_NULL: 7891ab64890Smrg case S_NAME: 7901ab64890Smrg return 0; 7911ab64890Smrg case S_VALUE: 7921ab64890Smrg if (! store_to_database(db)) 7931ab64890Smrg return 0; 7943233502eSmrg /* fall through - to next case */ 7951ab64890Smrg case S_CATEGORY: 7961ab64890Smrg if (parse_info.name[parse_info.nest_depth] != NULL) { 7971ab64890Smrg Xfree(parse_info.name[parse_info.nest_depth]); 7981ab64890Smrg parse_info.name[parse_info.nest_depth] = NULL; 7991ab64890Smrg } 8001ab64890Smrg --parse_info.nest_depth; 8011ab64890Smrg parse_info.pre_state = S_CATEGORY; 8021ab64890Smrg break; 8031ab64890Smrg default: 8041ab64890Smrg return 0; 8051ab64890Smrg } 8061ab64890Smrg return token_tbl[token].len; 8071ab64890Smrg} 8081ab64890Smrg 8091ab64890Smrgstatic int 8101ab64890Smrgf_double_quote( 8111ab64890Smrg const char *str, 8121ab64890Smrg Token token, 8131ab64890Smrg Database *db) 8141ab64890Smrg{ 8151ab64890Smrg char word[BUFSIZE]; 8161ab64890Smrg char* wordp; 8171ab64890Smrg int len; 8181ab64890Smrg 8199c019ec5Smaya if ((len = (int) strlen (str)) < sizeof word) 8201ab64890Smrg wordp = word; 8211ab64890Smrg else 8221ab64890Smrg wordp = Xmalloc (len + 1); 8231ab64890Smrg if (wordp == NULL) 8241ab64890Smrg return 0; 8251ab64890Smrg 8261ab64890Smrg len = 0; 8271ab64890Smrg switch (parse_info.pre_state) { 8281ab64890Smrg case S_NULL: 8291ab64890Smrg case S_CATEGORY: 8301ab64890Smrg goto err; 8311ab64890Smrg case S_NAME: 8321ab64890Smrg case S_VALUE: 8331ab64890Smrg len = get_quoted_word(str, wordp); 8341ab64890Smrg if (len < 1) 8351ab64890Smrg goto err; 83661b2299dSmrg if ((parse_info.bufsize + (int)strlen(wordp) + 1) 8371ab64890Smrg >= parse_info.bufMaxSize) { 8389c019ec5Smaya if (realloc_parse_info((int) strlen(wordp)+1) == False) { 8391ab64890Smrg goto err; 8401ab64890Smrg } 8411ab64890Smrg } 8421ab64890Smrg strcpy(&parse_info.buf[parse_info.bufsize], wordp); 8439c019ec5Smaya parse_info.bufsize = (int) ((size_t) parse_info.bufsize + strlen(wordp)); 8441ab64890Smrg parse_info.pre_state = S_VALUE; 8451ab64890Smrg break; 8461ab64890Smrg default: 8471ab64890Smrg goto err; 8481ab64890Smrg } 8491ab64890Smrg if (wordp != word) 8501ab64890Smrg Xfree (wordp); 8511ab64890Smrg return len; /* including length of token */ 8521ab64890Smrg 8531ab64890Smrgerr: 8541ab64890Smrg if (wordp != word) 8551ab64890Smrg Xfree (wordp); 8561ab64890Smrg return 0; 8571ab64890Smrg} 8581ab64890Smrg 8591ab64890Smrgstatic int 8601ab64890Smrgf_backslash( 8611ab64890Smrg const char *str, 8621ab64890Smrg Token token, 8631ab64890Smrg Database *db) 8641ab64890Smrg{ 8651ab64890Smrg return f_default(str, token, db); 8661ab64890Smrg} 8671ab64890Smrg 8681ab64890Smrgstatic int 8691ab64890Smrgf_numeric( 8701ab64890Smrg const char *str, 8711ab64890Smrg Token token, 8721ab64890Smrg Database *db) 8731ab64890Smrg{ 8741ab64890Smrg char word[BUFSIZE]; 8751ab64890Smrg const char *p; 8761ab64890Smrg char* wordp; 8771ab64890Smrg int len; 8781ab64890Smrg int token_len; 8791ab64890Smrg 8809c019ec5Smaya if ((len = (int) strlen (str)) < sizeof word) 8811ab64890Smrg wordp = word; 8821ab64890Smrg else 8831ab64890Smrg wordp = Xmalloc (len + 1); 8841ab64890Smrg if (wordp == NULL) 8851ab64890Smrg return 0; 8861ab64890Smrg 8871ab64890Smrg switch (parse_info.pre_state) { 8881ab64890Smrg case S_NULL: 8891ab64890Smrg case S_CATEGORY: 8901ab64890Smrg goto err; 8911ab64890Smrg case S_NAME: 8921ab64890Smrg case S_VALUE: 8931ab64890Smrg token_len = token_tbl[token].len; 8941ab64890Smrg p = str + token_len; 8951ab64890Smrg len = get_word(p, wordp); 8961ab64890Smrg if (len < 1) 8971ab64890Smrg goto err; 89861b2299dSmrg if ((parse_info.bufsize + token_len + (int)strlen(wordp) + 1) 8991ab64890Smrg >= parse_info.bufMaxSize) { 9009c019ec5Smaya if (realloc_parse_info((int)((size_t) token_len + strlen(wordp) + 1)) == False) 9011ab64890Smrg goto err; 9021ab64890Smrg } 9039c019ec5Smaya strncpy(&parse_info.buf[parse_info.bufsize], str, (size_t) token_len); 9041ab64890Smrg strcpy(&parse_info.buf[parse_info.bufsize + token_len], wordp); 9059c019ec5Smaya parse_info.bufsize = (int) ((size_t) parse_info.bufsize + ((size_t) token_len + strlen(wordp))); 9061ab64890Smrg parse_info.pre_state = S_VALUE; 9071ab64890Smrg break; 9081ab64890Smrg default: 9091ab64890Smrg goto err; 9101ab64890Smrg } 9111ab64890Smrg if (wordp != word) 9121ab64890Smrg Xfree (wordp); 9131ab64890Smrg return len + token_len; 9141ab64890Smrg 9151ab64890Smrgerr: 9161ab64890Smrg if (wordp != word) 9171ab64890Smrg Xfree (wordp); 9181ab64890Smrg return 0; 9191ab64890Smrg} 9201ab64890Smrg 9211ab64890Smrgstatic int 9221ab64890Smrgf_default( 9231ab64890Smrg const char *str, 9241ab64890Smrg Token token, 9251ab64890Smrg Database *db) 9261ab64890Smrg{ 9271ab64890Smrg char word[BUFSIZE], *p; 9281ab64890Smrg char* wordp; 9291ab64890Smrg int len; 9301ab64890Smrg 9319c019ec5Smaya if ((len = (int) strlen (str)) < sizeof word) 9321ab64890Smrg wordp = word; 9331ab64890Smrg else 9341ab64890Smrg wordp = Xmalloc (len + 1); 9351ab64890Smrg if (wordp == NULL) 9361ab64890Smrg return 0; 9371ab64890Smrg 9381ab64890Smrg len = get_word(str, wordp); 9391ab64890Smrg if (len < 1) 9401ab64890Smrg goto err; 9411ab64890Smrg 9421ab64890Smrg switch (parse_info.pre_state) { 9431ab64890Smrg case S_NULL: 9441ab64890Smrg if (parse_info.category != NULL) 9451ab64890Smrg goto err; 9466cc2b21fSmrg p = strdup(wordp); 9471ab64890Smrg if (p == NULL) 9481ab64890Smrg goto err; 9491ab64890Smrg parse_info.category = p; 9501ab64890Smrg parse_info.pre_state = S_CATEGORY; 9511ab64890Smrg break; 9521ab64890Smrg case S_CATEGORY: 9531ab64890Smrg if (parse_info.nest_depth == 0) { 9541ab64890Smrg if (check_category_end(str)) { 9551ab64890Smrg /* end of category is detected. 9561ab64890Smrg clear context and zap to end of this line */ 9571ab64890Smrg clear_parse_info(); 9589c019ec5Smaya len = (int) strlen(str); 9591ab64890Smrg break; 9601ab64890Smrg } 9611ab64890Smrg } 9626cc2b21fSmrg p = strdup(wordp); 9631ab64890Smrg if (p == NULL) 9641ab64890Smrg goto err; 9651ab64890Smrg if (parse_info.name[parse_info.nest_depth] != NULL) { 9661ab64890Smrg Xfree(parse_info.name[parse_info.nest_depth]); 9671ab64890Smrg } 9681ab64890Smrg parse_info.name[parse_info.nest_depth] = p; 9691ab64890Smrg parse_info.pre_state = S_NAME; 9701ab64890Smrg break; 9711ab64890Smrg case S_NAME: 9721ab64890Smrg case S_VALUE: 97361b2299dSmrg if ((parse_info.bufsize + (int)strlen(wordp) + 1) 9741ab64890Smrg >= parse_info.bufMaxSize) { 9759c019ec5Smaya if (realloc_parse_info((int) strlen(wordp) + 1) == False) 9761ab64890Smrg goto err; 9771ab64890Smrg } 9781ab64890Smrg strcpy(&parse_info.buf[parse_info.bufsize], wordp); 9799c019ec5Smaya parse_info.bufsize = (int) ((size_t) parse_info.bufsize + strlen(wordp)); 9801ab64890Smrg parse_info.pre_state = S_VALUE; 9811ab64890Smrg break; 9821ab64890Smrg default: 9831ab64890Smrg goto err; 9841ab64890Smrg } 9851ab64890Smrg if (wordp != word) 9861ab64890Smrg Xfree (wordp); 9871ab64890Smrg return len; 9881ab64890Smrg 9891ab64890Smrgerr: 9901ab64890Smrg if (wordp != word) 9911ab64890Smrg Xfree (wordp); 9921ab64890Smrg return 0; 9931ab64890Smrg} 9941ab64890Smrg 9951ab64890Smrg/************************************************************************/ 9961ab64890Smrg 9971ab64890Smrg#ifdef DEBUG 9981ab64890Smrgstatic void 9991ab64890SmrgPrintDatabase( 10001ab64890Smrg Database db) 10011ab64890Smrg{ 10021ab64890Smrg Database p = db; 10031ab64890Smrg int i = 0, j; 10041ab64890Smrg 10051ab64890Smrg printf("***\n*** BEGIN Database\n***\n"); 10061ab64890Smrg while (p) { 10071ab64890Smrg printf("%3d: ", i++); 10081ab64890Smrg printf("%s, %s, ", p->category, p->name); 10091ab64890Smrg printf("\t[%d: ", p->value_num); 10101ab64890Smrg for (j = 0; j < p->value_num; ++j) { 10111ab64890Smrg printf("%s, ", p->value[j]); 10121ab64890Smrg } 10131ab64890Smrg printf("]\n"); 10141ab64890Smrg p = p->next; 10151ab64890Smrg } 10161ab64890Smrg printf("***\n*** END Database\n***\n"); 10171ab64890Smrg} 10181ab64890Smrg#endif 10191ab64890Smrg 10201ab64890Smrgstatic void 10211ab64890SmrgDestroyDatabase( 10221ab64890Smrg Database db) 10231ab64890Smrg{ 10241ab64890Smrg Database p = db; 10251ab64890Smrg 10261ab64890Smrg while (p) { 10271ab64890Smrg if (p->category != NULL) { 10281ab64890Smrg Xfree(p->category); 10291ab64890Smrg } 10301ab64890Smrg if (p->name != NULL) { 10311ab64890Smrg Xfree(p->name); 10321ab64890Smrg } 10331ab64890Smrg if (p->value != (char **)NULL) { 10341ab64890Smrg if (*p->value != NULL) { 10351ab64890Smrg Xfree(*p->value); 10361ab64890Smrg } 1037818534a1Smrg Xfree(p->value); 10381ab64890Smrg } 10391ab64890Smrg db = p->next; 1040818534a1Smrg Xfree(p); 10411ab64890Smrg p = db; 10421ab64890Smrg } 10431ab64890Smrg} 10441ab64890Smrg 10451ab64890Smrgstatic int 10461ab64890SmrgCountDatabase( 10471ab64890Smrg Database db) 10481ab64890Smrg{ 10491ab64890Smrg Database p = db; 10501ab64890Smrg int cnt = 0; 10511ab64890Smrg 10521ab64890Smrg while (p) { 10531ab64890Smrg ++cnt; 10541ab64890Smrg p = p->next; 10551ab64890Smrg } 10561ab64890Smrg return cnt; 10571ab64890Smrg} 10581ab64890Smrg 10591ab64890Smrgstatic Database 10601ab64890SmrgCreateDatabase( 10611ab64890Smrg char *dbfile) 10621ab64890Smrg{ 10631ab64890Smrg Database db = (Database)NULL; 10641ab64890Smrg FILE *fd; 10651ab64890Smrg Line line; 10661ab64890Smrg char *p; 10671ab64890Smrg Token token; 10681ab64890Smrg int len; 10691ab64890Smrg int error = 0; 10701ab64890Smrg 10711ab64890Smrg fd = _XFopenFile(dbfile, "r"); 10721ab64890Smrg if (fd == (FILE *)NULL) 10731ab64890Smrg return NULL; 10741ab64890Smrg 10751ab64890Smrg bzero(&line, sizeof(Line)); 10761ab64890Smrg init_parse_info(); 10771ab64890Smrg 10781ab64890Smrg do { 10791ab64890Smrg int rc = read_line(fd, &line); 10801ab64890Smrg if (rc < 0) { 10811ab64890Smrg error = 1; 10821ab64890Smrg break; 10831ab64890Smrg } else if (rc == 0) { 10841ab64890Smrg break; 10851ab64890Smrg } 10861ab64890Smrg p = line.str; 10871ab64890Smrg while (*p) { 10881ab64890Smrg int (*parse_proc)(const char *str, Token token, Database *db) = NULL; 10891ab64890Smrg 10901ab64890Smrg token = get_token(p); 10911ab64890Smrg 10921ab64890Smrg switch (token_tbl[token].token) { 10931ab64890Smrg case T_NEWLINE: 10941ab64890Smrg parse_proc = f_newline; 10951ab64890Smrg break; 10961ab64890Smrg case T_COMMENT: 10971ab64890Smrg parse_proc = f_comment; 10981ab64890Smrg break; 10991ab64890Smrg case T_SEMICOLON: 11001ab64890Smrg parse_proc = f_semicolon; 11011ab64890Smrg break; 11021ab64890Smrg case T_DOUBLE_QUOTE: 11031ab64890Smrg parse_proc = f_double_quote; 11041ab64890Smrg break; 11051ab64890Smrg case T_LEFT_BRACE: 11061ab64890Smrg parse_proc = f_left_brace; 11071ab64890Smrg break; 11081ab64890Smrg case T_RIGHT_BRACE: 11091ab64890Smrg parse_proc = f_right_brace; 11101ab64890Smrg break; 11111ab64890Smrg case T_SPACE: 11121ab64890Smrg case T_TAB: 11131ab64890Smrg parse_proc = f_white; 11141ab64890Smrg break; 11151ab64890Smrg case T_BACKSLASH: 11161ab64890Smrg parse_proc = f_backslash; 11171ab64890Smrg break; 11181ab64890Smrg case T_NUMERIC_HEX: 11191ab64890Smrg case T_NUMERIC_DEC: 11201ab64890Smrg case T_NUMERIC_OCT: 11211ab64890Smrg parse_proc = f_numeric; 11221ab64890Smrg break; 11231ab64890Smrg case T_DEFAULT: 11241ab64890Smrg parse_proc = f_default; 11251ab64890Smrg break; 11261ab64890Smrg } 11271ab64890Smrg 11281ab64890Smrg len = parse_proc(p, token, &db); 11291ab64890Smrg 11301ab64890Smrg if (len < 1) { 11311ab64890Smrg error = 1; 11321ab64890Smrg break; 11331ab64890Smrg } 11341ab64890Smrg p += len; 11351ab64890Smrg } 11361ab64890Smrg } while (!error); 11371ab64890Smrg 11381ab64890Smrg if (parse_info.pre_state != S_NULL) { 11391ab64890Smrg clear_parse_info(); 11401ab64890Smrg error = 1; 11411ab64890Smrg } 11421ab64890Smrg if (error) { 11431ab64890Smrg#ifdef DEBUG 11441ab64890Smrg fprintf(stderr, "database format error at line %d.\n", line.seq); 11451ab64890Smrg#endif 11461ab64890Smrg DestroyDatabase(db); 11471ab64890Smrg db = (Database)NULL; 11481ab64890Smrg } 11491ab64890Smrg 11501ab64890Smrg fclose(fd); 11511ab64890Smrg free_line(&line); 11521ab64890Smrg 11531ab64890Smrg#ifdef DEBUG 11541ab64890Smrg PrintDatabase(db); 11551ab64890Smrg#endif 11561ab64890Smrg 11571ab64890Smrg return db; 11581ab64890Smrg} 11591ab64890Smrg 11601ab64890Smrg/************************************************************************/ 11611ab64890Smrg 11621ab64890Smrg#ifndef NOT_X_ENV 11631ab64890Smrg 11641ab64890Smrg/* locale framework functions */ 11651ab64890Smrg 11661ab64890Smrgtypedef struct _XlcDatabaseRec { 11671ab64890Smrg XrmQuark category_q; 11681ab64890Smrg XrmQuark name_q; 11691ab64890Smrg Database db; 11701ab64890Smrg struct _XlcDatabaseRec *next; 11711ab64890Smrg} XlcDatabaseRec, *XlcDatabase; 11721ab64890Smrg 11731ab64890Smrgtypedef struct _XlcDatabaseListRec { 11741ab64890Smrg XrmQuark name_q; 11751ab64890Smrg XlcDatabase lc_db; 11761ab64890Smrg Database database; 11771ab64890Smrg int ref_count; 11781ab64890Smrg struct _XlcDatabaseListRec *next; 11791ab64890Smrg} XlcDatabaseListRec, *XlcDatabaseList; 11801ab64890Smrg 11811ab64890Smrg/* database cache list (per file) */ 11821ab64890Smrgstatic XlcDatabaseList _db_list = (XlcDatabaseList)NULL; 11831ab64890Smrg 11841ab64890Smrg/************************************************************************/ 11851ab64890Smrg/* _XlcGetResource(lcd, category, class, value, count) */ 11861ab64890Smrg/*----------------------------------------------------------------------*/ 11871ab64890Smrg/* This function retrieves XLocale database information. */ 11881ab64890Smrg/************************************************************************/ 11891ab64890Smrgvoid 11901ab64890Smrg_XlcGetResource( 11911ab64890Smrg XLCd lcd, 11921ab64890Smrg const char *category, 11931ab64890Smrg const char *class, 11941ab64890Smrg char ***value, 11951ab64890Smrg int *count) 11961ab64890Smrg{ 11971ab64890Smrg XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd); 11981ab64890Smrg 11991ab64890Smrg (*methods->get_resource)(lcd, category, class, value, count); 12001ab64890Smrg return; 12011ab64890Smrg} 12021ab64890Smrg 12031ab64890Smrg/************************************************************************/ 12041ab64890Smrg/* _XlcGetLocaleDataBase(lcd, category, class, value, count) */ 12051ab64890Smrg/*----------------------------------------------------------------------*/ 12061ab64890Smrg/* This function retrieves XLocale database information. */ 12071ab64890Smrg/************************************************************************/ 12081ab64890Smrgvoid 12091ab64890Smrg_XlcGetLocaleDataBase( 12101ab64890Smrg XLCd lcd, 12111ab64890Smrg const char *category, 12121ab64890Smrg const char *name, 12131ab64890Smrg char ***value, 12141ab64890Smrg int *count) 12151ab64890Smrg{ 12161ab64890Smrg XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db); 12171ab64890Smrg XrmQuark category_q, name_q; 12181ab64890Smrg 12191ab64890Smrg category_q = XrmStringToQuark(category); 12201ab64890Smrg name_q = XrmStringToQuark(name); 12211ab64890Smrg for (; lc_db->db; ++lc_db) { 12221ab64890Smrg if (category_q == lc_db->category_q && name_q == lc_db->name_q) { 12231ab64890Smrg *value = lc_db->db->value; 12241ab64890Smrg *count = lc_db->db->value_num; 12251ab64890Smrg return; 12261ab64890Smrg } 12271ab64890Smrg } 12281ab64890Smrg *value = (char **)NULL; 12291ab64890Smrg *count = 0; 12301ab64890Smrg} 12311ab64890Smrg 12321ab64890Smrg/************************************************************************/ 12331ab64890Smrg/* _XlcDestroyLocaleDataBase(lcd) */ 12341ab64890Smrg/*----------------------------------------------------------------------*/ 12351ab64890Smrg/* This function destroy the XLocale Database that bound to the */ 12369c019ec5Smaya/* specified lcd. If the XLocale Database is referred from some */ 12371ab64890Smrg/* other lcd, this function just decreases reference count of */ 12381ab64890Smrg/* the database. If no locale refers the database, this function */ 12391ab64890Smrg/* remove it from the cache list and free work area. */ 12401ab64890Smrg/************************************************************************/ 12411ab64890Smrgvoid 12421ab64890Smrg_XlcDestroyLocaleDataBase( 12431ab64890Smrg XLCd lcd) 12441ab64890Smrg{ 12451ab64890Smrg XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db); 12461ab64890Smrg XlcDatabaseList p, prev; 12471ab64890Smrg 12481ab64890Smrg for (p = _db_list, prev = (XlcDatabaseList)NULL; p; 12491ab64890Smrg prev = p, p = p->next) { 12501ab64890Smrg if (p->lc_db == lc_db) { 12511ab64890Smrg if ((-- p->ref_count) < 1) { 12521ab64890Smrg if (p->lc_db != (XlcDatabase)NULL) { 1253818534a1Smrg Xfree(p->lc_db); 12541ab64890Smrg } 12551ab64890Smrg DestroyDatabase(p->database); 12561ab64890Smrg if (prev == (XlcDatabaseList)NULL) { 12571ab64890Smrg _db_list = p->next; 12581ab64890Smrg } else { 12591ab64890Smrg prev->next = p->next; 12601ab64890Smrg } 12611ab64890Smrg Xfree((char*)p); 12621ab64890Smrg } 12631ab64890Smrg break; 12641ab64890Smrg } 12651ab64890Smrg } 12661ab64890Smrg XLC_PUBLIC(lcd, xlocale_db) = (XPointer)NULL; 12671ab64890Smrg} 12681ab64890Smrg 12691ab64890Smrg/************************************************************************/ 12701ab64890Smrg/* _XlcCreateLocaleDataBase(lcd) */ 12711ab64890Smrg/*----------------------------------------------------------------------*/ 12721ab64890Smrg/* This function create an XLocale database which correspond to */ 12731ab64890Smrg/* the specified XLCd. */ 12741ab64890Smrg/************************************************************************/ 12751ab64890SmrgXPointer 12761ab64890Smrg_XlcCreateLocaleDataBase( 12771ab64890Smrg XLCd lcd) 12781ab64890Smrg{ 12791ab64890Smrg XlcDatabaseList list, new; 12801ab64890Smrg Database p, database = (Database)NULL; 12811ab64890Smrg XlcDatabase lc_db = (XlcDatabase)NULL; 12821ab64890Smrg XrmQuark name_q; 12831ab64890Smrg char *name; 12841ab64890Smrg int i, n; 12851ab64890Smrg 12861ab64890Smrg name = _XlcFileName(lcd, "locale"); 12871ab64890Smrg if (name == NULL) 12881ab64890Smrg return (XPointer)NULL; 12891ab64890Smrg 12901ab64890Smrg#ifndef __UNIXOS2__ 12911ab64890Smrg name_q = XrmStringToQuark(name); 12921ab64890Smrg#else 12931ab64890Smrg name_q = XrmStringToQuark((char*)__XOS2RedirRoot(name)); 12941ab64890Smrg#endif 12951ab64890Smrg for (list = _db_list; list; list = list->next) { 12961ab64890Smrg if (name_q == list->name_q) { 12971ab64890Smrg list->ref_count++; 12981ab64890Smrg Xfree (name); 12991ab64890Smrg return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)list->lc_db; 13001ab64890Smrg } 13011ab64890Smrg } 13021ab64890Smrg 13031ab64890Smrg database = CreateDatabase(name); 13041ab64890Smrg if (database == (Database)NULL) { 13051ab64890Smrg Xfree (name); 13061ab64890Smrg return (XPointer)NULL; 13071ab64890Smrg } 13081ab64890Smrg n = CountDatabase(database); 13096cc2b21fSmrg lc_db = Xcalloc(n + 1, sizeof(XlcDatabaseRec)); 13101ab64890Smrg if (lc_db == (XlcDatabase)NULL) 13111ab64890Smrg goto err; 13121ab64890Smrg for (p = database, i = 0; p && i < n; p = p->next, ++i) { 13131ab64890Smrg lc_db[i].category_q = XrmStringToQuark(p->category); 13141ab64890Smrg lc_db[i].name_q = XrmStringToQuark(p->name); 13151ab64890Smrg lc_db[i].db = p; 13161ab64890Smrg } 13171ab64890Smrg 1318818534a1Smrg new = Xmalloc(sizeof(XlcDatabaseListRec)); 13191ab64890Smrg if (new == (XlcDatabaseList)NULL) { 13201ab64890Smrg goto err; 13211ab64890Smrg } 13221ab64890Smrg new->name_q = name_q; 13231ab64890Smrg new->lc_db = lc_db; 13241ab64890Smrg new->database = database; 13251ab64890Smrg new->ref_count = 1; 13261ab64890Smrg new->next = _db_list; 13271ab64890Smrg _db_list = new; 13281ab64890Smrg 13291ab64890Smrg Xfree (name); 13301ab64890Smrg return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)lc_db; 13311ab64890Smrg 13321ab64890Smrg err: 13331ab64890Smrg DestroyDatabase(database); 13341ab64890Smrg if (lc_db != (XlcDatabase)NULL) { 1335818534a1Smrg Xfree(lc_db); 13361ab64890Smrg } 13371ab64890Smrg Xfree (name); 13381ab64890Smrg return (XPointer)NULL; 13391ab64890Smrg} 13401ab64890Smrg 13411ab64890Smrg#endif /* NOT_X_ENV */ 1342