_fallcDB.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* lcDB.c 1.3 - Fujitsu source for CDEnext 96/02/29 18:02:53 */
  24. /* $XConsortium: _fallcDB.c /main/1 1996/04/08 15:16:07 cde-fuj $ */
  25. /*
  26. *
  27. * Copyright IBM Corporation 1993
  28. *
  29. * All Rights Reserved
  30. *
  31. * License to use, copy, modify, and distribute this software and its
  32. * documentation for any purpose and without fee is hereby granted,
  33. * provided that the above copyright notice appear in all copies and that
  34. * both that copyright notice and this permission notice appear in
  35. * supporting documentation, and that the name of IBM not be
  36. * used in advertising or publicity pertaining to distribution of the
  37. * software without specific, written prior permission.
  38. *
  39. * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  40. * ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS, AND
  41. * NONINFRINGEMENT OF THIRD PARTY RIGHTS, IN NO EVENT SHALL
  42. * IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  43. * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  44. * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  45. * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  46. * SOFTWARE.
  47. *
  48. */
  49. #include "syncx.h"
  50. #include <X11/Xresource.h>
  51. #include "_fallibint.h"
  52. #include "_fallcPubI.h"
  53. /* specifying NOT_X_ENV allows users to just use
  54. the database parsing routine. */
  55. /* For UDC/VW */
  56. #ifndef BUFSIZE
  57. #define BUFSIZE 2048
  58. #endif
  59. #ifdef COMMENT
  60. #ifdef BUFSIZE
  61. #undef BUFSIZE
  62. #endif
  63. #define BUFSIZE 6144 /* 2048*3 */
  64. #endif
  65. #include <stdio.h>
  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. typedef enum {
  74. S_NULL, /* outside category */
  75. S_CATEGORY, /* inside category */
  76. S_NAME, /* has name, expecting values */
  77. S_VALUE
  78. } ParseState;
  79. typedef enum {
  80. T_NEWLINE,
  81. T_COMMENT,
  82. T_SEMICOLON,
  83. T_DOUBLE_QUOTE,
  84. T_LEFT_BRACE,
  85. T_RIGHT_BRACE,
  86. T_SPACE,
  87. T_TAB,
  88. T_BACKSLASH,
  89. T_NUMERIC_HEX,
  90. T_NUMERIC_DEC,
  91. T_NUMERIC_OCT,
  92. T_DEFAULT
  93. } Token;
  94. typedef struct {
  95. Token token; /* token id */
  96. char *name; /* token sequence */
  97. int len; /* length of token sequence */
  98. int (*parse_proc)(); /* parsing procedure */
  99. } TokenTable;
  100. static int f_newline();
  101. static int f_comment();
  102. static int f_semicolon();
  103. static int f_double_quote();
  104. static int f_left_brace();
  105. static int f_right_brace();
  106. static int f_white();
  107. static int f_backslash();
  108. static int f_numeric();
  109. static int f_default();
  110. static TokenTable token_tbl[] = {
  111. { T_NEWLINE, "\n", 1, f_newline },
  112. { T_COMMENT, "#", 1, f_comment },
  113. { T_SEMICOLON, ";", 1, f_semicolon },
  114. { T_DOUBLE_QUOTE, "\"", 1, f_double_quote },
  115. { T_LEFT_BRACE, "{", 1, f_left_brace },
  116. { T_RIGHT_BRACE, "}", 1, f_right_brace },
  117. { T_SPACE, " ", 1, f_white },
  118. { T_TAB, "\t", 1, f_white },
  119. { T_BACKSLASH, "\\", 1, f_backslash },
  120. { T_NUMERIC_HEX, "\\x", 2, f_numeric },
  121. { T_NUMERIC_DEC, "\\d", 2, f_numeric },
  122. { T_NUMERIC_OCT, "\\o", 2, f_numeric },
  123. { T_DEFAULT, " ", 1, f_default }, /* any character */
  124. 0
  125. };
  126. #define SYM_NEWLINE '\n'
  127. #define SYM_COMMENT '#'
  128. #define SYM_SEMICOLON ';'
  129. #define SYM_DOUBLE_QUOTE '"'
  130. #define SYM_LEFT_BRACE '{'
  131. #define SYM_RIGHT_BRACE '}'
  132. #define SYM_SPACE ' '
  133. #define SYM_TAB '\t'
  134. #define SYM_BACKSLASH '\\'
  135. /************************************************************************/
  136. #define MAX_NAME_NEST 64
  137. typedef struct {
  138. ParseState pre_state;
  139. char *category;
  140. char *name[MAX_NAME_NEST];
  141. int nest_depth;
  142. char **value;
  143. int value_len;
  144. int value_num;
  145. int bufsize; /* bufMaxSize >= bufsize >= 0 */
  146. int bufMaxSize; /* default : BUFSIZE */
  147. char *buf;
  148. } DBParseInfo;
  149. static DBParseInfo parse_info;
  150. static void init_parse_info(void)
  151. {
  152. static int first = 1;
  153. char *ptr;
  154. int size;
  155. if(first == 1){
  156. bzero(&parse_info, sizeof(DBParseInfo));
  157. parse_info.buf = (char *)Xmalloc(BUFSIZE);
  158. parse_info.bufMaxSize = BUFSIZE;
  159. first = 0;
  160. return ;
  161. }
  162. ptr = parse_info.buf;
  163. size = parse_info.bufMaxSize;
  164. bzero(&parse_info, sizeof(DBParseInfo));
  165. parse_info.buf = ptr;
  166. parse_info.bufMaxSize = size;
  167. }
  168. static void
  169. clear_parse_info(void)
  170. {
  171. int i;
  172. char *ptr;
  173. int size;
  174. parse_info.pre_state = S_NULL;
  175. if(parse_info.category != NULL){
  176. Xfree(parse_info.category);
  177. }
  178. for(i = 0; i <= parse_info.nest_depth; ++i){
  179. if(parse_info.name[i]){
  180. Xfree(parse_info.name[i]);
  181. }
  182. }
  183. if(parse_info.value){
  184. if(*parse_info.value){
  185. Xfree(*parse_info.value);
  186. }
  187. Xfree((char *)parse_info.value);
  188. }
  189. ptr = parse_info.buf;
  190. size = parse_info.bufMaxSize;
  191. bzero(&parse_info, sizeof(DBParseInfo));
  192. parse_info.buf = ptr;
  193. parse_info.bufMaxSize = size;
  194. }
  195. static Bool
  196. realloc_parse_info(int len)
  197. {
  198. char *p;
  199. parse_info.bufMaxSize = BUFSIZE *
  200. ((parse_info.bufsize + len)/BUFSIZE + 1);
  201. p = (char *)Xrealloc(parse_info.buf, parse_info.bufMaxSize);
  202. if(p == NULL){
  203. return(False);
  204. }
  205. parse_info.buf = p;
  206. return(True);
  207. }
  208. /************************************************************************/
  209. typedef struct _Line {
  210. char *str;
  211. int cursize;
  212. int maxsize;
  213. int seq;
  214. } Line;
  215. static void
  216. free_line(Line *line)
  217. {
  218. if(line->str != NULL){
  219. Xfree(line->str);
  220. }
  221. bzero(line, sizeof(Line));
  222. }
  223. static int
  224. realloc_line(Line *line, int size)
  225. {
  226. char *str = line->str;
  227. if(str != NULL){
  228. str = (char *)Xrealloc(str, size);
  229. }else{
  230. str = (char *)Xmalloc(size);
  231. }
  232. if(str == NULL){
  233. /* malloc error */
  234. bzero(line, sizeof(Line));
  235. return 0;
  236. }
  237. line->str = str;
  238. line->maxsize = size;
  239. return 1;
  240. }
  241. #define iswhite(ch) ((ch) == SYM_SPACE || (ch) == SYM_TAB)
  242. static void
  243. zap_comment(char *str, int *quoted)
  244. {
  245. char *p = str;
  246. while(*p){
  247. if(*p == SYM_DOUBLE_QUOTE){
  248. if(p == str || p[-1] != SYM_BACKSLASH){
  249. /* unescaped double quote changes quoted state. */
  250. *quoted = *quoted ? 0 : 1;
  251. }
  252. }
  253. if(*p == SYM_COMMENT && !*quoted){
  254. int pos = p - str;
  255. if(pos == 0 ||
  256. iswhite(p[-1]) && (pos == 1 || p[-2] != SYM_BACKSLASH)){
  257. int len = strlen(p);
  258. if(len > 0 && p[len - 1] == SYM_NEWLINE){
  259. /* newline is the identifier for finding end of value.
  260. therefore, it should not be removed. */
  261. *p++ = SYM_NEWLINE;
  262. }
  263. *p = '\0';
  264. break;
  265. }
  266. }
  267. ++p;
  268. }
  269. }
  270. static int
  271. read_line(FILE *fd, Line *line)
  272. {
  273. char buf[BUFSIZE], *p;
  274. int len;
  275. int quoted = 0; /* quoted by double quote? */
  276. char *str;
  277. int cur;
  278. str = line->str;
  279. cur = line->cursize = 0;
  280. while((p = fgets(buf, BUFSIZE, fd)) != NULL){
  281. ++line->seq;
  282. zap_comment(p, &quoted); /* remove comment line */
  283. len = strlen(p);
  284. if(len == 0){
  285. if(cur > 0){
  286. break;
  287. }
  288. continue;
  289. }
  290. if(cur + len + 1 > line->maxsize){
  291. /* need to reallocate buffer. */
  292. if(! realloc_line(line, line->maxsize + BUFSIZE)){
  293. return -1; /* realloc error. */
  294. }
  295. str = line->str;
  296. }
  297. strncpy(str + cur, p, len);
  298. cur += len;
  299. str[cur] = '\0';
  300. if(!quoted){
  301. if(cur > 1 && str[cur - 2] == SYM_BACKSLASH &&
  302. str[cur - 1] == SYM_NEWLINE){
  303. /* the line is ended backslash followed by newline.
  304. need to concatinate the next line. */
  305. cur -= 2;
  306. str[cur] = '\0';
  307. }else{
  308. break;
  309. }
  310. }
  311. }
  312. if(quoted){
  313. /* error. still in quoted state. */
  314. return -1;
  315. }
  316. return line->cursize = cur;
  317. }
  318. /************************************************************************/
  319. static Token
  320. get_token(char *str)
  321. {
  322. switch(*str){
  323. case SYM_NEWLINE: return T_NEWLINE;
  324. case SYM_COMMENT: return T_COMMENT;
  325. case SYM_SEMICOLON: return T_SEMICOLON;
  326. case SYM_DOUBLE_QUOTE: return T_DOUBLE_QUOTE;
  327. case SYM_LEFT_BRACE: return T_LEFT_BRACE;
  328. case SYM_RIGHT_BRACE: return T_RIGHT_BRACE;
  329. case SYM_SPACE: return T_SPACE;
  330. case SYM_TAB: return T_TAB;
  331. case SYM_BACKSLASH:
  332. switch(str[1]){
  333. case 'x': return T_NUMERIC_HEX;
  334. case 'd': return T_NUMERIC_DEC;
  335. case 'o': return T_NUMERIC_OCT;
  336. }
  337. return T_BACKSLASH;
  338. default:
  339. return T_DEFAULT;
  340. }
  341. }
  342. static int
  343. get_word(char *str, char *word)
  344. {
  345. char *p = str, *w = word;
  346. Token token;
  347. int token_len;
  348. while(*p != '\0'){
  349. token = get_token(p);
  350. token_len = token_tbl[token].len;
  351. if(token == T_BACKSLASH){
  352. p += token_len;
  353. if(*p == '\0'){
  354. break;
  355. }
  356. token = get_token(p);
  357. token_len = token_tbl[token].len;
  358. }else if(token != T_COMMENT &&
  359. token != T_DEFAULT){
  360. break;
  361. }
  362. strncpy(w, p, token_len);
  363. p += token_len; w += token_len;
  364. }
  365. *w = '\0';
  366. return p - str; /* return number of scanned chars */
  367. }
  368. static int
  369. get_quoted_word(char *str, char *word)
  370. {
  371. char *p = str, *w = word;
  372. Token token;
  373. int token_len;
  374. if(*p == SYM_DOUBLE_QUOTE){
  375. ++p;
  376. }
  377. while(*p != '\0'){
  378. token = get_token(p);
  379. token_len = token_tbl[token].len;
  380. if(token == T_DOUBLE_QUOTE){
  381. p += token_len;
  382. *w = '\0';
  383. return p - str;
  384. }
  385. if(token == T_BACKSLASH){
  386. p += token_len;
  387. if(*p == '\0'){
  388. break;
  389. }
  390. token = get_token(p);
  391. token_len = token_tbl[token].len;
  392. }
  393. strncpy(w, p, token_len);
  394. p += token_len; w += token_len;
  395. }
  396. /* error. cannot detect next double quote */
  397. return 0;
  398. }
  399. /************************************************************************/
  400. static int
  401. append_value_list(void)
  402. {
  403. char **value_list = parse_info.value;
  404. char *value = NULL;
  405. int value_num = parse_info.value_num;
  406. int value_len = parse_info.value_len;
  407. char *str = parse_info.buf;
  408. int len = parse_info.bufsize;
  409. char *p;
  410. if(len < 1){
  411. return 1; /* return with no error */
  412. }
  413. if(value_list == (char **)NULL){
  414. value_list = (char **)Xmalloc(sizeof(char *) * 2);
  415. *value_list = NULL;
  416. }else{
  417. value_list = (char **)
  418. Xrealloc(value_list, sizeof(char *) * (value_num + 2));
  419. }
  420. if(value_list == (char **)NULL){
  421. goto err;
  422. }
  423. value = *value_list;
  424. if(value == NULL){
  425. value = (char *)Xmalloc(value_len + len + 1);
  426. }else{
  427. value = (char *)Xrealloc(value, value_len + len + 1);
  428. }
  429. if(value == NULL){
  430. goto err;
  431. }
  432. if(value != *value_list){
  433. int delta, i;
  434. delta = value - *value_list;
  435. *value_list = value;
  436. for(i = 1; i < value_num; ++i){
  437. value_list[i] += delta;
  438. }
  439. }
  440. value_list[value_num] = p = &value[value_len];
  441. value_list[value_num + 1] = NULL;
  442. strncpy(p, str, len);
  443. p[len] = 0;
  444. parse_info.value = value_list;
  445. parse_info.value_num = value_num + 1;
  446. parse_info.value_len = value_len + len + 1;
  447. parse_info.bufsize = 0;
  448. return 1;
  449. err:
  450. if(value_list){
  451. Xfree((char **)value_list);
  452. }
  453. Xfree(value);
  454. parse_info.value = (char **)NULL;
  455. parse_info.value_num = 0;
  456. parse_info.value_len = 0;
  457. parse_info.bufsize = 0;
  458. return 0;
  459. }
  460. static int
  461. construct_name(char *name)
  462. {
  463. int i, len = 0;
  464. char *p = name;
  465. for(i = 0; i <= parse_info.nest_depth; ++i){
  466. len += strlen(parse_info.name[i]) + 1;
  467. }
  468. strcpy(p, parse_info.name[0]);
  469. p += strlen(parse_info.name[0]);
  470. for(i = 1; i <= parse_info.nest_depth; ++i){
  471. *p++ = '.';
  472. strcpy(p, parse_info.name[i]);
  473. p += strlen(parse_info.name[i]);
  474. }
  475. return *name != '\0';
  476. }
  477. static int
  478. store_to_database(Database *db)
  479. {
  480. Database new = (Database)NULL;
  481. char name[BUFSIZE];
  482. while(1){
  483. if(parse_info.pre_state == S_VALUE){
  484. if(! append_value_list()){
  485. break;
  486. }
  487. }
  488. if(parse_info.name[parse_info.nest_depth] == NULL){
  489. break;
  490. }
  491. new = (Database)Xmalloc(sizeof(DatabaseRec));
  492. if(new == (Database)NULL){
  493. break;
  494. }
  495. bzero(new, sizeof(DatabaseRec));
  496. new->category = (char *)Xmalloc(strlen(parse_info.category) + 1);
  497. if(new->category == NULL){
  498. break;
  499. }
  500. strcpy(new->category, parse_info.category);
  501. if(! construct_name(name)){
  502. break;
  503. }
  504. new->name = (char *)Xmalloc(strlen(name) + 1);
  505. if(new->name == NULL){
  506. break;
  507. }
  508. strcpy(new->name, name);
  509. new->next = *db;
  510. new->value = parse_info.value;
  511. new->value_num = parse_info.value_num;
  512. *db = new;
  513. Xfree(parse_info.name[parse_info.nest_depth]);
  514. parse_info.name[parse_info.nest_depth] = NULL;
  515. parse_info.value = (char **)NULL;
  516. parse_info.value_num = 0;
  517. parse_info.value_len = 0;
  518. return 1;
  519. }
  520. if(new){
  521. if(new->category){
  522. Xfree(new->category);
  523. }
  524. if(new->name){
  525. Xfree(new->name);
  526. }
  527. Xfree(new);
  528. }
  529. if(parse_info.value){
  530. if(*parse_info.value){
  531. Xfree(*parse_info.value);
  532. }
  533. Xfree((char **)parse_info.value);
  534. parse_info.value = (char **)NULL;
  535. parse_info.value_num = 0;
  536. parse_info.value_len = 0;
  537. }
  538. return 0;
  539. }
  540. #define END_MARK "END"
  541. #define END_MARK_LEN 3 /*strlen(END_MARK)*/
  542. static int
  543. check_category_end(char *str)
  544. {
  545. char *p;
  546. int len;
  547. p = str;
  548. if(strncmp(p, END_MARK, END_MARK_LEN)){
  549. return 0;
  550. }
  551. p += END_MARK_LEN;
  552. while(iswhite(*p)){
  553. ++p;
  554. }
  555. len = strlen(parse_info.category);
  556. if(strncmp(p, parse_info.category, len)){
  557. return 0;
  558. }
  559. p += len;
  560. return p - str;
  561. }
  562. /************************************************************************/
  563. static int
  564. f_newline(char *str, Token token, Database *db)
  565. {
  566. switch(parse_info.pre_state){
  567. case S_NULL:
  568. case S_CATEGORY:
  569. break;
  570. case S_NAME:
  571. return 0; /* no value */
  572. case S_VALUE:
  573. if(!store_to_database(db)){
  574. return 0;
  575. }
  576. parse_info.pre_state = S_CATEGORY;
  577. break;
  578. default:
  579. return 0;
  580. }
  581. return token_tbl[token].len;
  582. }
  583. static int
  584. f_comment(char *str, Token token, Database *db)
  585. {
  586. /* NOTE: comment is already handled in read_line(),
  587. so this function is not necessary. */
  588. char *p = str;
  589. while(*p != SYM_NEWLINE && *p != '\0'){
  590. ++p; /* zap to the end of line */
  591. }
  592. return p - str;
  593. }
  594. static int
  595. f_white(char *str, Token token, Database *db)
  596. {
  597. char *p = str;
  598. while(iswhite(*p)){
  599. ++p;
  600. }
  601. return p - str;
  602. }
  603. static int
  604. f_semicolon(char *str, Token token, Database *db)
  605. {
  606. switch(parse_info.pre_state){
  607. case S_NULL:
  608. case S_CATEGORY:
  609. case S_NAME:
  610. return 0;
  611. case S_VALUE:
  612. if(! append_value_list()){
  613. return 0;
  614. }
  615. parse_info.pre_state = S_VALUE;
  616. break;
  617. default:
  618. return 0;
  619. }
  620. return token_tbl[token].len;
  621. }
  622. static int
  623. f_left_brace(char *str, Token token, Database *db)
  624. {
  625. switch(parse_info.pre_state){
  626. case S_NULL:
  627. case S_CATEGORY:
  628. return 0;
  629. case S_NAME:
  630. if(parse_info.name[parse_info.nest_depth] == NULL ||
  631. parse_info.nest_depth + 1 > MAX_NAME_NEST){
  632. return 0;
  633. }
  634. ++parse_info.nest_depth;
  635. parse_info.pre_state = S_CATEGORY;
  636. break;
  637. case S_VALUE:
  638. default:
  639. return 0;
  640. }
  641. return token_tbl[token].len;
  642. }
  643. static int
  644. f_right_brace(char *str, Token token, Database *db)
  645. {
  646. if(parse_info.nest_depth < 1){
  647. return 0;
  648. }
  649. switch(parse_info.pre_state){
  650. case S_NULL:
  651. case S_NAME:
  652. return 0;
  653. case S_VALUE:
  654. if(! store_to_database(db)){
  655. return 0;
  656. }
  657. /* fall into next case */
  658. case S_CATEGORY:
  659. if(parse_info.name[parse_info.nest_depth] != NULL){
  660. Xfree(parse_info.name[parse_info.nest_depth]);
  661. parse_info.name[parse_info.nest_depth] = NULL;
  662. }
  663. --parse_info.nest_depth;
  664. parse_info.pre_state = S_CATEGORY;
  665. break;
  666. default:
  667. return 0;
  668. }
  669. return token_tbl[token].len;
  670. }
  671. static int
  672. f_double_quote(char *str, Token token, Database *db)
  673. {
  674. char word[BUFSIZE];
  675. int len = 0;
  676. switch(parse_info.pre_state){
  677. case S_NULL:
  678. case S_CATEGORY:
  679. return 0;
  680. case S_NAME:
  681. case S_VALUE:
  682. len = get_quoted_word(str, word);
  683. if(len < 1){
  684. return 0;
  685. }
  686. if( (parse_info.bufsize + (int)strlen(word) +1)
  687. >= parse_info.bufMaxSize){
  688. if(realloc_parse_info(strlen(word) +1) == False){
  689. return 0;
  690. }
  691. }
  692. strcpy(&parse_info.buf[parse_info.bufsize], word);
  693. parse_info.bufsize += strlen(word);
  694. parse_info.pre_state = S_VALUE;
  695. break;
  696. default:
  697. return 0;
  698. }
  699. return len; /* including length of token */
  700. }
  701. static int
  702. f_backslash(char *str, Token token, Database *db)
  703. {
  704. return f_default(str, token, db);
  705. }
  706. static int
  707. f_numeric(char *str, Token token, Database *db)
  708. {
  709. char word[BUFSIZE], *p;
  710. int len;
  711. int token_len;
  712. switch(parse_info.pre_state){
  713. case S_NULL:
  714. case S_CATEGORY:
  715. return 0;
  716. case S_NAME:
  717. case S_VALUE:
  718. token_len = token_tbl[token].len;
  719. p = str + token_len;
  720. len = get_word(p, word);
  721. if(len < 1){
  722. return 0;
  723. }
  724. if( (parse_info.bufsize + token_len + (int)strlen(word) +1)
  725. >= parse_info.bufMaxSize){
  726. if(realloc_parse_info(token_len + strlen(word) +1) == False){
  727. return 0;
  728. }
  729. }
  730. strncpy(&parse_info.buf[parse_info.bufsize], str, token_len);
  731. strcpy(&parse_info.buf[parse_info.bufsize + token_len], word);
  732. parse_info.bufsize += token_len + strlen(word);
  733. parse_info.pre_state = S_VALUE;
  734. break;
  735. default:
  736. return 0;
  737. }
  738. return len + token_len;
  739. }
  740. static int
  741. f_default(char *str, Token token, Database *db)
  742. {
  743. char word[BUFSIZE], *p;
  744. int len;
  745. len = get_word(str, word);
  746. if(len < 1){
  747. return 0;
  748. }
  749. switch(parse_info.pre_state){
  750. case S_NULL:
  751. if(parse_info.category != NULL){
  752. return 0;
  753. }
  754. p = (char *)Xmalloc(strlen(word) + 1);
  755. if(p == NULL){
  756. return 0;
  757. }
  758. strcpy(p, word);
  759. parse_info.category = p;
  760. parse_info.pre_state = S_CATEGORY;
  761. break;
  762. case S_CATEGORY:
  763. if(parse_info.nest_depth == 0){
  764. if(check_category_end(str)){
  765. /* end of category is detected.
  766. clear context and zap to end of this line */
  767. clear_parse_info();
  768. len = strlen(str);
  769. break;
  770. }
  771. }
  772. p = (char *)Xmalloc(strlen(word) + 1);
  773. if(p == NULL){
  774. return 0;
  775. }
  776. strcpy(p, word);
  777. if(parse_info.name[parse_info.nest_depth] != NULL){
  778. Xfree(parse_info.name[parse_info.nest_depth]);
  779. }
  780. parse_info.name[parse_info.nest_depth] = p;
  781. parse_info.pre_state = S_NAME;
  782. break;
  783. case S_NAME:
  784. case S_VALUE:
  785. if( (parse_info.bufsize + (int)strlen(word) +1 )
  786. >= parse_info.bufMaxSize){
  787. if(realloc_parse_info(strlen(word) +1) == False){
  788. return 0;
  789. }
  790. }
  791. strcpy(&parse_info.buf[parse_info.bufsize], word);
  792. parse_info.bufsize += strlen(word);
  793. parse_info.pre_state = S_VALUE;
  794. break;
  795. default:
  796. return 0;
  797. }
  798. return len;
  799. }
  800. /************************************************************************/
  801. #ifdef DEBUG
  802. static void
  803. PrintDatabase(Database db)
  804. {
  805. Database p = db;
  806. int i = 0, j;
  807. printf("***\n*** BEGIN Database\n***\n");
  808. while(p){
  809. printf("%3d: ", i++);
  810. printf("%s, %s, ", p->category, p->name);
  811. printf("\t[%d: ", p->value_num);
  812. for(j = 0; j < p->value_num; ++j){
  813. printf("%s, ", p->value[j]);
  814. }
  815. printf("]\n");
  816. p = p->next;
  817. }
  818. printf("***\n*** END Database\n***\n");
  819. }
  820. #endif
  821. static void
  822. DestroyDatabase(Database db)
  823. {
  824. Database p = db;
  825. while(p){
  826. if(p->category != NULL){
  827. Xfree(p->category);
  828. }
  829. if(p->name != NULL){
  830. Xfree(p->name);
  831. }
  832. if(p->value != (char **)NULL){
  833. if(*p->value != NULL){
  834. Xfree(*p->value);
  835. }
  836. Xfree((char *)p->value);
  837. }
  838. db = p->next;
  839. Xfree((char *)p);
  840. p = db;
  841. }
  842. }
  843. static int
  844. CountDatabase(Database db)
  845. {
  846. Database p = db;
  847. int cnt = 0;
  848. while(p){
  849. ++cnt;
  850. p = p->next;
  851. }
  852. return cnt;
  853. }
  854. static Database
  855. CreateDatabase(char *dbfile)
  856. {
  857. Database db = (Database)NULL;
  858. FILE *fd;
  859. Line line;
  860. char *p;
  861. Token token;
  862. int token_len;
  863. int len;
  864. int error = 0;
  865. fd = fopen(dbfile, "r");
  866. if(fd == (FILE *)NULL){
  867. return NULL;
  868. }
  869. bzero(&line, sizeof(Line));
  870. init_parse_info();
  871. do {
  872. int rc = read_line(fd, &line);
  873. if(rc < 0){
  874. error = 1;
  875. break;
  876. }else if(rc == 0){
  877. break;
  878. }
  879. p = line.str;
  880. while(*p){
  881. token = get_token(p);
  882. len = (*token_tbl[token].parse_proc)(p, token, &db);
  883. if(len < 1){
  884. error = 1;
  885. break;
  886. }
  887. p += len;
  888. }
  889. } while (!error);
  890. if(parse_info.pre_state != S_NULL){
  891. clear_parse_info();
  892. error = 1;
  893. }
  894. if(error){
  895. #ifdef DEBUG
  896. fprintf(stderr, "database format error at line %d.\n", line.seq);
  897. #endif
  898. DestroyDatabase(db);
  899. db = (Database)NULL;
  900. }
  901. fclose(fd);
  902. free_line(&line);
  903. #ifdef DEBUG
  904. PrintDatabase(db);
  905. #endif
  906. return db;
  907. }
  908. /************************************************************************/
  909. /* locale framework functions */
  910. typedef struct _XlcDatabaseRec {
  911. XrmQuark category_q;
  912. XrmQuark name_q;
  913. Database db;
  914. struct _XlcDatabaseRec *next;
  915. } XlcDatabaseRec, *XlcDatabase;
  916. typedef struct _XlcDatabaseListRec {
  917. XrmQuark name_q;
  918. XlcDatabase lc_db;
  919. Database database;
  920. int ref_count;
  921. struct _XlcDatabaseListRec *next;
  922. } XlcDatabaseListRec, *XlcDatabaseList;
  923. /* database cache list (per file) */
  924. static XlcDatabaseList _db_list = (XlcDatabaseList)NULL;
  925. /************************************************************************/
  926. /* _fallcGetResource(lcd, category, class, value, count) */
  927. /*----------------------------------------------------------------------*/
  928. /* This function retrieves XLocale database information. */
  929. /************************************************************************/
  930. void
  931. _fallcGetResource(
  932. XLCd lcd,
  933. char *category,
  934. char *class,
  935. char ***value,
  936. int *count)
  937. {
  938. XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd);
  939. (*methods->get_resource)(lcd, category, class, value, count);
  940. return;
  941. }
  942. /************************************************************************/
  943. /* _fallcGetLocaleDataBase(lcd, category, class, value, count) */
  944. /*----------------------------------------------------------------------*/
  945. /* This function retrieves XLocale database information. */
  946. /************************************************************************/
  947. void
  948. _fallcGetLocaleDataBase(
  949. XLCd lcd,
  950. char *category,
  951. char *name,
  952. char ***value,
  953. int *count)
  954. {
  955. XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
  956. XrmQuark category_q, name_q;
  957. category_q = falrmStringToQuark(category);
  958. name_q = falrmStringToQuark(name);
  959. for(; lc_db->db; ++lc_db){
  960. if(category_q == lc_db->category_q && name_q == lc_db->name_q){
  961. *value = lc_db->db->value;
  962. *count = lc_db->db->value_num;
  963. return;
  964. }
  965. }
  966. *value = (char **)NULL;
  967. *count = 0;
  968. }
  969. /************************************************************************/
  970. /* _fallcDestroyLocaleDataBase(lcd) */
  971. /*----------------------------------------------------------------------*/
  972. /* This function destroy the XLocale Database that bound to the */
  973. /* specified lcd. If the XLocale Database is referred from some */
  974. /* other lcd, this function just decreases reference count of */
  975. /* the database. If no locale refers the database, this function */
  976. /* remove it from the cache list and free work area. */
  977. /************************************************************************/
  978. void
  979. _fallcDestroyLocaleDataBase(XLCd lcd)
  980. {
  981. XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db);
  982. XlcDatabaseList p, prev;
  983. for(p = _db_list, prev = (XlcDatabaseList)NULL; p;
  984. prev = p, p = p->next){
  985. if(p->lc_db == lc_db){
  986. if((-- p->ref_count) < 1){
  987. if(p->lc_db != (XlcDatabase)NULL){
  988. Xfree((char *)p->lc_db);
  989. }
  990. DestroyDatabase(p->database);
  991. if(prev == (XlcDatabaseList)NULL){
  992. _db_list = p->next;
  993. }else{
  994. prev->next = p->next;
  995. }
  996. Xfree((char*)p);
  997. }
  998. break;
  999. }
  1000. }
  1001. XLC_PUBLIC(lcd, xlocale_db) = (XPointer)NULL;
  1002. }
  1003. /************************************************************************/
  1004. /* _fallcCreateLocaleDataBase(lcd) */
  1005. /*----------------------------------------------------------------------*/
  1006. /* This function create an XLocale database which correspond to */
  1007. /* the specified XLCd. */
  1008. /************************************************************************/
  1009. XPointer
  1010. _fallcCreateLocaleDataBase(XLCd lcd)
  1011. {
  1012. XlcDatabaseList list, new;
  1013. Database p, database = (Database)NULL;
  1014. XlcDatabase lc_db = (XlcDatabase)NULL;
  1015. XrmQuark name_q;
  1016. char pathname[256], *name;
  1017. int i, n;
  1018. name = _fallcFileName(lcd, "locale");
  1019. if(name == NULL){
  1020. return (XPointer)NULL;
  1021. }
  1022. strcpy(pathname, name);
  1023. Xfree(name);
  1024. name_q = falrmStringToQuark(pathname);
  1025. for(list = _db_list; list; list = list->next){
  1026. if(name_q == list->name_q){
  1027. list->ref_count++;
  1028. return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)list->lc_db;
  1029. }
  1030. }
  1031. database = CreateDatabase(pathname);
  1032. if(database == (Database)NULL){
  1033. return (XPointer)NULL;
  1034. }
  1035. n = CountDatabase(database);
  1036. lc_db = (XlcDatabase)Xmalloc(sizeof(XlcDatabaseRec) * (n + 1));
  1037. if(lc_db == (XlcDatabase)NULL){
  1038. DestroyDatabase(database);
  1039. if(lc_db != (XlcDatabase)NULL){
  1040. Xfree((char *)lc_db);
  1041. }
  1042. return (XPointer)NULL;
  1043. }
  1044. bzero(lc_db, sizeof(XlcDatabaseRec) * (n + 1));
  1045. for(p = database, i = 0; p && i < n; p = p->next, ++i){
  1046. lc_db[i].category_q = falrmStringToQuark(p->category);
  1047. lc_db[i].name_q = falrmStringToQuark(p->name);
  1048. lc_db[i].db = p;
  1049. }
  1050. new = (XlcDatabaseList)Xmalloc(sizeof(XlcDatabaseListRec));
  1051. if(new == (XlcDatabaseList)NULL){
  1052. DestroyDatabase(database);
  1053. if(lc_db != (XlcDatabase)NULL){
  1054. Xfree((char *)lc_db);
  1055. }
  1056. return (XPointer)NULL;
  1057. }
  1058. new->name_q = name_q;
  1059. new->lc_db = lc_db;
  1060. new->database = database;
  1061. new->ref_count = 1;
  1062. new->next = _db_list;
  1063. _db_list = new;
  1064. return XLC_PUBLIC(lcd, xlocale_db) = (XPointer)lc_db;
  1065. }