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 } 344d4a3aaf4Smrg memcpy(str + cur, p, (size_t) len); 3451ab64890Smrg 3461ab64890Smrg cur += len; 3471ab64890Smrg str[cur] = '\0'; 3481ab64890Smrg if (!quoted && cur > 1 && str[cur - 2] == SYM_BACKSLASH && 3491ab64890Smrg (str[cur - 1] == SYM_NEWLINE || str[cur-1] == SYM_CR)) { 3501ab64890Smrg /* the line is ended backslash followed by newline. 3511ab64890Smrg need to concatinate the next line. */ 3521ab64890Smrg cur -= 2; 3531ab64890Smrg str[cur] = '\0'; 3541ab64890Smrg } else if (len < BUFSIZE - 1 || buf[len - 1] == SYM_NEWLINE || 3551ab64890Smrg buf[len - 1] == SYM_CR) { 3561ab64890Smrg /* the line is shorter than BUFSIZE. */ 3571ab64890Smrg break; 3581ab64890Smrg } 3591ab64890Smrg } 3601ab64890Smrg if (quoted) { 3611ab64890Smrg /* error. still in quoted state. */ 3621ab64890Smrg return -1; 3631ab64890Smrg } 3641ab64890Smrg return line->cursize = cur; 3651ab64890Smrg} 3661ab64890Smrg 3671ab64890Smrg/************************************************************************/ 3681ab64890Smrg 3691ab64890Smrgstatic Token 3701ab64890Smrgget_token( 3711ab64890Smrg const char *str) 3721ab64890Smrg{ 3731ab64890Smrg switch (*str) { 3741ab64890Smrg case SYM_NEWLINE: 3751ab64890Smrg case SYM_CR: return T_NEWLINE; 3761ab64890Smrg case SYM_COMMENT: return T_COMMENT; 3771ab64890Smrg case SYM_SEMICOLON: return T_SEMICOLON; 3781ab64890Smrg case SYM_DOUBLE_QUOTE: return T_DOUBLE_QUOTE; 3791ab64890Smrg case SYM_LEFT_BRACE: return T_LEFT_BRACE; 3801ab64890Smrg case SYM_RIGHT_BRACE: return T_RIGHT_BRACE; 3811ab64890Smrg case SYM_SPACE: return T_SPACE; 3821ab64890Smrg case SYM_TAB: return T_TAB; 3831ab64890Smrg case SYM_BACKSLASH: 3841ab64890Smrg switch (str[1]) { 3851ab64890Smrg case 'x': return T_NUMERIC_HEX; 3861ab64890Smrg case 'd': return T_NUMERIC_DEC; 3871ab64890Smrg case 'o': return T_NUMERIC_OCT; 3881ab64890Smrg } 3891ab64890Smrg return T_BACKSLASH; 3901ab64890Smrg default: 3911ab64890Smrg return T_DEFAULT; 3921ab64890Smrg } 3931ab64890Smrg} 3941ab64890Smrg 3951ab64890Smrgstatic int 3961ab64890Smrgget_word( 3971ab64890Smrg const char *str, 3981ab64890Smrg char *word) 3991ab64890Smrg{ 4001ab64890Smrg const char *p = str; 4011ab64890Smrg char *w = word; 4021ab64890Smrg Token token; 4031ab64890Smrg int token_len; 4041ab64890Smrg 4051ab64890Smrg while (*p != '\0') { 4061ab64890Smrg token = get_token(p); 4071ab64890Smrg token_len = token_tbl[token].len; 4081ab64890Smrg if (token == T_BACKSLASH) { 4091ab64890Smrg p += token_len; 4101ab64890Smrg if (*p == '\0') 4111ab64890Smrg break; 4121ab64890Smrg token = get_token(p); 4131ab64890Smrg token_len = token_tbl[token].len; 4141ab64890Smrg } else if (token != T_COMMENT && token != T_DEFAULT) { 4151ab64890Smrg break; 4161ab64890Smrg } 4179c019ec5Smaya strncpy(w, p, (size_t) token_len); 4181ab64890Smrg p += token_len; w += token_len; 4191ab64890Smrg } 4201ab64890Smrg *w = '\0'; 4211ab64890Smrg return p - str; /* return number of scanned chars */ 4221ab64890Smrg} 4231ab64890Smrg 4241ab64890Smrgstatic int 4251ab64890Smrgget_quoted_word( 4261ab64890Smrg const char *str, 4271ab64890Smrg char *word) 4281ab64890Smrg{ 4291ab64890Smrg const char *p = str; 4301ab64890Smrg char *w = word; 4311ab64890Smrg Token token; 4321ab64890Smrg int token_len; 4331ab64890Smrg 4341ab64890Smrg if (*p == SYM_DOUBLE_QUOTE) { 4351ab64890Smrg ++p; 4361ab64890Smrg } 4371ab64890Smrg while (*p != '\0') { 4381ab64890Smrg token = get_token(p); 4391ab64890Smrg token_len = token_tbl[token].len; 4401ab64890Smrg if (token == T_DOUBLE_QUOTE) { 4411ab64890Smrg p += token_len; 4421ab64890Smrg goto found; 4431ab64890Smrg } 4441ab64890Smrg if (token == T_BACKSLASH) { 4451ab64890Smrg p += token_len; 4461ab64890Smrg if (*p == '\0') { 4471ab64890Smrg break; 4481ab64890Smrg } 4491ab64890Smrg token = get_token(p); 4501ab64890Smrg token_len = token_tbl[token].len; 4511ab64890Smrg } 4529c019ec5Smaya strncpy(w, p, (size_t) token_len); 4531ab64890Smrg p += token_len; w += token_len; 4541ab64890Smrg } 4551ab64890Smrg /* error. cannot detect next double quote */ 4561ab64890Smrg return 0; 4571ab64890Smrg 4581ab64890Smrg found:; 4591ab64890Smrg *w = '\0'; 4601ab64890Smrg return p - str; 4611ab64890Smrg} 4621ab64890Smrg 4631ab64890Smrg/************************************************************************/ 4641ab64890Smrg 4651ab64890Smrgstatic int 4661ab64890Smrgappend_value_list (void) 4671ab64890Smrg{ 4681ab64890Smrg char **value_list = parse_info.value; 4691ab64890Smrg char *value; 4701ab64890Smrg int value_num = parse_info.value_num; 4711ab64890Smrg int value_len = parse_info.value_len; 4721ab64890Smrg char *str = parse_info.buf; 4731ab64890Smrg int len = parse_info.bufsize; 4741ab64890Smrg char *p; 4751ab64890Smrg 4761ab64890Smrg if (len < 1) { 4771ab64890Smrg return 1; /* return with no error */ 4781ab64890Smrg } 4791ab64890Smrg 4801ab64890Smrg if (value_list == (char **)NULL) { 481818534a1Smrg value_list = Xmalloc(sizeof(char *) * 2); 4821ab64890Smrg *value_list = NULL; 4831ab64890Smrg } else { 4841ab64890Smrg char **prev_list = value_list; 4851ab64890Smrg 4861ab64890Smrg value_list = (char **) 487258a0ebeSmrg Xreallocarray(value_list, value_num + 2, sizeof(char *)); 4881ab64890Smrg if (value_list == NULL) { 4891ab64890Smrg Xfree(prev_list); 4901ab64890Smrg } 4911ab64890Smrg } 4921ab64890Smrg if (value_list == (char **)NULL) 4931ab64890Smrg goto err2; 4941ab64890Smrg 4951ab64890Smrg value = *value_list; 4961ab64890Smrg if (value == NULL) { 497818534a1Smrg value = Xmalloc(value_len + len + 1); 4981ab64890Smrg } else { 4991ab64890Smrg char *prev_value = value; 5001ab64890Smrg 501818534a1Smrg value = Xrealloc(value, value_len + len + 1); 5021ab64890Smrg if (value == NULL) { 5031ab64890Smrg Xfree(prev_value); 5041ab64890Smrg } 5051ab64890Smrg } 5061ab64890Smrg if (value == NULL) { 5071ab64890Smrg goto err1; 5081ab64890Smrg } 5091ab64890Smrg if (value != *value_list) { 5101ab64890Smrg int i; 511e9628295Smrg char *old_list; 512e9628295Smrg old_list = *value_list; 5131ab64890Smrg *value_list = value; 514e9628295Smrg /* Re-derive pointers from the new realloc() result to avoid undefined 515e9628295Smrg behaviour (and crashes on architectures with pointer bounds). */ 5161ab64890Smrg for (i = 1; i < value_num; ++i) { 517e9628295Smrg value_list[i] = value + (value_list[i] - old_list); 5181ab64890Smrg } 5191ab64890Smrg } 5201ab64890Smrg 5211ab64890Smrg value_list[value_num] = p = &value[value_len]; 5221ab64890Smrg value_list[value_num + 1] = NULL; 5239c019ec5Smaya strncpy(p, str, (size_t) len); 5241ab64890Smrg p[len] = 0; 5251ab64890Smrg 5261ab64890Smrg parse_info.value = value_list; 5271ab64890Smrg parse_info.value_num = value_num + 1; 5281ab64890Smrg parse_info.value_len = value_len + len + 1; 5291ab64890Smrg parse_info.bufsize = 0; 5301ab64890Smrg return 1; 5311ab64890Smrg 5321ab64890Smrg err1: 5331ab64890Smrg if (value_list) { 5341ab64890Smrg Xfree((char **)value_list); 5351ab64890Smrg } 5361ab64890Smrg if (value) { 5371ab64890Smrg Xfree(value); 5381ab64890Smrg } 5391ab64890Smrg err2: 5401ab64890Smrg parse_info.value = (char **)NULL; 5411ab64890Smrg parse_info.value_num = 0; 5421ab64890Smrg parse_info.value_len = 0; 5431ab64890Smrg parse_info.bufsize = 0; 5441ab64890Smrg return 0; 5451ab64890Smrg} 5461ab64890Smrg 54761b2299dSmrgstatic int 5481ab64890Smrgconstruct_name( 5491ab64890Smrg char *name, 5501ab64890Smrg int size) 5511ab64890Smrg{ 5521ab64890Smrg int i; 5531ab64890Smrg int len = 0; 5541ab64890Smrg char *p = name; 5551ab64890Smrg 5561ab64890Smrg for (i = 0; i <= parse_info.nest_depth; ++i) { 5579c019ec5Smaya len = (int) ((size_t) len + (strlen(parse_info.name[i]) + 1)); 5581ab64890Smrg } 5591ab64890Smrg if (len >= size) 5601ab64890Smrg return 0; 5611ab64890Smrg 5621ab64890Smrg strcpy(p, parse_info.name[0]); 5631ab64890Smrg p += strlen(parse_info.name[0]); 5641ab64890Smrg for (i = 1; i <= parse_info.nest_depth; ++i) { 5651ab64890Smrg *p++ = '.'; 5661ab64890Smrg strcpy(p, parse_info.name[i]); 5671ab64890Smrg p += strlen(parse_info.name[i]); 5681ab64890Smrg } 5691ab64890Smrg return *name != '\0'; 5701ab64890Smrg} 5711ab64890Smrg 5721ab64890Smrgstatic int 5731ab64890Smrgstore_to_database( 5741ab64890Smrg Database *db) 5751ab64890Smrg{ 5761ab64890Smrg Database new = (Database)NULL; 5771ab64890Smrg char name[BUFSIZE]; 5781ab64890Smrg 5791ab64890Smrg if (parse_info.pre_state == S_VALUE) { 5801ab64890Smrg if (! append_value_list()) { 5811ab64890Smrg goto err; 5821ab64890Smrg } 5831ab64890Smrg } 5841ab64890Smrg 5851ab64890Smrg if (parse_info.name[parse_info.nest_depth] == NULL) { 5861ab64890Smrg goto err; 5871ab64890Smrg } 5881ab64890Smrg 5896cc2b21fSmrg new = Xcalloc(1, sizeof(DatabaseRec)); 5901ab64890Smrg if (new == (Database)NULL) { 5911ab64890Smrg goto err; 5921ab64890Smrg } 5931ab64890Smrg 5946cc2b21fSmrg new->category = strdup(parse_info.category); 5951ab64890Smrg if (new->category == NULL) { 5961ab64890Smrg goto err; 5971ab64890Smrg } 5981ab64890Smrg 5991ab64890Smrg if (! construct_name(name, sizeof(name))) { 6001ab64890Smrg goto err; 6011ab64890Smrg } 6026cc2b21fSmrg new->name = strdup(name); 6031ab64890Smrg if (new->name == NULL) { 6041ab64890Smrg goto err; 6051ab64890Smrg } 6061ab64890Smrg new->next = *db; 6071ab64890Smrg new->value = parse_info.value; 6081ab64890Smrg new->value_num = parse_info.value_num; 6091ab64890Smrg *db = new; 6101ab64890Smrg 6111ab64890Smrg Xfree(parse_info.name[parse_info.nest_depth]); 6121ab64890Smrg parse_info.name[parse_info.nest_depth] = NULL; 6131ab64890Smrg 6141ab64890Smrg parse_info.value = (char **)NULL; 6151ab64890Smrg parse_info.value_num = 0; 6161ab64890Smrg parse_info.value_len = 0; 6171ab64890Smrg 6181ab64890Smrg return 1; 6191ab64890Smrg 6201ab64890Smrg err: 6211ab64890Smrg if (new) { 6221ab64890Smrg if (new->category) { 6231ab64890Smrg Xfree(new->category); 6241ab64890Smrg } 6251ab64890Smrg if (new->name) { 6261ab64890Smrg Xfree(new->name); 6271ab64890Smrg } 6281ab64890Smrg Xfree(new); 6291ab64890Smrg } 6301ab64890Smrg if (parse_info.value) { 6311ab64890Smrg if (*parse_info.value) { 6321ab64890Smrg Xfree(*parse_info.value); 6331ab64890Smrg } 6341ab64890Smrg Xfree((char **)parse_info.value); 6351ab64890Smrg parse_info.value = (char **)NULL; 6361ab64890Smrg parse_info.value_num = 0; 6371ab64890Smrg parse_info.value_len = 0; 6381ab64890Smrg } 6391ab64890Smrg return 0; 6401ab64890Smrg} 6411ab64890Smrg 6421ab64890Smrg#define END_MARK "END" 6431ab64890Smrg#define END_MARK_LEN 3 /*strlen(END_MARK)*/ 6441ab64890Smrg 6451ab64890Smrgstatic int 6461ab64890Smrgcheck_category_end( 6471ab64890Smrg const char *str) 6481ab64890Smrg{ 6491ab64890Smrg const char *p; 6501ab64890Smrg int len; 6511ab64890Smrg 6521ab64890Smrg p = str; 6531ab64890Smrg if (strncmp(p, END_MARK, END_MARK_LEN)) { 6541ab64890Smrg return 0; 6551ab64890Smrg } 6561ab64890Smrg p += END_MARK_LEN; 6571ab64890Smrg 6581ab64890Smrg while (iswhite(*p)) { 6591ab64890Smrg ++p; 6601ab64890Smrg } 6619c019ec5Smaya len = (int) strlen(parse_info.category); 6629c019ec5Smaya if (strncmp(p, parse_info.category, (size_t) len)) { 6631ab64890Smrg return 0; 6641ab64890Smrg } 6651ab64890Smrg p += len; 6661ab64890Smrg return p - str; 6671ab64890Smrg} 6681ab64890Smrg 6691ab64890Smrg/************************************************************************/ 6701ab64890Smrg 6711ab64890Smrgstatic int 6721ab64890Smrgf_newline( 6731ab64890Smrg const char *str, 6741ab64890Smrg Token token, 6751ab64890Smrg Database *db) 6761ab64890Smrg{ 6771ab64890Smrg switch (parse_info.pre_state) { 6781ab64890Smrg case S_NULL: 6791ab64890Smrg case S_CATEGORY: 6801ab64890Smrg break; 6811ab64890Smrg case S_NAME: 6821ab64890Smrg return 0; /* no value */ 6831ab64890Smrg case S_VALUE: 6841ab64890Smrg if (!store_to_database(db)) 6851ab64890Smrg return 0; 6861ab64890Smrg parse_info.pre_state = S_CATEGORY; 6871ab64890Smrg break; 6881ab64890Smrg default: 6891ab64890Smrg return 0; 6901ab64890Smrg } 6911ab64890Smrg return token_tbl[token].len; 6921ab64890Smrg} 6931ab64890Smrg 6941ab64890Smrgstatic int 6951ab64890Smrgf_comment( 6961ab64890Smrg const char *str, 6971ab64890Smrg Token token, 6981ab64890Smrg Database *db) 6991ab64890Smrg{ 7001ab64890Smrg /* NOTE: comment is already handled in read_line(), 7011ab64890Smrg so this function is not necessary. */ 7021ab64890Smrg 7031ab64890Smrg const char *p = str; 7041ab64890Smrg 7051ab64890Smrg while (*p != SYM_NEWLINE && *p != SYM_CR && *p != '\0') { 7061ab64890Smrg ++p; /* zap to the end of line */ 7071ab64890Smrg } 7081ab64890Smrg return p - str; 7091ab64890Smrg} 7101ab64890Smrg 7111ab64890Smrgstatic int 7121ab64890Smrgf_white( 7131ab64890Smrg const char *str, 7141ab64890Smrg Token token, 7151ab64890Smrg Database *db) 7161ab64890Smrg{ 7171ab64890Smrg const char *p = str; 7181ab64890Smrg 7191ab64890Smrg while (iswhite(*p)) { 7201ab64890Smrg ++p; 7211ab64890Smrg } 7221ab64890Smrg return p - str; 7231ab64890Smrg} 7241ab64890Smrg 7251ab64890Smrgstatic int 7261ab64890Smrgf_semicolon( 7271ab64890Smrg const char *str, 7281ab64890Smrg Token token, 7291ab64890Smrg Database *db) 7301ab64890Smrg{ 7311ab64890Smrg switch (parse_info.pre_state) { 7321ab64890Smrg case S_NULL: 7331ab64890Smrg case S_CATEGORY: 7341ab64890Smrg case S_NAME: 7351ab64890Smrg return 0; 7361ab64890Smrg case S_VALUE: 7371ab64890Smrg if (! append_value_list()) 7381ab64890Smrg return 0; 7391ab64890Smrg parse_info.pre_state = S_VALUE; 7401ab64890Smrg break; 7411ab64890Smrg default: 7421ab64890Smrg return 0; 7431ab64890Smrg } 7441ab64890Smrg return token_tbl[token].len; 7451ab64890Smrg} 7461ab64890Smrg 7471ab64890Smrgstatic int 7481ab64890Smrgf_left_brace( 7491ab64890Smrg const char *str, 7501ab64890Smrg Token token, 7511ab64890Smrg Database *db) 7521ab64890Smrg{ 7531ab64890Smrg switch (parse_info.pre_state) { 7541ab64890Smrg case S_NULL: 7551ab64890Smrg case S_CATEGORY: 7561ab64890Smrg case S_VALUE: 7571ab64890Smrg return 0; 7581ab64890Smrg case S_NAME: 7591ab64890Smrg if (parse_info.name[parse_info.nest_depth] == NULL 7601ab64890Smrg || parse_info.nest_depth + 1 > MAX_NAME_NEST) 7611ab64890Smrg return 0; 7621ab64890Smrg ++parse_info.nest_depth; 7631ab64890Smrg parse_info.pre_state = S_CATEGORY; 7641ab64890Smrg break; 7651ab64890Smrg default: 7661ab64890Smrg return 0; 7671ab64890Smrg } 7681ab64890Smrg return token_tbl[token].len; 7691ab64890Smrg} 7701ab64890Smrg 7711ab64890Smrgstatic int 7721ab64890Smrgf_right_brace( 7731ab64890Smrg const char *str, 7741ab64890Smrg Token token, 7751ab64890Smrg Database *db) 7761ab64890Smrg{ 7771ab64890Smrg if (parse_info.nest_depth < 1) 7781ab64890Smrg return 0; 7791ab64890Smrg 7801ab64890Smrg switch (parse_info.pre_state) { 7811ab64890Smrg case S_NULL: 7821ab64890Smrg case S_NAME: 7831ab64890Smrg return 0; 7841ab64890Smrg case S_VALUE: 7851ab64890Smrg if (! store_to_database(db)) 7861ab64890Smrg return 0; 7873233502eSmrg /* fall through - to next case */ 7881ab64890Smrg case S_CATEGORY: 7891ab64890Smrg if (parse_info.name[parse_info.nest_depth] != NULL) { 7901ab64890Smrg Xfree(parse_info.name[parse_info.nest_depth]); 7911ab64890Smrg parse_info.name[parse_info.nest_depth] = NULL; 7921ab64890Smrg } 7931ab64890Smrg --parse_info.nest_depth; 7941ab64890Smrg parse_info.pre_state = S_CATEGORY; 7951ab64890Smrg break; 7961ab64890Smrg default: 7971ab64890Smrg return 0; 7981ab64890Smrg } 7991ab64890Smrg return token_tbl[token].len; 8001ab64890Smrg} 8011ab64890Smrg 8021ab64890Smrgstatic int 8031ab64890Smrgf_double_quote( 8041ab64890Smrg const char *str, 8051ab64890Smrg Token token, 8061ab64890Smrg Database *db) 8071ab64890Smrg{ 8081ab64890Smrg char word[BUFSIZE]; 8091ab64890Smrg char* wordp; 8101ab64890Smrg int len; 8111ab64890Smrg 8129c019ec5Smaya if ((len = (int) strlen (str)) < sizeof word) 8131ab64890Smrg wordp = word; 8141ab64890Smrg else 8151ab64890Smrg wordp = Xmalloc (len + 1); 8161ab64890Smrg if (wordp == NULL) 8171ab64890Smrg return 0; 8181ab64890Smrg 8191ab64890Smrg len = 0; 8201ab64890Smrg switch (parse_info.pre_state) { 8211ab64890Smrg case S_NULL: 8221ab64890Smrg case S_CATEGORY: 8231ab64890Smrg goto err; 8241ab64890Smrg case S_NAME: 8251ab64890Smrg case S_VALUE: 8261ab64890Smrg len = get_quoted_word(str, wordp); 8271ab64890Smrg if (len < 1) 8281ab64890Smrg goto err; 82961b2299dSmrg if ((parse_info.bufsize + (int)strlen(wordp) + 1) 8301ab64890Smrg >= parse_info.bufMaxSize) { 8319c019ec5Smaya if (realloc_parse_info((int) strlen(wordp)+1) == False) { 8321ab64890Smrg goto err; 8331ab64890Smrg } 8341ab64890Smrg } 8351ab64890Smrg strcpy(&parse_info.buf[parse_info.bufsize], wordp); 8369c019ec5Smaya parse_info.bufsize = (int) ((size_t) parse_info.bufsize + strlen(wordp)); 8371ab64890Smrg parse_info.pre_state = S_VALUE; 8381ab64890Smrg break; 8391ab64890Smrg default: 8401ab64890Smrg goto err; 8411ab64890Smrg } 8421ab64890Smrg if (wordp != word) 8431ab64890Smrg Xfree (wordp); 8441ab64890Smrg return len; /* including length of token */ 8451ab64890Smrg 8461ab64890Smrgerr: 8471ab64890Smrg if (wordp != word) 8481ab64890Smrg Xfree (wordp); 8491ab64890Smrg return 0; 8501ab64890Smrg} 8511ab64890Smrg 8521ab64890Smrgstatic int 8531ab64890Smrgf_backslash( 8541ab64890Smrg const char *str, 8551ab64890Smrg Token token, 8561ab64890Smrg Database *db) 8571ab64890Smrg{ 8581ab64890Smrg return f_default(str, token, db); 8591ab64890Smrg} 8601ab64890Smrg 8611ab64890Smrgstatic int 8621ab64890Smrgf_numeric( 8631ab64890Smrg const char *str, 8641ab64890Smrg Token token, 8651ab64890Smrg Database *db) 8661ab64890Smrg{ 8671ab64890Smrg char word[BUFSIZE]; 8681ab64890Smrg const char *p; 8691ab64890Smrg char* wordp; 8701ab64890Smrg int len; 8711ab64890Smrg int token_len; 8721ab64890Smrg 8739c019ec5Smaya if ((len = (int) strlen (str)) < sizeof word) 8741ab64890Smrg wordp = word; 8751ab64890Smrg else 8761ab64890Smrg wordp = Xmalloc (len + 1); 8771ab64890Smrg if (wordp == NULL) 8781ab64890Smrg return 0; 8791ab64890Smrg 8801ab64890Smrg switch (parse_info.pre_state) { 8811ab64890Smrg case S_NULL: 8821ab64890Smrg case S_CATEGORY: 8831ab64890Smrg goto err; 8841ab64890Smrg case S_NAME: 8851ab64890Smrg case S_VALUE: 8861ab64890Smrg token_len = token_tbl[token].len; 8871ab64890Smrg p = str + token_len; 8881ab64890Smrg len = get_word(p, wordp); 8891ab64890Smrg if (len < 1) 8901ab64890Smrg goto err; 89161b2299dSmrg if ((parse_info.bufsize + token_len + (int)strlen(wordp) + 1) 8921ab64890Smrg >= parse_info.bufMaxSize) { 8939c019ec5Smaya if (realloc_parse_info((int)((size_t) token_len + strlen(wordp) + 1)) == False) 8941ab64890Smrg goto err; 8951ab64890Smrg } 8969c019ec5Smaya strncpy(&parse_info.buf[parse_info.bufsize], str, (size_t) token_len); 8971ab64890Smrg strcpy(&parse_info.buf[parse_info.bufsize + token_len], wordp); 8989c019ec5Smaya parse_info.bufsize = (int) ((size_t) parse_info.bufsize + ((size_t) token_len + strlen(wordp))); 8991ab64890Smrg parse_info.pre_state = S_VALUE; 9001ab64890Smrg break; 9011ab64890Smrg default: 9021ab64890Smrg goto err; 9031ab64890Smrg } 9041ab64890Smrg if (wordp != word) 9051ab64890Smrg Xfree (wordp); 9061ab64890Smrg return len + token_len; 9071ab64890Smrg 9081ab64890Smrgerr: 9091ab64890Smrg if (wordp != word) 9101ab64890Smrg Xfree (wordp); 9111ab64890Smrg return 0; 9121ab64890Smrg} 9131ab64890Smrg 9141ab64890Smrgstatic int 9151ab64890Smrgf_default( 9161ab64890Smrg const char *str, 9171ab64890Smrg Token token, 9181ab64890Smrg Database *db) 9191ab64890Smrg{ 9201ab64890Smrg char word[BUFSIZE], *p; 9211ab64890Smrg char* wordp; 9221ab64890Smrg int len; 9231ab64890Smrg 9249c019ec5Smaya if ((len = (int) strlen (str)) < sizeof word) 9251ab64890Smrg wordp = word; 9261ab64890Smrg else 9271ab64890Smrg wordp = Xmalloc (len + 1); 9281ab64890Smrg if (wordp == NULL) 9291ab64890Smrg return 0; 9301ab64890Smrg 9311ab64890Smrg len = get_word(str, wordp); 9321ab64890Smrg if (len < 1) 9331ab64890Smrg goto err; 9341ab64890Smrg 9351ab64890Smrg switch (parse_info.pre_state) { 9361ab64890Smrg case S_NULL: 9371ab64890Smrg if (parse_info.category != NULL) 9381ab64890Smrg goto err; 9396cc2b21fSmrg p = strdup(wordp); 9401ab64890Smrg if (p == NULL) 9411ab64890Smrg goto err; 9421ab64890Smrg parse_info.category = p; 9431ab64890Smrg parse_info.pre_state = S_CATEGORY; 9441ab64890Smrg break; 9451ab64890Smrg case S_CATEGORY: 9461ab64890Smrg if (parse_info.nest_depth == 0) { 9471ab64890Smrg if (check_category_end(str)) { 9481ab64890Smrg /* end of category is detected. 9491ab64890Smrg clear context and zap to end of this line */ 9501ab64890Smrg clear_parse_info(); 9519c019ec5Smaya len = (int) strlen(str); 9521ab64890Smrg break; 9531ab64890Smrg } 9541ab64890Smrg } 9556cc2b21fSmrg p = strdup(wordp); 9561ab64890Smrg if (p == NULL) 9571ab64890Smrg goto err; 9581ab64890Smrg if (parse_info.name[parse_info.nest_depth] != NULL) { 9591ab64890Smrg Xfree(parse_info.name[parse_info.nest_depth]); 9601ab64890Smrg } 9611ab64890Smrg parse_info.name[parse_info.nest_depth] = p; 9621ab64890Smrg parse_info.pre_state = S_NAME; 9631ab64890Smrg break; 9641ab64890Smrg case S_NAME: 9651ab64890Smrg case S_VALUE: 96661b2299dSmrg if ((parse_info.bufsize + (int)strlen(wordp) + 1) 9671ab64890Smrg >= parse_info.bufMaxSize) { 9689c019ec5Smaya if (realloc_parse_info((int) strlen(wordp) + 1) == False) 9691ab64890Smrg goto err; 9701ab64890Smrg } 9711ab64890Smrg strcpy(&parse_info.buf[parse_info.bufsize], wordp); 9729c019ec5Smaya parse_info.bufsize = (int) ((size_t) parse_info.bufsize + strlen(wordp)); 9731ab64890Smrg parse_info.pre_state = S_VALUE; 9741ab64890Smrg break; 9751ab64890Smrg default: 9761ab64890Smrg goto err; 9771ab64890Smrg } 9781ab64890Smrg if (wordp != word) 9791ab64890Smrg Xfree (wordp); 9801ab64890Smrg return len; 9811ab64890Smrg 9821ab64890Smrgerr: 9831ab64890Smrg if (wordp != word) 9841ab64890Smrg Xfree (wordp); 9851ab64890Smrg return 0; 9861ab64890Smrg} 9871ab64890Smrg 9881ab64890Smrg/************************************************************************/ 9891ab64890Smrg 9901ab64890Smrg#ifdef DEBUG 9911ab64890Smrgstatic void 9921ab64890SmrgPrintDatabase( 9931ab64890Smrg Database db) 9941ab64890Smrg{ 9951ab64890Smrg Database p = db; 9961ab64890Smrg int i = 0, j; 9971ab64890Smrg 9981ab64890Smrg printf("***\n*** BEGIN Database\n***\n"); 9991ab64890Smrg while (p) { 10001ab64890Smrg printf("%3d: ", i++); 10011ab64890Smrg printf("%s, %s, ", p->category, p->name); 10021ab64890Smrg printf("\t[%d: ", p->value_num); 10031ab64890Smrg for (j = 0; j < p->value_num; ++j) { 10041ab64890Smrg printf("%s, ", p->value[j]); 10051ab64890Smrg } 10061ab64890Smrg printf("]\n"); 10071ab64890Smrg p = p->next; 10081ab64890Smrg } 10091ab64890Smrg printf("***\n*** END Database\n***\n"); 10101ab64890Smrg} 10111ab64890Smrg#endif 10121ab64890Smrg 10131ab64890Smrgstatic void 10141ab64890SmrgDestroyDatabase( 10151ab64890Smrg Database db) 10161ab64890Smrg{ 10171ab64890Smrg Database p = db; 10181ab64890Smrg 10191ab64890Smrg while (p) { 10201ab64890Smrg if (p->category != NULL) { 10211ab64890Smrg Xfree(p->category); 10221ab64890Smrg } 10231ab64890Smrg if (p->name != NULL) { 10241ab64890Smrg Xfree(p->name); 10251ab64890Smrg } 10261ab64890Smrg if (p->value != (char **)NULL) { 10271ab64890Smrg if (*p->value != NULL) { 10281ab64890Smrg Xfree(*p->value); 10291ab64890Smrg } 1030818534a1Smrg Xfree(p->value); 10311ab64890Smrg } 10321ab64890Smrg db = p->next; 1033818534a1Smrg Xfree(p); 10341ab64890Smrg p = db; 10351ab64890Smrg } 10361ab64890Smrg} 10371ab64890Smrg 10381ab64890Smrgstatic int 10391ab64890SmrgCountDatabase( 10401ab64890Smrg Database db) 10411ab64890Smrg{ 10421ab64890Smrg Database p = db; 10431ab64890Smrg int cnt = 0; 10441ab64890Smrg 10451ab64890Smrg while (p) { 10461ab64890Smrg ++cnt; 10471ab64890Smrg p = p->next; 10481ab64890Smrg } 10491ab64890Smrg return cnt; 10501ab64890Smrg} 10511ab64890Smrg 10521ab64890Smrgstatic Database 10531ab64890SmrgCreateDatabase( 10541ab64890Smrg char *dbfile) 10551ab64890Smrg{ 10561ab64890Smrg Database db = (Database)NULL; 10571ab64890Smrg FILE *fd; 10581ab64890Smrg Line line; 10591ab64890Smrg char *p; 10601ab64890Smrg Token token; 10611ab64890Smrg int len; 10621ab64890Smrg int error = 0; 10631ab64890Smrg 10641ab64890Smrg fd = _XFopenFile(dbfile, "r"); 10651ab64890Smrg if (fd == (FILE *)NULL) 10661ab64890Smrg return NULL; 10671ab64890Smrg 10681ab64890Smrg bzero(&line, sizeof(Line)); 10691ab64890Smrg init_parse_info(); 10701ab64890Smrg 10711ab64890Smrg do { 10721ab64890Smrg int rc = read_line(fd, &line); 10731ab64890Smrg if (rc < 0) { 10741ab64890Smrg error = 1; 10751ab64890Smrg break; 10761ab64890Smrg } else if (rc == 0) { 10771ab64890Smrg break; 10781ab64890Smrg } 10791ab64890Smrg p = line.str; 10801ab64890Smrg while (*p) { 10811ab64890Smrg int (*parse_proc)(const char *str, Token token, Database *db) = NULL; 10821ab64890Smrg 10831ab64890Smrg token = get_token(p); 10841ab64890Smrg 10851ab64890Smrg switch (token_tbl[token].token) { 10861ab64890Smrg case T_NEWLINE: 10871ab64890Smrg parse_proc = f_newline; 10881ab64890Smrg break; 10891ab64890Smrg case T_COMMENT: 10901ab64890Smrg parse_proc = f_comment; 10911ab64890Smrg break; 10921ab64890Smrg case T_SEMICOLON: 10931ab64890Smrg parse_proc = f_semicolon; 10941ab64890Smrg break; 10951ab64890Smrg case T_DOUBLE_QUOTE: 10961ab64890Smrg parse_proc = f_double_quote; 10971ab64890Smrg break; 10981ab64890Smrg case T_LEFT_BRACE: 10991ab64890Smrg parse_proc = f_left_brace; 11001ab64890Smrg break; 11011ab64890Smrg case T_RIGHT_BRACE: 11021ab64890Smrg parse_proc = f_right_brace; 11031ab64890Smrg break; 11041ab64890Smrg case T_SPACE: 11051ab64890Smrg case T_TAB: 11061ab64890Smrg parse_proc = f_white; 11071ab64890Smrg break; 11081ab64890Smrg case T_BACKSLASH: 11091ab64890Smrg parse_proc = f_backslash; 11101ab64890Smrg break; 11111ab64890Smrg case T_NUMERIC_HEX: 11121ab64890Smrg case T_NUMERIC_DEC: 11131ab64890Smrg case T_NUMERIC_OCT: 11141ab64890Smrg parse_proc = f_numeric; 11151ab64890Smrg break; 11161ab64890Smrg case T_DEFAULT: 11171ab64890Smrg parse_proc = f_default; 11181ab64890Smrg break; 11191ab64890Smrg } 11201ab64890Smrg 11211ab64890Smrg len = parse_proc(p, token, &db); 11221ab64890Smrg 11231ab64890Smrg if (len < 1) { 11241ab64890Smrg error = 1; 11251ab64890Smrg break; 11261ab64890Smrg } 11271ab64890Smrg p += len; 11281ab64890Smrg } 11291ab64890Smrg } while (!error); 11301ab64890Smrg 11311ab64890Smrg if (parse_info.pre_state != S_NULL) { 11321ab64890Smrg clear_parse_info(); 11331ab64890Smrg error = 1; 11341ab64890Smrg } 11351ab64890Smrg if (error) { 11361ab64890Smrg#ifdef DEBUG 11371ab64890Smrg fprintf(stderr, "database format error at line %d.\n", line.seq); 11381ab64890Smrg#endif 11391ab64890Smrg DestroyDatabase(db); 11401ab64890Smrg db = (Database)NULL; 11411ab64890Smrg } 11421ab64890Smrg 11431ab64890Smrg fclose(fd); 11441ab64890Smrg free_line(&line); 11451ab64890Smrg 11461ab64890Smrg#ifdef DEBUG 11471ab64890Smrg PrintDatabase(db); 11481ab64890Smrg#endif 11491ab64890Smrg 11501ab64890Smrg return db; 11511ab64890Smrg} 11521ab64890Smrg 11531ab64890Smrg/************************************************************************/ 11541ab64890Smrg 11551ab64890Smrg#ifndef NOT_X_ENV 11561ab64890Smrg 11571ab64890Smrg/* locale framework functions */ 11581ab64890Smrg 11591ab64890Smrgtypedef struct _XlcDatabaseRec { 11601ab64890Smrg XrmQuark category_q; 11611ab64890Smrg XrmQuark name_q; 11621ab64890Smrg Database db; 11631ab64890Smrg struct _XlcDatabaseRec *next; 11641ab64890Smrg} XlcDatabaseRec, *XlcDatabase; 11651ab64890Smrg 11661ab64890Smrgtypedef struct _XlcDatabaseListRec { 11671ab64890Smrg XrmQuark name_q; 11681ab64890Smrg XlcDatabase lc_db; 11691ab64890Smrg Database database; 11701ab64890Smrg int ref_count; 11711ab64890Smrg struct _XlcDatabaseListRec *next; 11721ab64890Smrg} XlcDatabaseListRec, *XlcDatabaseList; 11731ab64890Smrg 11741ab64890Smrg/* database cache list (per file) */ 11751ab64890Smrgstatic XlcDatabaseList _db_list = (XlcDatabaseList)NULL; 11761ab64890Smrg 11771ab64890Smrg/************************************************************************/ 11781ab64890Smrg/* _XlcGetResource(lcd, category, class, value, count) */ 11791ab64890Smrg/*----------------------------------------------------------------------*/ 11801ab64890Smrg/* This function retrieves XLocale database information. */ 11811ab64890Smrg/************************************************************************/ 11821ab64890Smrgvoid 11831ab64890Smrg_XlcGetResource( 11841ab64890Smrg XLCd lcd, 11851ab64890Smrg const char *category, 11861ab64890Smrg const char *class, 11871ab64890Smrg char ***value, 11881ab64890Smrg int *count) 11891ab64890Smrg{ 11901ab64890Smrg XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd); 11911ab64890Smrg 11921ab64890Smrg (*methods->get_resource)(lcd, category, class, value, count); 11931ab64890Smrg return; 11941ab64890Smrg} 11951ab64890Smrg 11961ab64890Smrg/************************************************************************/ 11971ab64890Smrg/* _XlcGetLocaleDataBase(lcd, category, class, value, count) */ 11981ab64890Smrg/*----------------------------------------------------------------------*/ 11991ab64890Smrg/* This function retrieves XLocale database information. */ 12001ab64890Smrg/************************************************************************/ 12011ab64890Smrgvoid 12021ab64890Smrg_XlcGetLocaleDataBase( 12031ab64890Smrg XLCd lcd, 12041ab64890Smrg const char *category, 12051ab64890Smrg const char *name, 12061ab64890Smrg char ***value, 12071ab64890Smrg int *count) 12081ab64890Smrg{ 12091ab64890Smrg XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db); 12101ab64890Smrg XrmQuark category_q, name_q; 12111ab64890Smrg 12121ab64890Smrg category_q = XrmStringToQuark(category); 12131ab64890Smrg name_q = XrmStringToQuark(name); 12141ab64890Smrg for (; lc_db->db; ++lc_db) { 12151ab64890Smrg if (category_q == lc_db->category_q && name_q == lc_db->name_q) { 12161ab64890Smrg *value = lc_db->db->value; 12171ab64890Smrg *count = lc_db->db->value_num; 12181ab64890Smrg return; 12191ab64890Smrg } 12201ab64890Smrg } 12211ab64890Smrg *value = (char **)NULL; 12221ab64890Smrg *count = 0; 12231ab64890Smrg} 12241ab64890Smrg 12251ab64890Smrg/************************************************************************/ 12261ab64890Smrg/* _XlcDestroyLocaleDataBase(lcd) */ 12271ab64890Smrg/*----------------------------------------------------------------------*/ 12281ab64890Smrg/* This function destroy the XLocale Database that bound to the */ 12299c019ec5Smaya/* specified lcd. If the XLocale Database is referred from some */ 12301ab64890Smrg/* other lcd, this function just decreases reference count of */ 12311ab64890Smrg/* the database. If no locale refers the database, this function */ 12321ab64890Smrg/* remove it from the cache list and free work area. */ 12331ab64890Smrg/************************************************************************/ 12341ab64890Smrgvoid 12351ab64890Smrg_XlcDestroyLocaleDataBase( 12361ab64890Smrg XLCd lcd) 12371ab64890Smrg{ 12381ab64890Smrg XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db); 12391ab64890Smrg XlcDatabaseList p, prev; 12401ab64890Smrg 12411ab64890Smrg for (p = _db_list, prev = (XlcDatabaseList)NULL; p; 12421ab64890Smrg prev = p, p = p->next) { 12431ab64890Smrg if (p->lc_db == lc_db) { 12441ab64890Smrg if ((-- p->ref_count) < 1) { 12451ab64890Smrg if (p->lc_db != (XlcDatabase)NULL) { 1246818534a1Smrg Xfree(p->lc_db); 12471ab64890Smrg } 12481ab64890Smrg DestroyDatabase(p->database); 12491ab64890Smrg if (prev == (XlcDatabaseList)NULL) { 12501ab64890Smrg _db_list = p->next; 12511ab64890Smrg } else { 12521ab64890Smrg prev->next = p->next; 12531ab64890Smrg } 12541ab64890Smrg Xfree((char*)p); 12551ab64890Smrg } 12561ab64890Smrg break; 12571ab64890Smrg } 12581ab64890Smrg } 12591ab64890Smrg XLC_PUBLIC(lcd, xlocale_db) = (XPointer)NULL; 12601ab64890Smrg} 12611ab64890Smrg 12621ab64890Smrg/************************************************************************/ 12631ab64890Smrg/* _XlcCreateLocaleDataBase(lcd) */ 12641ab64890Smrg/*----------------------------------------------------------------------*/ 12651ab64890Smrg/* This function create an XLocale database which correspond to */ 12661ab64890Smrg/* the specified XLCd. */ 12671ab64890Smrg/************************************************************************/ 12681ab64890SmrgXPointer 12691ab64890Smrg_XlcCreateLocaleDataBase( 12701ab64890Smrg XLCd lcd) 12711ab64890Smrg{ 12721ab64890Smrg XlcDatabaseList list, new; 12731ab64890Smrg Database p, database = (Database)NULL; 12741ab64890Smrg XlcDatabase lc_db = (XlcDatabase)NULL; 12751ab64890Smrg XrmQuark name_q; 12761ab64890Smrg char *name; 12771ab64890Smrg int i, n; 12781ab64890Smrg 12791ab64890Smrg name = _XlcFileName(lcd, "locale"); 12801ab64890Smrg if (name == NULL) 12811ab64890Smrg return (XPointer)NULL; 12821ab64890Smrg 12831ab64890Smrg name_q = XrmStringToQuark(name); 12841ab64890Smrg for (list = _db_list; list; list = list->next) { 12851ab64890Smrg if (name_q == list->name_q) { 12861ab64890Smrg list->ref_count++; 12871ab64890Smrg Xfree (name); 12881ab64890Smrg return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)list->lc_db; 12891ab64890Smrg } 12901ab64890Smrg } 12911ab64890Smrg 12921ab64890Smrg database = CreateDatabase(name); 12931ab64890Smrg if (database == (Database)NULL) { 12941ab64890Smrg Xfree (name); 12951ab64890Smrg return (XPointer)NULL; 12961ab64890Smrg } 12971ab64890Smrg n = CountDatabase(database); 12986cc2b21fSmrg lc_db = Xcalloc(n + 1, sizeof(XlcDatabaseRec)); 12991ab64890Smrg if (lc_db == (XlcDatabase)NULL) 13001ab64890Smrg goto err; 13011ab64890Smrg for (p = database, i = 0; p && i < n; p = p->next, ++i) { 13021ab64890Smrg lc_db[i].category_q = XrmStringToQuark(p->category); 13031ab64890Smrg lc_db[i].name_q = XrmStringToQuark(p->name); 13041ab64890Smrg lc_db[i].db = p; 13051ab64890Smrg } 13061ab64890Smrg 1307818534a1Smrg new = Xmalloc(sizeof(XlcDatabaseListRec)); 13081ab64890Smrg if (new == (XlcDatabaseList)NULL) { 13091ab64890Smrg goto err; 13101ab64890Smrg } 13111ab64890Smrg new->name_q = name_q; 13121ab64890Smrg new->lc_db = lc_db; 13131ab64890Smrg new->database = database; 13141ab64890Smrg new->ref_count = 1; 13151ab64890Smrg new->next = _db_list; 13161ab64890Smrg _db_list = new; 13171ab64890Smrg 13181ab64890Smrg Xfree (name); 13191ab64890Smrg return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)lc_db; 13201ab64890Smrg 13211ab64890Smrg err: 13221ab64890Smrg DestroyDatabase(database); 13231ab64890Smrg if (lc_db != (XlcDatabase)NULL) { 1324818534a1Smrg Xfree(lc_db); 13251ab64890Smrg } 13261ab64890Smrg Xfree (name); 13271ab64890Smrg return (XPointer)NULL; 13281ab64890Smrg} 13291ab64890Smrg 13301ab64890Smrg#endif /* NOT_X_ENV */ 1331