home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / evbl0627.zip / everblue_20010627.zip / x11 / Xlc_DB.c < prev    next >
C/C++ Source or Header  |  1999-11-02  |  31KB  |  1,362 lines

  1. /* $TOG: lcDB.c /main/12 1997/06/02 17:27:50 kaleb $ */
  2. /*
  3.  *
  4.  * Copyright IBM Corporation 1993
  5.  *
  6.  * All Rights Reserved
  7.  *
  8.  * License to use, copy, modify, and distribute this software and its
  9.  * documentation for any purpose and without fee is hereby granted,
  10.  * provided that the above copyright notice appear in all copies and that
  11.  * both that copyright notice and this permission notice appear in
  12.  * supporting documentation, and that the name of IBM not be
  13.  * used in advertising or publicity pertaining to distribution of the
  14.  * software without specific, written prior permission.
  15.  *
  16.  * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  17.  * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND 
  18.  * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL
  19.  * IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  20.  * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  21.  * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  22.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  23.  * SOFTWARE.
  24.  *
  25. */
  26. /*
  27.  *  (c) Copyright 1995 FUJITSU LIMITED
  28.  *  This is source code modified by FUJITSU LIMITED under the Joint
  29.  *  Development Agreement for the CDE/Motif PST.
  30.  */
  31. /* $XFree86: xc/lib/X11/lcDB.c,v 3.3.2.4 1998/10/04 13:36:24 hohndel Exp $ */
  32.  
  33.  
  34.  
  35. #ifndef    NOT_X_ENV
  36.  
  37. #include <X11/Xlib.h>
  38. #include <X11/Xresource.h>
  39. #include "Xlib_private.h"
  40. #include "XlcPubI.h"
  41.  
  42. #else    /* NOT_X_ENV */
  43.  
  44. #define    Xmalloc    malloc
  45. #define    Xrealloc    realloc
  46. #define    Xfree    free
  47.  
  48. #endif    /* NOT_X_ENV */
  49.  
  50. /* specifying NOT_X_ENV allows users to just use
  51.    the database parsing routine. */
  52. /* For UDC/VW */
  53. #ifndef    BUFSIZE
  54. #define    BUFSIZE    2048
  55. #endif
  56.  
  57. #ifdef COMMENT
  58. #ifdef  BUFSIZE
  59. #undef BUFSIZE
  60. #endif
  61. #define BUFSIZE 6144 /* 2048*3 */
  62. #endif
  63.  
  64. #include <stdio.h>
  65.  
  66. typedef struct _DatabaseRec {
  67.     char *category;
  68.     char *name;
  69.     char **value;
  70.     int value_num;
  71.     struct _DatabaseRec *next;
  72. } DatabaseRec, *Database;
  73.  
  74. typedef enum {
  75.     S_NULL,    /* outside category */
  76.     S_CATEGORY,    /* inside category */
  77.     S_NAME,    /* has name, expecting values */
  78.     S_VALUE
  79. } ParseState;
  80.  
  81. typedef enum {
  82.     T_NEWLINE,
  83.     T_COMMENT,
  84.     T_SEMICOLON,
  85.     T_DOUBLE_QUOTE,
  86.     T_LEFT_BRACE,
  87.     T_RIGHT_BRACE,
  88.     T_SPACE,
  89.     T_TAB,
  90.     T_BACKSLASH,
  91.     T_NUMERIC_HEX,
  92.     T_NUMERIC_DEC,
  93.     T_NUMERIC_OCT,
  94.     T_DEFAULT
  95. } Token;
  96.  
  97. typedef struct {
  98.     Token token;    /* token id */
  99.     char *name;        /* token sequence */
  100.     int len;        /* length of token sequence */
  101.     int (*parse_proc)(); /* parsing procedure */
  102. } TokenTable;
  103.  
  104. static int f_newline();
  105. static int f_comment();
  106. static int f_semicolon();
  107. static int f_double_quote();
  108. static int f_left_brace();
  109. static int f_right_brace();
  110. static int f_white();
  111. static int f_backslash();
  112. static int f_numeric();
  113. static int f_default();
  114.  
  115. static TokenTable token_tbl[] = {
  116.     { T_NEWLINE,    "\n",    1,    f_newline },
  117.     { T_COMMENT,    "#",    1,    f_comment },
  118.     { T_SEMICOLON,    ";",    1,    f_semicolon },
  119.     { T_DOUBLE_QUOTE,    "\"",    1,    f_double_quote },
  120.     { T_LEFT_BRACE,    "{",    1,    f_left_brace },
  121.     { T_RIGHT_BRACE,    "}",    1,    f_right_brace },
  122.     { T_SPACE,        " ",    1,    f_white },
  123.     { T_TAB,        "\t",    1,    f_white },
  124.     { T_BACKSLASH,    "\\",    1,    f_backslash },
  125.     { T_NUMERIC_HEX,    "\\x",    2,    f_numeric },
  126.     { T_NUMERIC_DEC,    "\\d",    2,    f_numeric },
  127.     { T_NUMERIC_OCT,    "\\o",    2,    f_numeric },
  128.     { T_DEFAULT,    " ",    1,    f_default },    /* any character */
  129.     0 
  130. };
  131.  
  132. #define    SYM_CR          '\r'
  133. #define    SYM_NEWLINE    '\n'
  134. #define    SYM_COMMENT    '#'
  135. #define    SYM_SEMICOLON    ';'
  136. #define    SYM_DOUBLE_QUOTE    '"'
  137. #define    SYM_LEFT_BRACE    '{'
  138. #define    SYM_RIGHT_BRACE    '}'
  139. #define    SYM_SPACE    ' '
  140. #define    SYM_TAB        '\t'
  141. #define    SYM_BACKSLASH    '\\'
  142.  
  143. /************************************************************************/
  144.  
  145. #define MAX_NAME_NEST    64
  146.  
  147. typedef struct {
  148.     ParseState pre_state;
  149.     char *category;
  150.     char *name[MAX_NAME_NEST];
  151.     int nest_depth;
  152.     char **value;
  153.     int value_len;
  154.     int value_num;
  155.     int bufsize;        /* bufMaxSize >= bufsize >= 0 */
  156.     int bufMaxSize;     /* default : BUFSIZE */
  157.     char *buf;
  158. } DBParseInfo;
  159.  
  160. static DBParseInfo parse_info;
  161.  
  162. static void init_parse_info()
  163. {
  164.     DBUG_ENTER("init_parse_info")
  165.     static int first = 1;
  166.     char *ptr;
  167.     int  size;
  168.     if(first == 1){
  169.     bzero(&parse_info, sizeof(DBParseInfo));
  170.     parse_info.buf = (char *)Xmalloc(BUFSIZE);
  171.     parse_info.bufMaxSize = BUFSIZE;
  172.     first = 0;
  173.     DBUG_VOID_RETURN;
  174.     }
  175.     ptr = parse_info.buf;
  176.     size = parse_info.bufMaxSize;
  177.     bzero(&parse_info, sizeof(DBParseInfo));
  178.     parse_info.buf = ptr;
  179.     parse_info.bufMaxSize = size;
  180.     DBUG_VOID_RETURN;
  181. }
  182.  
  183. static void
  184. clear_parse_info()
  185. {
  186.     DBUG_ENTER("clear_parse_info")
  187.     int i;
  188.     char *ptr;
  189.     int size;
  190.     parse_info.pre_state = S_NULL;
  191.     if(parse_info.category != NULL){
  192.     Xfree(parse_info.category);
  193.     }
  194.     for(i = 0; i <= parse_info.nest_depth; ++i){
  195.     if(parse_info.name[i]){
  196.         Xfree(parse_info.name[i]);
  197.     }
  198.     }
  199.     if(parse_info.value){
  200.     if(*parse_info.value){
  201.         Xfree(*parse_info.value);
  202.     }
  203.     Xfree((char *)parse_info.value);
  204.     }
  205.     ptr = parse_info.buf;
  206.     size = parse_info.bufMaxSize;
  207.     bzero(&parse_info, sizeof(DBParseInfo));
  208.     parse_info.buf = ptr;
  209.     parse_info.bufMaxSize = size;
  210.     DBUG_VOID_RETURN;
  211. }
  212.  
  213. static Bool
  214. realloc_parse_info(len)
  215. int len;
  216. {
  217.     DBUG_ENTER("realloc_parse_info")
  218.     char *p;
  219.  
  220.     parse_info.bufMaxSize = BUFSIZE * 
  221.         ((parse_info.bufsize + len)/BUFSIZE + 1);
  222.     p = (char *)Xrealloc(parse_info.buf, parse_info.bufMaxSize);
  223.     if(p == NULL){
  224.         DBUG_RETURN(False);
  225.     }
  226.     parse_info.buf = p;
  227.  
  228.     DBUG_RETURN(True);
  229. }
  230. /************************************************************************/
  231. typedef struct _Line {
  232.     char *str;
  233.     int cursize;
  234.     int maxsize;
  235.     int seq;
  236. } Line;
  237.  
  238. static void
  239. free_line(line)
  240.     Line *line;
  241. {
  242.     DBUG_ENTER("free_line")
  243.     if(line->str != NULL){
  244.     Xfree(line->str);
  245.     }
  246.     bzero(line, sizeof(Line));
  247.     DBUG_VOID_RETURN;
  248. }
  249.  
  250. static int
  251. realloc_line(line, size)
  252.     Line *line;
  253.     int size;
  254. {
  255.     DBUG_ENTER("realloc_line")
  256.     char *str = line->str;
  257.  
  258.     if(str != NULL){
  259.     str = (char *)Xrealloc(str, size);
  260.     }else{
  261.     str = (char *)Xmalloc(size);
  262.     }
  263.     if(str == NULL){
  264.     /* malloc error */
  265.     if (line->str != NULL) {
  266.         Xfree(line->str);
  267.     }
  268.     bzero(line, sizeof(Line));
  269.     DBUG_RETURN(0);
  270.     }
  271.     line->str = str;
  272.     line->maxsize = size;
  273.     DBUG_RETURN(1);
  274. }
  275.  
  276. #define    iswhite(ch)    ((ch) == SYM_SPACE   || (ch) == SYM_TAB)
  277.  
  278. static void
  279. zap_comment(str, quoted)
  280.     char *str;
  281.     int *quoted;
  282. {
  283.     DBUG_ENTER("zap_comment")
  284.     char *p = str;
  285. #ifdef    never
  286.     *quoted = 0;
  287.     if(*p == SYM_COMMENT){
  288.     int len = strlen(str);
  289.     if(p[len - 1] == SYM_NEWLINE || p[len - 1] == SYM_CR){
  290.         *p++ = SYM_NEWLINE;
  291.     }
  292.     *p = '\0';
  293.     }
  294. #else
  295.     while(*p){
  296.     if(*p == SYM_DOUBLE_QUOTE){
  297.         if(p == str || p[-1] != SYM_BACKSLASH){
  298.         /* unescaped double quote changes quoted state. */
  299.         *quoted = *quoted ? 0 : 1;
  300.         }
  301.     }
  302.     if(*p == SYM_COMMENT && !*quoted){
  303.         int pos = p - str;
  304.         if(pos == 0 ||
  305.            iswhite(p[-1]) && (pos == 1 || p[-2] != SYM_BACKSLASH)){
  306.         int len = strlen(p);
  307.         if(len > 0 && (p[len - 1] == SYM_NEWLINE || p[len-1] == SYM_CR)) {
  308.             /* newline is the identifier for finding end of value.
  309.                therefore, it should not be removed. */
  310.             *p++ = SYM_NEWLINE;
  311.         }
  312.         *p = '\0';
  313.         break;
  314.         }
  315.     }
  316.     ++p;
  317.     }
  318. #endif
  319.     DBUG_VOID_RETURN;
  320. }
  321.  
  322. static int
  323. read_line(fd, line)
  324.     FILE *fd;
  325.     Line *line;
  326. {
  327.     DBUG_ENTER("read_line")
  328.     char buf[BUFSIZE], *p;
  329.     int len;
  330.     int quoted = 0;    /* quoted by double quote? */
  331.     char *str;
  332.     int cur;
  333.  
  334.     str = line->str;
  335.     cur = line->cursize = 0;
  336.  
  337.     while((p = fgets(buf, BUFSIZE, fd)) != NULL){
  338.     ++line->seq;
  339.     zap_comment(p, "ed);    /* remove comment line */
  340.     len = strlen(p);
  341.     if(len == 0){
  342.         if(cur > 0){
  343.         break;
  344.         }
  345.         continue;
  346.     }
  347.     if(cur + len + 1 > line->maxsize){
  348.         /* need to reallocate buffer. */
  349.         if(! realloc_line(line, line->maxsize + BUFSIZE)){
  350.         goto err;    /* realloc error. */
  351.         }
  352.         str = line->str;
  353.     }
  354.     strncpy(str + cur, p, len);
  355.  
  356.     cur += len;
  357.     str[cur] = '\0';
  358. #ifdef __EMX__  /* Take out carriage returns under OS/2 */
  359.     if(cur>1) {
  360.        if(str[cur-2] == '\r' && str[cur-1] == '\n'){
  361.           str[cur-2] = '\n';
  362.           str[cur-1] = '\0';
  363.           cur--;
  364.        }
  365.     }
  366. #endif
  367.     if(!quoted){
  368.         if(cur > 1 && str[cur - 2] == SYM_BACKSLASH &&
  369.            (str[cur - 1] == SYM_NEWLINE || str[cur-1] == SYM_CR)){
  370.         /* the line is ended backslash followed by newline.
  371.            need to concatinate the next line. */
  372.         cur -= 2;
  373.         str[cur] = '\0';
  374.         }else{
  375.         break;
  376.         }
  377.     }
  378.     }
  379.     if(quoted){
  380.     /* error.  still in quoted state. */
  381.     goto err;
  382.     }
  383.     line->cursize = cur;
  384.     DBUG_RETURN(cur);
  385.  
  386.  err:;
  387.     DBUG_RETURN(-1);
  388. }
  389.  
  390. /************************************************************************/
  391.  
  392. static Token
  393. get_token(str)
  394.     char *str;
  395. {
  396.     DBUG_ENTER("get_token")
  397.     switch(*str){
  398.     case SYM_NEWLINE:
  399.     case SYM_CR:    DBUG_RETURN(T_NEWLINE);
  400.     case SYM_COMMENT:    DBUG_RETURN(T_COMMENT);
  401.     case SYM_SEMICOLON:    DBUG_RETURN(T_SEMICOLON);
  402.     case SYM_DOUBLE_QUOTE:    DBUG_RETURN(T_DOUBLE_QUOTE);
  403.     case SYM_LEFT_BRACE:    DBUG_RETURN(T_LEFT_BRACE);
  404.     case SYM_RIGHT_BRACE:    DBUG_RETURN(T_RIGHT_BRACE);
  405.     case SYM_SPACE:    DBUG_RETURN(T_SPACE);
  406.     case SYM_TAB:    DBUG_RETURN(T_TAB);
  407.     case SYM_BACKSLASH:
  408.     switch(str[1]){
  409.     case 'x': DBUG_RETURN(T_NUMERIC_HEX);
  410.     case 'd': DBUG_RETURN(T_NUMERIC_DEC);
  411.     case 'o': DBUG_RETURN(T_NUMERIC_OCT);
  412.     }
  413.     DBUG_RETURN(T_BACKSLASH);
  414.     default:
  415.     DBUG_RETURN(T_DEFAULT);
  416.     }
  417. }
  418.  
  419. #define CHECKWORD(n) \
  420.     if (w - word + (n) >= size - 1) {*word = 0; return 0;} else
  421.  
  422. static int
  423. get_word(str, word, size)
  424.     char *str;
  425.     char *word;
  426.     int size;
  427. {
  428.     DBUG_ENTER("get_word")
  429.     char *p = str, *w = word;
  430.     Token token;
  431.     int token_len;
  432.  
  433.     while(*p != '\0'){
  434.     token = get_token(p);
  435.     token_len = token_tbl[token].len;
  436.     if(token == T_BACKSLASH){
  437.         p += token_len;
  438.         if(*p == '\0'){
  439.         break;
  440.         }
  441.         token = get_token(p);
  442.         token_len = token_tbl[token].len;
  443.     }else if(token != T_COMMENT &&
  444.          token != T_DEFAULT){
  445.         break;
  446.     }
  447.     CHECKWORD(token_len);
  448.     strncpy(w, p, token_len);
  449.     p += token_len; w += token_len;
  450.     }
  451.     *w = '\0';
  452.     DBUG_RETURN(p - str);    /* return number of scanned chars */
  453. }
  454.  
  455. static int
  456. get_quoted_word(str, word, size)
  457.     char *str;
  458.     char *word;
  459.     int size;
  460. {
  461.     DBUG_ENTER("get_quoted_word")
  462.     char *p = str, *w = word;
  463.     Token token;
  464.     int token_len;
  465.  
  466.     if(*p == SYM_DOUBLE_QUOTE){
  467.     ++p;
  468.     }
  469.     while(*p != '\0'){
  470.     token = get_token(p);
  471.     token_len = token_tbl[token].len;
  472.     if(token == T_DOUBLE_QUOTE){
  473.         p += token_len;
  474.         goto found;
  475.     }
  476.     if(token == T_BACKSLASH){
  477.         p += token_len;
  478.         if(*p == '\0'){
  479.         break;
  480.         }
  481.         token = get_token(p);
  482.         token_len = token_tbl[token].len;
  483.     }
  484.     CHECKWORD(token_len);
  485.     strncpy(w, p, token_len);
  486.     p += token_len; w += token_len;
  487.     }
  488.     /* error. cannot detect next double quote */
  489.     DBUG_RETURN(0);
  490.  
  491.  found:;
  492.     *w = '\0';
  493.     DBUG_RETURN(p - str);
  494. }
  495.  
  496. /************************************************************************/
  497.  
  498. static int
  499. append_value_list()
  500. {
  501.     DBUG_ENTER("append_value_list")
  502.     char **value_list = parse_info.value;
  503.     char *value;
  504.     int value_num = parse_info.value_num;
  505.     int value_len = parse_info.value_len;
  506.     char *str = parse_info.buf;
  507.     int len = parse_info.bufsize;
  508.     char *p;
  509.  
  510.     if(len < 1){
  511.     DBUG_RETURN(1); /* return with no error */
  512.     }
  513.  
  514.     if(value_list == (char **)NULL){
  515.     value_list = (char **)Xmalloc(sizeof(char *) * 2);
  516.     *value_list = NULL;
  517.     }else{
  518.     char **prev_list = value_list;
  519.  
  520.     value_list = (char **)
  521.         Xrealloc(value_list, sizeof(char *) * (value_num + 2));
  522.     if (value_list == NULL){
  523.         Xfree(prev_list);
  524.     }
  525.     }
  526.     if(value_list == (char **)NULL){
  527.     goto err;
  528.     }
  529.  
  530.     value = *value_list;
  531.     if(value == NULL){
  532.     value = (char *)Xmalloc(value_len + len + 1);
  533.     }else{
  534.     char *prev_value = value;
  535.  
  536.     value = (char *)Xrealloc(value, value_len + len + 1);
  537.     if (value == NULL){
  538.         Xfree(prev_value);
  539.     }
  540.     }
  541.     if(value == NULL){
  542.     goto err;
  543.     }
  544.     if(value != *value_list){
  545.     int delta, i;
  546.     delta = value - *value_list;
  547.     *value_list = value;
  548.     for(i = 1; i < value_num; ++i){
  549.         value_list[i] += delta;
  550.     }
  551.     }
  552.  
  553.     value_list[value_num] = p = &value[value_len];
  554.     value_list[value_num + 1] = NULL;
  555.     strncpy(p, str, len);
  556.     p[len] = 0;
  557.  
  558.     parse_info.value = value_list;
  559.     parse_info.value_num = value_num + 1;
  560.     parse_info.value_len = value_len + len + 1;
  561.     parse_info.bufsize = 0;
  562.     DBUG_RETURN(1);
  563.  
  564.  err:;
  565.     if(value_list){
  566.     Xfree((char **)value_list);
  567.     }
  568.     if(value){
  569.     Xfree(value);
  570.     }
  571.     parse_info.value = (char **)NULL;
  572.     parse_info.value_num = 0;
  573.     parse_info.value_len = 0;
  574.     parse_info.bufsize = 0;
  575.     DBUG_RETURN(0);
  576. }
  577.  
  578. static int 
  579. construct_name(name, size)
  580.     char *name;
  581.     int size;
  582. {
  583.     DBUG_ENTER("construct_name")
  584.     register int i, len = 0;
  585.     char *p = name;
  586.  
  587.     for(i = 0; i <= parse_info.nest_depth; ++i){
  588.     len += strlen(parse_info.name[i]) + 1;
  589.     }
  590.     if (len >= size)
  591.     DBUG_RETURN(0);
  592.  
  593.     strcpy(p, parse_info.name[0]);
  594.     p += strlen(parse_info.name[0]);
  595.     for(i = 1; i <= parse_info.nest_depth; ++i){
  596.     *p++ = '.';
  597.     strcpy(p, parse_info.name[i]);
  598.     p += strlen(parse_info.name[i]);
  599.     }
  600.     DBUG_RETURN(*name != '\0');
  601. }
  602.  
  603. static int
  604. store_to_database(db)
  605.     Database *db;
  606. {
  607.     DBUG_ENTER("store_to_database")
  608.     Database new = (Database)NULL;
  609.     char name[BUFSIZE];
  610.  
  611.     if(parse_info.pre_state == S_VALUE){
  612.     if(! append_value_list()){
  613.         goto err;
  614.     }
  615.     }
  616.  
  617.     if(parse_info.name[parse_info.nest_depth] == NULL){
  618.     goto err;
  619.     }
  620.  
  621.     new = (Database)Xmalloc(sizeof(DatabaseRec));
  622.     if(new == (Database)NULL){
  623.     goto err;
  624.     }
  625.     bzero(new, sizeof(DatabaseRec));
  626.  
  627.     new->category = (char *)Xmalloc(strlen(parse_info.category) + 1);
  628.     if(new->category == NULL){
  629.     goto err;
  630.     }
  631.     strcpy(new->category, parse_info.category);
  632.  
  633.     if(! construct_name(name, sizeof(name))){
  634.     goto err;
  635.     }
  636.     new->name = (char *)Xmalloc(strlen(name) + 1);
  637.     if(new->name == NULL){
  638.     goto err;
  639.     }
  640.     strcpy(new->name, name);
  641.     new->next = *db;
  642.     new->value = parse_info.value;
  643.     new->value_num = parse_info.value_num;
  644.     *db = new;
  645.  
  646.     Xfree(parse_info.name[parse_info.nest_depth]);
  647.     parse_info.name[parse_info.nest_depth] = NULL;
  648.  
  649.     parse_info.value = (char **)NULL;
  650.     parse_info.value_num = 0;
  651.     parse_info.value_len = 0;
  652.  
  653.     DBUG_RETURN(1);
  654.  
  655.  err:;
  656.     if(new){
  657.     if(new->category){
  658.         Xfree(new->category);
  659.     }
  660.     if(new->name){
  661.         Xfree(new->name);
  662.     }
  663.     }
  664.     if(parse_info.value){
  665.     if(*parse_info.value){
  666.         Xfree(*parse_info.value);
  667.     }
  668.     Xfree((char **)parse_info.value);
  669.     parse_info.value = (char **)NULL;
  670.     parse_info.value_num = 0;
  671.     parse_info.value_len = 0;
  672.     }
  673.     DBUG_RETURN(0);
  674. }
  675.  
  676. #define END_MARK    "END"
  677. #define    END_MARK_LEN    3 /*strlen(END_MARK)*/
  678.  
  679. static int
  680. check_category_end(str)
  681.     char *str;
  682. {
  683.     DBUG_ENTER("check_category_end")
  684.     char *p;
  685.     int len;
  686.  
  687.     p = str;
  688.     if(strncmp(p, END_MARK, END_MARK_LEN)){
  689.     DBUG_RETURN(0);
  690.     }
  691.     p += END_MARK_LEN;
  692.  
  693.     while(iswhite(*p)){
  694.     ++p;
  695.     }
  696.     len = strlen(parse_info.category);
  697.     if(strncmp(p, parse_info.category, len)){
  698.     DBUG_RETURN(0);
  699.     }
  700.     p += len;
  701.     DBUG_RETURN(p - str);
  702. }
  703.  
  704. /************************************************************************/
  705.  
  706. static int
  707. f_newline(str, token, db)
  708.     char *str;
  709.     Token token;
  710.     Database *db;
  711. {
  712.     DBUG_ENTER("f_newline")
  713.     switch(parse_info.pre_state){
  714.     case S_NULL:
  715.     case S_CATEGORY:
  716.     break;
  717.     case S_NAME:
  718.     goto err; /* no value */
  719.     case S_VALUE:
  720.     if(!store_to_database(db)){
  721.         goto err;
  722.     }
  723.     parse_info.pre_state = S_CATEGORY;
  724.     break;
  725.     default:
  726.     goto err;
  727.     }
  728.     DBUG_RETURN(token_tbl[token].len);
  729.  
  730.  err:;
  731.     DBUG_RETURN(0);
  732. }
  733.  
  734. static int
  735. f_comment(str, token, db)
  736.     char *str;
  737.     Token token;
  738.     Database *db;
  739. {
  740.     DBUG_ENTER("f_comment")
  741.     /* NOTE: comment is already handled in read_line(),
  742.        so this function is not necessary. */
  743.  
  744.     char *p = str;
  745.  
  746.     while(*p != SYM_NEWLINE && *p != SYM_CR && *p != '\0'){
  747.     ++p;    /* zap to the end of line */
  748.     }
  749.     DBUG_RETURN(p - str);
  750. }
  751.  
  752. static int
  753. f_white(str, token, db)
  754.     char *str;
  755.     Token token;
  756.     Database *db;
  757. {
  758.     DBUG_ENTER("f_white")
  759.     char *p = str;
  760.  
  761.     while(iswhite(*p)){
  762.     ++p;
  763.     }
  764.     DBUG_RETURN(p - str);
  765. }
  766.  
  767. static int
  768. f_semicolon(str, token, db)
  769.     char *str;
  770.     Token token;
  771.     Database *db;
  772. {
  773.     DBUG_ENTER("f_semicolon")
  774.     switch(parse_info.pre_state){
  775.     case S_NULL:
  776.     case S_CATEGORY:
  777.     case S_NAME:
  778.     goto err;
  779.     case S_VALUE:
  780.     if(! append_value_list()){
  781.         goto err;
  782.     }
  783.     parse_info.pre_state = S_VALUE;
  784.     break;
  785.     default:
  786.     goto err;
  787.     }
  788.     DBUG_RETURN(token_tbl[token].len);
  789.  
  790.  err:;
  791.     DBUG_RETURN(0);
  792. }
  793.  
  794. static int
  795. f_left_brace(str, token, db)
  796.     char *str;
  797.     Token token;
  798.     Database *db;
  799. {
  800.     DBUG_ENTER("f_left_brace")
  801.     switch(parse_info.pre_state){
  802.     case S_NULL:
  803.     case S_CATEGORY:
  804.     goto err;
  805.     case S_NAME:
  806.     if(parse_info.name[parse_info.nest_depth] == NULL ||
  807.        parse_info.nest_depth + 1 > MAX_NAME_NEST){
  808.         goto err;
  809.     }
  810.     ++parse_info.nest_depth;
  811.     parse_info.pre_state = S_CATEGORY;
  812.     break;
  813.     case S_VALUE:
  814.     default:
  815.     goto err;
  816.     }
  817.     DBUG_RETURN(token_tbl[token].len);
  818.  
  819.  err:
  820.     DBUG_RETURN(0);
  821. }
  822.  
  823. static int
  824. f_right_brace(str, token, db)
  825.     char *str;
  826.     Token token;
  827.     Database *db;
  828. {
  829.     DBUG_ENTER("f_right_brace")
  830.     if(parse_info.nest_depth < 1){
  831.     goto err;
  832.     }
  833.  
  834.     switch(parse_info.pre_state){
  835.     case S_NULL:
  836.     case S_NAME:
  837.     goto err;
  838.     case S_VALUE:
  839.     if(! store_to_database(db)){
  840.         goto err;
  841.     }
  842.     /* fall into next case */
  843.     case S_CATEGORY:
  844.     if(parse_info.name[parse_info.nest_depth] != NULL){
  845.         Xfree(parse_info.name[parse_info.nest_depth]);
  846.         parse_info.name[parse_info.nest_depth] = NULL;
  847.     }
  848.     --parse_info.nest_depth;
  849.     parse_info.pre_state = S_CATEGORY;
  850.     break;
  851.     default:
  852.     goto err;
  853.     }
  854.     DBUG_RETURN(token_tbl[token].len);
  855.  
  856.  err:;
  857.     DBUG_RETURN(0);
  858. }
  859.  
  860. static int
  861. f_double_quote(str, token, db)
  862.     char *str;
  863.     Token token;
  864.     Database *db;
  865. {
  866.     DBUG_ENTER("f_double_quote")
  867.     char word[BUFSIZE];
  868.     int len = 0;
  869.  
  870.     switch(parse_info.pre_state){
  871.     case S_NULL:
  872.     case S_CATEGORY:
  873.     goto err;
  874.     case S_NAME:
  875.     case S_VALUE:
  876.     len = get_quoted_word(str, word, sizeof(word));
  877.     if(len < 1){
  878.         goto err;
  879.     }
  880.     if( (parse_info.bufsize + (int)strlen(word) +1) 
  881.                     >= parse_info.bufMaxSize){
  882.         if(realloc_parse_info(strlen(word) +1) == False){
  883.         goto err;
  884.         }
  885.     }
  886.     strcpy(&parse_info.buf[parse_info.bufsize], word);
  887.     parse_info.bufsize += strlen(word);
  888.     parse_info.pre_state = S_VALUE;
  889.     break;
  890.     default:
  891.     goto err;
  892.     }
  893.     DBUG_RETURN(len);    /* including length of token */
  894.  
  895.  err:;
  896.     DBUG_RETURN(0);
  897. }
  898.  
  899. static int
  900. f_backslash(str, token, db)
  901.     char *str;
  902.     Token token;
  903.     Database *db;
  904. {
  905.     DBUG_ENTER("f_backslash")
  906.     int result = f_default(str, token, db);
  907.     DBUG_RETURN(result);
  908. }
  909.  
  910. static int
  911. f_numeric(str, token, db)
  912.     char *str;
  913.     Token token;
  914.     Database *db;
  915. {
  916.     DBUG_ENTER("f_numeric")
  917.     char word[BUFSIZE], *p;
  918.     int len;
  919.     int token_len;
  920.  
  921.     switch(parse_info.pre_state){
  922.     case S_NULL:
  923.     case S_CATEGORY:
  924.     goto err;
  925.     case S_NAME:
  926.     case S_VALUE:
  927.     token_len = token_tbl[token].len;
  928.     p = str + token_len;
  929.     len = get_word(p, word, sizeof(word));
  930.     if(len < 1){
  931.         goto err;
  932.     }
  933.     if( (parse_info.bufsize + token_len + (int)strlen(word) +1) 
  934.                     >= parse_info.bufMaxSize){
  935.         if(realloc_parse_info(token_len + strlen(word) +1) == False){
  936.         goto err;
  937.         }
  938.     }
  939.     strncpy(&parse_info.buf[parse_info.bufsize], str, token_len);
  940.     strcpy(&parse_info.buf[parse_info.bufsize + token_len], word);
  941.     parse_info.bufsize += token_len + strlen(word);
  942.     parse_info.pre_state = S_VALUE;
  943.     break;
  944.     default:
  945.     goto err;
  946.     }
  947.     DBUG_RETURN(len + token_len);
  948.  
  949.  err:;
  950.     DBUG_RETURN(0);
  951. }
  952.  
  953. static int
  954. f_default(str, token, db)
  955.     char *str;
  956.     Token token;
  957.     Database *db;
  958. {
  959.     DBUG_ENTER("f_default")
  960.     char word[BUFSIZE], *p;
  961.     int len;
  962.  
  963.     len = get_word(str, word, sizeof(word));
  964.     if(len < 1){
  965.     goto err;
  966.     }
  967.  
  968.     switch(parse_info.pre_state){
  969.     case S_NULL:
  970.     if(parse_info.category != NULL){
  971.         goto err;
  972.     }
  973.     p = (char *)Xmalloc(strlen(word) + 1);
  974.     if(p == NULL){
  975.         goto err;
  976.     }
  977.     strcpy(p, word);
  978.     parse_info.category = p;
  979.     parse_info.pre_state = S_CATEGORY;
  980.     break;
  981.     case S_CATEGORY:
  982.     if(parse_info.nest_depth == 0){
  983.         if(check_category_end(str)){
  984.         /* end of category is detected.
  985.            clear context and zap to end of this line */
  986.         clear_parse_info();
  987.         len = strlen(str);
  988.         break;
  989.         }
  990.     }
  991.     p = (char *)Xmalloc(strlen(word) + 1);
  992.     if(p == NULL){
  993.         goto err;
  994.     }
  995.     strcpy(p, word);
  996.     if(parse_info.name[parse_info.nest_depth] != NULL){
  997.         Xfree(parse_info.name[parse_info.nest_depth]);
  998.     }
  999.     parse_info.name[parse_info.nest_depth] = p;
  1000.     parse_info.pre_state = S_NAME;
  1001.     break;
  1002.     case S_NAME:
  1003.     case S_VALUE:
  1004.     if( (parse_info.bufsize + (int)strlen(word) +1 ) 
  1005.                     >= parse_info.bufMaxSize){
  1006.         if(realloc_parse_info(strlen(word) +1) == False){
  1007.         goto err;
  1008.         }
  1009.     }
  1010.     strcpy(&parse_info.buf[parse_info.bufsize], word);
  1011.     parse_info.bufsize += strlen(word);
  1012.     parse_info.pre_state = S_VALUE;
  1013.     break;
  1014.     default:
  1015.     goto err;
  1016.     }
  1017.     DBUG_RETURN(len);
  1018.  
  1019.  err:;
  1020.     DBUG_RETURN(0);
  1021. }
  1022.  
  1023. /************************************************************************/
  1024.  
  1025. #ifdef    DEBUG
  1026. static void
  1027. PrintDatabase(db)
  1028.     Database db;
  1029. {
  1030.     DBUG_ENTER("PrintDatabase")
  1031. #ifdef VERBOSE
  1032.     Database p = db;
  1033.     int i = 0, j;
  1034.  
  1035.     printf("***\n*** BEGIN Database\n***\n");
  1036.     while(p){
  1037.     printf("%3d: ", i++);
  1038.     printf("%s, %s, ", p->category, p->name);
  1039.     printf("\t[%d: ", p->value_num);
  1040.     for(j = 0; j < p->value_num; ++j){
  1041.         printf("%s, ", p->value[j]);
  1042.     }
  1043.     printf("]\n");
  1044.     p = p->next;
  1045.     }
  1046.     printf("***\n*** END   Database\n***\n");
  1047. #endif
  1048.     DBUG_VOID_RETURN;
  1049. }
  1050. #endif
  1051.  
  1052. static void
  1053. DestroyDatabase(db)
  1054.     Database db;
  1055. {
  1056.     DBUG_ENTER("DestroyDatabase")
  1057.     Database p = db;
  1058.  
  1059.     while(p){
  1060.     if(p->category != NULL){
  1061.         Xfree(p->category);
  1062.     }
  1063.     if(p->name != NULL){
  1064.         Xfree(p->name);
  1065.     }
  1066.     if(p->value != (char **)NULL){
  1067.         if(*p->value != NULL){
  1068.         Xfree(*p->value);
  1069.         }
  1070.         Xfree((char *)p->value);
  1071.     }
  1072.     db = p->next;
  1073.     Xfree((char *)p);
  1074.     p = db;
  1075.     }
  1076.     DBUG_VOID_RETURN;
  1077. }
  1078.  
  1079. static int
  1080. CountDatabase(db)
  1081.     Database db;
  1082. {
  1083.     DBUG_ENTER("CountDatabase")
  1084.     Database p = db;
  1085.     int cnt = 0;
  1086.  
  1087.     while(p){
  1088.     ++cnt;
  1089.     p = p->next;
  1090.     }
  1091.     DBUG_RETURN(cnt);
  1092. }
  1093.  
  1094. static Database
  1095. CreateDatabase(dbfile)
  1096.     char *dbfile;
  1097. {
  1098.     DBUG_ENTER("CreateDatabase")
  1099.     Database db = (Database)NULL;
  1100.     FILE *fd;
  1101.     Line line;
  1102.     char *p;
  1103.     Token token;
  1104.     int len;
  1105.     int error = 0;
  1106.  
  1107.     fd = fopen(dbfile, "r");
  1108.     if(fd == (FILE *)NULL){
  1109.     DBUG_RETURN(NULL);
  1110.     }
  1111.  
  1112.     bzero(&line, sizeof(Line));
  1113.     init_parse_info();
  1114.  
  1115.     do {
  1116.     int rc = read_line(fd, &line);
  1117.     if(rc < 0){
  1118.         error = 1;
  1119.         break;
  1120.     }else if(rc == 0){
  1121.         break;
  1122.     }
  1123.     p = line.str;
  1124.     while(*p){
  1125.         token = get_token(p);
  1126.         len = (*token_tbl[token].parse_proc)(p, token, &db);
  1127.         if(len < 1){
  1128.         error = 1;
  1129.         break;
  1130.         }
  1131.         p += len;
  1132.     }
  1133.     } while (!error);
  1134.  
  1135.     if(parse_info.pre_state != S_NULL){
  1136.     clear_parse_info();
  1137.     error = 1;
  1138.     }
  1139.     if(error){
  1140. #if defined(DEBUG) && defined(VERBOSE)
  1141.     fprintf(stderr, "database format error at line %d.\n", line.seq);
  1142. #endif
  1143.     DestroyDatabase(db);
  1144.     db = (Database)NULL;
  1145.     }
  1146.  
  1147.     fclose(fd);
  1148.     free_line(&line);
  1149.  
  1150. #ifdef    DEBUG
  1151.     PrintDatabase(db);
  1152. #endif
  1153.  
  1154.     DBUG_RETURN(db);
  1155. }
  1156.  
  1157. /************************************************************************/
  1158.  
  1159. #ifndef    NOT_X_ENV
  1160.  
  1161. /* locale framework functions */
  1162.  
  1163. typedef struct _XlcDatabaseRec {
  1164.     XrmQuark category_q;
  1165.     XrmQuark name_q;
  1166.     Database db;
  1167.     struct _XlcDatabaseRec *next;
  1168. } XlcDatabaseRec, *XlcDatabase;
  1169.  
  1170. typedef    struct _XlcDatabaseListRec {
  1171.     XrmQuark name_q;
  1172.     XlcDatabase lc_db;
  1173.     Database database;
  1174.     int ref_count;
  1175.     struct _XlcDatabaseListRec *next;
  1176. } XlcDatabaseListRec, *XlcDatabaseList;
  1177.  
  1178. /* database cache list (per file) */
  1179. static XlcDatabaseList _db_list = (XlcDatabaseList)NULL;
  1180.  
  1181. /************************************************************************/
  1182. /*    _XlcGetResource(lcd, category, class, value, count)        */
  1183. /*----------------------------------------------------------------------*/
  1184. /*    This function retrieves XLocale database information.        */
  1185. /************************************************************************/
  1186. void
  1187. _XlcGetResource(lcd, category, class, value, count)
  1188.     XLCd lcd;
  1189.     char *category;
  1190.     char *class;
  1191.     char ***value;
  1192.     int *count;
  1193. {
  1194.     DBUG_ENTER("_XlcGetResource")
  1195.     XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd);
  1196.  
  1197.     (*methods->get_resource)(lcd, category, class, value, count);
  1198.     DBUG_VOID_RETURN;
  1199. }
  1200.  
  1201. /************************************************************************/
  1202. /*    _XlcGetLocaleDataBase(lcd, category, class, value, count)    */
  1203. /*----------------------------------------------------------------------*/
  1204. /*    This function retrieves XLocale database information.        */
  1205. /************************************************************************/
  1206. void
  1207. _XlcGetLocaleDataBase(lcd, category, name, value, count)
  1208.     XLCd lcd;
  1209.     char *category;
  1210.     char *name;
  1211.     char ***value;
  1212.     int *count;
  1213. {
  1214.     DBUG_ENTER("_XlcGetLocaleDataBase")
  1215.     XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
  1216.     XrmQuark category_q, name_q;
  1217.  
  1218.     category_q = XrmStringToQuark(category);
  1219.     name_q = XrmStringToQuark(name);
  1220.     for(; lc_db->db; ++lc_db){
  1221.     if(category_q == lc_db->category_q && name_q == lc_db->name_q){
  1222.         *value = lc_db->db->value;
  1223.         *count = lc_db->db->value_num;
  1224.         DBUG_VOID_RETURN;
  1225.     }
  1226.     }
  1227.     *value = (char **)NULL;
  1228.     *count = 0;
  1229.     DBUG_VOID_RETURN;
  1230. }
  1231.  
  1232. /************************************************************************/
  1233. /*    _XlcDestroyLocaleDataBase(lcd)                    */
  1234. /*----------------------------------------------------------------------*/
  1235. /*    This function destroy the XLocale Database that bound to the     */
  1236. /*    specified lcd.  If the XLocale Database is refered from some     */
  1237. /*    other lcd, this function just decreases reference count of     */
  1238. /*    the database.  If no locale refers the database, this function    */
  1239. /*    remove it from the cache list and free work area.        */
  1240. /************************************************************************/
  1241. void
  1242. _XlcDestroyLocaleDataBase(lcd)
  1243.     XLCd lcd;
  1244. {
  1245.     DBUG_ENTER("_XlcDestroyLocaleDataBase")
  1246.     XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
  1247.     XlcDatabaseList p, prev;
  1248.  
  1249.     for(p = _db_list, prev = (XlcDatabaseList)NULL; p;
  1250.     prev = p, p = p->next){
  1251.     if(p->lc_db == lc_db){
  1252.         if((-- p->ref_count) < 1){
  1253.         if(p->lc_db != (XlcDatabase)NULL){
  1254.             Xfree((char *)p->lc_db);
  1255.         }
  1256.         DestroyDatabase(p->database);
  1257.         if(prev == (XlcDatabaseList)NULL){
  1258.             _db_list = p->next;
  1259.         }else{
  1260.             prev->next = p->next;
  1261.         }
  1262.         Xfree((char*)p);
  1263.         }
  1264.         break;
  1265.     }
  1266.     }
  1267.     XLC_PUBLIC(lcd, xlocale_db) = (XPointer)NULL;
  1268.     DBUG_VOID_RETURN;
  1269. }
  1270.  
  1271. /************************************************************************/
  1272. /*    _XlcCreateLocaleDataBase(lcd)                    */
  1273. /*----------------------------------------------------------------------*/
  1274. /*    This function create an XLocale database which correspond to    */
  1275. /*    the specified XLCd.                        */
  1276. /************************************************************************/
  1277. XPointer
  1278. _XlcCreateLocaleDataBase(lcd)
  1279.     XLCd lcd;
  1280. {
  1281.     DBUG_ENTER("_XlcCreateLocaleDataBase")
  1282.     XlcDatabaseList list, new;
  1283.     Database p, database = (Database)NULL;
  1284.     XlcDatabase lc_db = (XlcDatabase)NULL;
  1285.     XrmQuark name_q;
  1286.     char *name;
  1287.     int i, n;
  1288.  
  1289.     name = _XlcFileName(lcd, "locale");
  1290.     if(name == NULL){
  1291. #if defined(DEBUG) && defined(VERBOSE)
  1292.     fprintf(stderr,"_XlcCreateLocaleDataBase: _XlcFileName() failed!\n");
  1293. #endif
  1294.     DBUG_RETURN((XPointer)NULL);
  1295.     }
  1296.  
  1297. #ifndef __EMX__
  1298.     name_q = XrmStringToQuark(name);
  1299. #else
  1300.     name_q = XrmStringToQuark((char*)__XOS2RedirRoot(name));
  1301. #endif
  1302.     for(list = _db_list; list; list = list->next){
  1303.     if(name_q == list->name_q){
  1304.         list->ref_count++;
  1305.         Xfree (name);
  1306.         XLC_PUBLIC(lcd, xlocale_db) = (XPointer)list->lc_db;
  1307.         DBUG_RETURN((XPointer)list->lc_db);
  1308.     }
  1309.     }
  1310.  
  1311.     database = CreateDatabase(name);
  1312.     if(database == (Database)NULL){
  1313. #if defined(DEBUG) && defined(VERBOSE)
  1314.     fprintf(stderr,"_XlcCreateLocaleDataBase: CreateDatabase() failed!\n");
  1315. #endif
  1316.     Xfree (name);
  1317.     DBUG_RETURN((XPointer)NULL);
  1318.     }
  1319.     n = CountDatabase(database);
  1320.     lc_db = (XlcDatabase)Xmalloc(sizeof(XlcDatabaseRec) * (n + 1));
  1321.     if(lc_db == (XlcDatabase)NULL){
  1322. #if defined(DEBUG) && defined(VERBOSE)
  1323.     fprintf(stderr,"_XlcCreateLocaleDataBase: malloc for lc_db failed!\n");
  1324. #endif
  1325.     goto err;
  1326.     }
  1327.     bzero(lc_db, sizeof(XlcDatabaseRec) * (n + 1));
  1328.     for(p = database, i = 0; p && i < n; p = p->next, ++i){
  1329.     lc_db[i].category_q = XrmStringToQuark(p->category);
  1330.     lc_db[i].name_q = XrmStringToQuark(p->name);
  1331.     lc_db[i].db = p;
  1332.     }
  1333.  
  1334.     new = (XlcDatabaseList)Xmalloc(sizeof(XlcDatabaseListRec));
  1335.     if(new == (XlcDatabaseList)NULL){
  1336. #if defined(DEBUG) && defined(VERBOSE)
  1337.     fprintf(stderr,"_XlcCreateLocaleDataBase: malloc for new failed!\n");
  1338. #endif
  1339.     goto err;
  1340.     }
  1341.     new->name_q = name_q;
  1342.     new->lc_db = lc_db;
  1343.     new->database = database;
  1344.     new->ref_count = 1;
  1345.     new->next = _db_list;
  1346.     _db_list = new;
  1347.  
  1348.     Xfree (name);
  1349.     XLC_PUBLIC(lcd, xlocale_db) = (XPointer)lc_db;
  1350.     DBUG_RETURN((XPointer)lc_db);
  1351.  
  1352.  err:
  1353.     DestroyDatabase(database);
  1354.     if(lc_db != (XlcDatabase)NULL){
  1355.     Xfree((char *)lc_db);
  1356.     }
  1357.     Xfree (name);
  1358.     DBUG_RETURN((XPointer)NULL);
  1359. }
  1360.  
  1361. #endif    /* NOT_X_ENV */
  1362.