Bug Summary

File:src/xlibi18n/lcDB.c
Location:line 824, column 5
Description:Value stored to 'len' is never read

Annotated Source Code

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