Bug Summary

File:src/xlibi18n/lcDB.c
Location:line 825, 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))__builtin___memset_chk (&parse_info, 0, sizeof(DBParseInfo
), __builtin_object_size (&parse_info, 0))
;
168 parse_info.buf = 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))__builtin___memset_chk (&parse_info, 0, sizeof(DBParseInfo
), __builtin_object_size (&parse_info, 0))
;
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(parse_info.value)free((parse_info.value));
200 }
201 ptr = parse_info.buf;
202 size = parse_info.bufMaxSize;
203 bzero(&parse_info, sizeof(DBParseInfo))__builtin___memset_chk (&parse_info, 0, sizeof(DBParseInfo
), __builtin_object_size (&parse_info, 0))
;
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 int newsize = BUFSIZE2048 * ((parse_info.bufsize + len)/BUFSIZE2048 + 1);
214
215 p = Xrealloc(parse_info.buf, newsize)realloc((parse_info.buf), ((newsize) == 0 ? 1 : (newsize)));
216 if (p == NULL((void*)0))
217 return False0;
218 parse_info.bufMaxSize = newsize;
219 parse_info.buf = p;
220
221 return True1;
222}
223
224/************************************************************************/
225
226typedef struct _Line {
227 char *str;
228 int cursize;
229 int maxsize;
230 int seq;
231} Line;
232
233static void
234free_line(
235 Line *line)
236{
237 if (line->str != NULL((void*)0)) {
238 Xfree(line->str)free((line->str));
239 }
240 bzero(line, sizeof(Line))__builtin___memset_chk (line, 0, sizeof(Line), __builtin_object_size
(line, 0))
;
241}
242
243static int
244realloc_line(
245 Line *line,
246 int size)
247{
248 char *str = line->str;
249
250 if (str != NULL((void*)0)) {
251 str = Xrealloc(str, size)realloc((str), ((size) == 0 ? 1 : (size)));
252 } else {
253 str = Xmalloc(size)malloc(((size) == 0 ? 1 : (size)));
254 }
255 if (str == NULL((void*)0)) {
256 /* malloc error */
257 if (line->str != NULL((void*)0)) {
258 Xfree(line->str)free((line->str));
259 }
260 bzero(line, sizeof(Line))__builtin___memset_chk (line, 0, sizeof(Line), __builtin_object_size
(line, 0))
;
261 return 0;
262 }
263 line->str = str;
264 line->maxsize = size;
265 return 1;
266}
267
268#define iswhite(ch)((ch) == ' ' || (ch) == '\t') ((ch) == SYM_SPACE' ' || (ch) == SYM_TAB'\t')
269
270static void
271zap_comment(
272 char *str,
273 int *quoted)
274{
275 char *p = str;
276#ifdef never
277 *quoted = 0;
278 if (*p == SYM_COMMENT'#') {
279 int len = strlen(str);
280 if (p[len - 1] == SYM_NEWLINE'\n' || p[len - 1] == SYM_CR'\r') {
281 *p++ = SYM_NEWLINE'\n';
282 }
283 *p = '\0';
284 }
285#else
286 while (*p) {
287 if (*p == SYM_DOUBLE_QUOTE'"') {
288 if (p == str || p[-1] != SYM_BACKSLASH'\\') {
289 /* unescaped double quote changes quoted state. */
290 *quoted = *quoted ? 0 : 1;
291 }
292 }
293 if (*p == SYM_COMMENT'#' && !*quoted) {
294 int pos = p - str;
295 if (pos == 0 ||
296 (iswhite(p[-1])((p[-1]) == ' ' || (p[-1]) == '\t') && (pos == 1 || p[-2] != SYM_BACKSLASH'\\'))) {
297 int len = strlen(p);
298 if (len > 0 && (p[len - 1] == SYM_NEWLINE'\n' || p[len-1] == SYM_CR'\r')) {
299 /* newline is the identifier for finding end of value.
300 therefore, it should not be removed. */
301 *p++ = SYM_NEWLINE'\n';
302 }
303 *p = '\0';
304 break;
305 }
306 }
307 ++p;
308 }
309#endif
310}
311
312static int
313read_line(
314 FILE *fd,
315 Line *line)
316{
317 char buf[BUFSIZE2048], *p;
318 int len;
319 int quoted = 0; /* quoted by double quote? */
320 char *str;
321 int cur;
322
323 str = line->str;
324 cur = line->cursize = 0;
325
326 while ((p = fgets(buf, BUFSIZE2048, fd)) != NULL((void*)0)) {
327 ++line->seq;
328 zap_comment(p, &quoted); /* remove comment line */
329 len = strlen(p);
330 if (len == 0) {
331 if (cur > 0) {
332 break;
333 }
334 continue;
335 }
336 if (cur + len + 1 > line->maxsize) {
337 /* need to reallocate buffer. */
338 if (! realloc_line(line, line->maxsize + BUFSIZE2048)) {
339 return -1; /* realloc error. */
340 }
341 str = line->str;
342 }
343 strncpy(str + cur, p, len)__builtin___strncpy_chk (str + cur, p, len, __builtin_object_size
(str + cur, 2 > 1 ? 1 : 0))
;
344
345 cur += len;
346 str[cur] = '\0';
347#ifdef __UNIXOS2__ /* Take out carriage returns under OS/2 */
348 if (cur>1) {
349 if (str[cur-2] == '\r' && str[cur-1] == '\n') {
350 str[cur-2] = '\n';
351 str[cur-1] = '\0';
352 cur--;
353 }
354 }
355#endif
356 if (!quoted && cur > 1 && str[cur - 2] == SYM_BACKSLASH'\\' &&
357 (str[cur - 1] == SYM_NEWLINE'\n' || str[cur-1] == SYM_CR'\r')) {
358 /* the line is ended backslash followed by newline.
359 need to concatinate the next line. */
360 cur -= 2;
361 str[cur] = '\0';
362 } else if (len < BUFSIZE2048 - 1 || buf[len - 1] == SYM_NEWLINE'\n' ||
363 buf[len - 1] == SYM_CR'\r') {
364 /* the line is shorter than BUFSIZE. */
365 break;
366 }
367 }
368 if (quoted) {
369 /* error. still in quoted state. */
370 return -1;
371 }
372 return line->cursize = cur;
373}
374
375/************************************************************************/
376
377static Token
378get_token(
379 const char *str)
380{
381 switch (*str) {
382 case SYM_NEWLINE'\n':
383 case SYM_CR'\r': return T_NEWLINE;
384 case SYM_COMMENT'#': return T_COMMENT;
385 case SYM_SEMICOLON';': return T_SEMICOLON;
386 case SYM_DOUBLE_QUOTE'"': return T_DOUBLE_QUOTE;
387 case SYM_LEFT_BRACE'{': return T_LEFT_BRACE;
388 case SYM_RIGHT_BRACE'}': return T_RIGHT_BRACE;
389 case SYM_SPACE' ': return T_SPACE;
390 case SYM_TAB'\t': return T_TAB;
391 case SYM_BACKSLASH'\\':
392 switch (str[1]) {
393 case 'x': return T_NUMERIC_HEX;
394 case 'd': return T_NUMERIC_DEC;
395 case 'o': return T_NUMERIC_OCT;
396 }
397 return T_BACKSLASH;
398 default:
399 return T_DEFAULT;
400 }
401}
402
403static int
404get_word(
405 const char *str,
406 char *word)
407{
408 const char *p = str;
409 char *w = word;
410 Token token;
411 int token_len;
412
413 while (*p != '\0') {
414 token = get_token(p);
415 token_len = token_tbl[token].len;
416 if (token == T_BACKSLASH) {
417 p += token_len;
418 if (*p == '\0')
419 break;
420 token = get_token(p);
421 token_len = token_tbl[token].len;
422 } else if (token != T_COMMENT && token != T_DEFAULT) {
423 break;
424 }
425 strncpy(w, p, token_len)__builtin___strncpy_chk (w, p, token_len, __builtin_object_size
(w, 2 > 1 ? 1 : 0))
;
426 p += token_len; w += token_len;
427 }
428 *w = '\0';
429 return p - str; /* return number of scanned chars */
430}
431
432static int
433get_quoted_word(
434 const char *str,
435 char *word)
436{
437 const char *p = str;
438 char *w = word;
439 Token token;
440 int token_len;
441
442 if (*p == SYM_DOUBLE_QUOTE'"') {
443 ++p;
444 }
445 while (*p != '\0') {
446 token = get_token(p);
447 token_len = token_tbl[token].len;
448 if (token == T_DOUBLE_QUOTE) {
449 p += token_len;
450 goto found;
451 }
452 if (token == T_BACKSLASH) {
453 p += token_len;
454 if (*p == '\0') {
455 break;
456 }
457 token = get_token(p);
458 token_len = token_tbl[token].len;
459 }
460 strncpy(w, p, token_len)__builtin___strncpy_chk (w, p, token_len, __builtin_object_size
(w, 2 > 1 ? 1 : 0))
;
461 p += token_len; w += token_len;
462 }
463 /* error. cannot detect next double quote */
464 return 0;
465
466 found:;
467 *w = '\0';
468 return p - str;
469}
470
471/************************************************************************/
472
473static int
474append_value_list (void)
475{
476 char **value_list = parse_info.value;
477 char *value;
478 int value_num = parse_info.value_num;
479 int value_len = parse_info.value_len;
480 char *str = parse_info.buf;
481 int len = parse_info.bufsize;
482 char *p;
483
484 if (len < 1) {
485 return 1; /* return with no error */
486 }
487
488 if (value_list == (char **)NULL((void*)0)) {
489 value_list = Xmalloc(sizeof(char *) * 2)malloc(((sizeof(char *) * 2) == 0 ? 1 : (sizeof(char *) * 2))
)
;
490 *value_list = NULL((void*)0);
491 } else {
492 char **prev_list = value_list;
493
494 value_list = (char **)
495 Xrealloc(value_list, sizeof(char *) * (value_num + 2))realloc((value_list), ((sizeof(char *) * (value_num + 2)) == 0
? 1 : (sizeof(char *) * (value_num + 2))))
;
496 if (value_list == NULL((void*)0)) {
497 Xfree(prev_list)free((prev_list));
498 }
499 }
500 if (value_list == (char **)NULL((void*)0))
501 goto err2;
502
503 value = *value_list;
504 if (value == NULL((void*)0)) {
505 value = Xmalloc(value_len + len + 1)malloc(((value_len + len + 1) == 0 ? 1 : (value_len + len + 1
)))
;
506 } else {
507 char *prev_value = value;
508
509 value = Xrealloc(value, value_len + len + 1)realloc((value), ((value_len + len + 1) == 0 ? 1 : (value_len
+ len + 1)))
;
510 if (value == NULL((void*)0)) {
511 Xfree(prev_value)free((prev_value));
512 }
513 }
514 if (value == NULL((void*)0)) {
515 goto err1;
516 }
517 if (value != *value_list) {
518 int i;
519 ssize_t delta;
520 delta = value - *value_list;
521 *value_list = value;
522 for (i = 1; i < value_num; ++i) {
523 value_list[i] += delta;
524 }
525 }
526
527 value_list[value_num] = p = &value[value_len];
528 value_list[value_num + 1] = NULL((void*)0);
529 strncpy(p, str, len)__builtin___strncpy_chk (p, str, len, __builtin_object_size (
p, 2 > 1 ? 1 : 0))
;
530 p[len] = 0;
531
532 parse_info.value = value_list;
533 parse_info.value_num = value_num + 1;
534 parse_info.value_len = value_len + len + 1;
535 parse_info.bufsize = 0;
536 return 1;
537
538 err1:
539 if (value_list) {
540 Xfree((char **)value_list)free(((char **)value_list));
541 }
542 if (value) {
543 Xfree(value)free((value));
544 }
545 err2:
546 parse_info.value = (char **)NULL((void*)0);
547 parse_info.value_num = 0;
548 parse_info.value_len = 0;
549 parse_info.bufsize = 0;
550 return 0;
551}
552
553static int
554construct_name(
555 char *name,
556 int size)
557{
558 int i;
559 int len = 0;
560 char *p = name;
561
562 for (i = 0; i <= parse_info.nest_depth; ++i) {
563 len += strlen(parse_info.name[i]) + 1;
564 }
565 if (len >= size)
566 return 0;
567
568 strcpy(p, parse_info.name[0])__builtin___strcpy_chk (p, parse_info.name[0], __builtin_object_size
(p, 2 > 1 ? 1 : 0))
;
569 p += strlen(parse_info.name[0]);
570 for (i = 1; i <= parse_info.nest_depth; ++i) {
571 *p++ = '.';
572 strcpy(p, parse_info.name[i])__builtin___strcpy_chk (p, parse_info.name[i], __builtin_object_size
(p, 2 > 1 ? 1 : 0))
;
573 p += strlen(parse_info.name[i]);
574 }
575 return *name != '\0';
576}
577
578static int
579store_to_database(
580 Database *db)
581{
582 Database new = (Database)NULL((void*)0);
583 char name[BUFSIZE2048];
584
585 if (parse_info.pre_state == S_VALUE) {
586 if (! append_value_list()) {
587 goto err;
588 }
589 }
590
591 if (parse_info.name[parse_info.nest_depth] == NULL((void*)0)) {
592 goto err;
593 }
594
595 new = Xcalloc(1, sizeof(DatabaseRec))calloc(((1) == 0 ? 1 : (1)), (sizeof(DatabaseRec)));
596 if (new == (Database)NULL((void*)0)) {
597 goto err;
598 }
599
600 new->category = strdup(parse_info.category);
601 if (new->category == NULL((void*)0)) {
602 goto err;
603 }
604
605 if (! construct_name(name, sizeof(name))) {
606 goto err;
607 }
608 new->name = strdup(name);
609 if (new->name == NULL((void*)0)) {
610 goto err;
611 }
612 new->next = *db;
613 new->value = parse_info.value;
614 new->value_num = parse_info.value_num;
615 *db = new;
616
617 Xfree(parse_info.name[parse_info.nest_depth])free((parse_info.name[parse_info.nest_depth]));
618 parse_info.name[parse_info.nest_depth] = NULL((void*)0);
619
620 parse_info.value = (char **)NULL((void*)0);
621 parse_info.value_num = 0;
622 parse_info.value_len = 0;
623
624 return 1;
625
626 err:
627 if (new) {
628 if (new->category) {
629 Xfree(new->category)free((new->category));
630 }
631 if (new->name) {
632 Xfree(new->name)free((new->name));
633 }
634 Xfree(new)free((new));
635 }
636 if (parse_info.value) {
637 if (*parse_info.value) {
638 Xfree(*parse_info.value)free((*parse_info.value));
639 }
640 Xfree((char **)parse_info.value)free(((char **)parse_info.value));
641 parse_info.value = (char **)NULL((void*)0);
642 parse_info.value_num = 0;
643 parse_info.value_len = 0;
644 }
645 return 0;
646}
647
648#define END_MARK"END" "END"
649#define END_MARK_LEN3 3 /*strlen(END_MARK)*/
650
651static int
652check_category_end(
653 const char *str)
654{
655 const char *p;
656 int len;
657
658 p = str;
659 if (strncmp(p, END_MARK"END", END_MARK_LEN3)) {
660 return 0;
661 }
662 p += END_MARK_LEN3;
663
664 while (iswhite(*p)((*p) == ' ' || (*p) == '\t')) {
665 ++p;
666 }
667 len = strlen(parse_info.category);
668 if (strncmp(p, parse_info.category, len)) {
669 return 0;
670 }
671 p += len;
672 return p - str;
673}
674
675/************************************************************************/
676
677static int
678f_newline(
679 const char *str,
680 Token token,
681 Database *db)
682{
683 switch (parse_info.pre_state) {
684 case S_NULL:
685 case S_CATEGORY:
686 break;
687 case S_NAME:
688 return 0; /* no value */
689 case S_VALUE:
690 if (!store_to_database(db))
691 return 0;
692 parse_info.pre_state = S_CATEGORY;
693 break;
694 default:
695 return 0;
696 }
697 return token_tbl[token].len;
698}
699
700static int
701f_comment(
702 const char *str,
703 Token token,
704 Database *db)
705{
706 /* NOTE: comment is already handled in read_line(),
707 so this function is not necessary. */
708
709 const char *p = str;
710
711 while (*p != SYM_NEWLINE'\n' && *p != SYM_CR'\r' && *p != '\0') {
712 ++p; /* zap to the end of line */
713 }
714 return p - str;
715}
716
717static int
718f_white(
719 const char *str,
720 Token token,
721 Database *db)
722{
723 const char *p = str;
724
725 while (iswhite(*p)((*p) == ' ' || (*p) == '\t')) {
726 ++p;
727 }
728 return p - str;
729}
730
731static int
732f_semicolon(
733 const char *str,
734 Token token,
735 Database *db)
736{
737 switch (parse_info.pre_state) {
738 case S_NULL:
739 case S_CATEGORY:
740 case S_NAME:
741 return 0;
742 case S_VALUE:
743 if (! append_value_list())
744 return 0;
745 parse_info.pre_state = S_VALUE;
746 break;
747 default:
748 return 0;
749 }
750 return token_tbl[token].len;
751}
752
753static int
754f_left_brace(
755 const char *str,
756 Token token,
757 Database *db)
758{
759 switch (parse_info.pre_state) {
760 case S_NULL:
761 case S_CATEGORY:
762 case S_VALUE:
763 return 0;
764 case S_NAME:
765 if (parse_info.name[parse_info.nest_depth] == NULL((void*)0)
766 || parse_info.nest_depth + 1 > MAX_NAME_NEST64)
767 return 0;
768 ++parse_info.nest_depth;
769 parse_info.pre_state = S_CATEGORY;
770 break;
771 default:
772 return 0;
773 }
774 return token_tbl[token].len;
775}
776
777static int
778f_right_brace(
779 const char *str,
780 Token token,
781 Database *db)
782{
783 if (parse_info.nest_depth < 1)
784 return 0;
785
786 switch (parse_info.pre_state) {
787 case S_NULL:
788 case S_NAME:
789 return 0;
790 case S_VALUE:
791 if (! store_to_database(db))
792 return 0;
793 /* fall into next case */
794 case S_CATEGORY:
795 if (parse_info.name[parse_info.nest_depth] != NULL((void*)0)) {
796 Xfree(parse_info.name[parse_info.nest_depth])free((parse_info.name[parse_info.nest_depth]));
797 parse_info.name[parse_info.nest_depth] = NULL((void*)0);
798 }
799 --parse_info.nest_depth;
800 parse_info.pre_state = S_CATEGORY;
801 break;
802 default:
803 return 0;
804 }
805 return token_tbl[token].len;
806}
807
808static int
809f_double_quote(
810 const char *str,
811 Token token,
812 Database *db)
813{
814 char word[BUFSIZE2048];
815 char* wordp;
816 int len;
817
818 if ((len = strlen (str)) < sizeof word)
819 wordp = word;
820 else
821 wordp = Xmalloc (len + 1)malloc(((len + 1) == 0 ? 1 : (len + 1)));
822 if (wordp == NULL((void*)0))
823 return 0;
824
825 len = 0;
Value stored to 'len' is never read
826 switch (parse_info.pre_state) {
827 case S_NULL:
828 case S_CATEGORY:
829 goto err;
830 case S_NAME:
831 case S_VALUE:
832 len = get_quoted_word(str, wordp);
833 if (len < 1)
834 goto err;
835 if ((parse_info.bufsize + (int)strlen(wordp) + 1)
836 >= parse_info.bufMaxSize) {
837 if (realloc_parse_info(strlen(wordp)+1) == False0) {
838 goto err;
839 }
840 }
841 strcpy(&parse_info.buf[parse_info.bufsize], wordp)__builtin___strcpy_chk (&parse_info.buf[parse_info.bufsize
], wordp, __builtin_object_size (&parse_info.buf[parse_info
.bufsize], 2 > 1 ? 1 : 0))
;
842 parse_info.bufsize += strlen(wordp);
843 parse_info.pre_state = S_VALUE;
844 break;
845 default:
846 goto err;
847 }
848 if (wordp != word)
849 Xfree (wordp)free((wordp));
850 return len; /* including length of token */
851
852err:
853 if (wordp != word)
854 Xfree (wordp)free((wordp));
855 return 0;
856}
857
858static int
859f_backslash(
860 const char *str,
861 Token token,
862 Database *db)
863{
864 return f_default(str, token, db);
865}
866
867static int
868f_numeric(
869 const char *str,
870 Token token,
871 Database *db)
872{
873 char word[BUFSIZE2048];
874 const char *p;
875 char* wordp;
876 int len;
877 int token_len;
878
879 if ((len = strlen (str)) < sizeof word)
880 wordp = word;
881 else
882 wordp = Xmalloc (len + 1)malloc(((len + 1) == 0 ? 1 : (len + 1)));
883 if (wordp == NULL((void*)0))
884 return 0;
885
886 switch (parse_info.pre_state) {
887 case S_NULL:
888 case S_CATEGORY:
889 goto err;
890 case S_NAME:
891 case S_VALUE:
892 token_len = token_tbl[token].len;
893 p = str + token_len;
894 len = get_word(p, wordp);
895 if (len < 1)
896 goto err;
897 if ((parse_info.bufsize + token_len + (int)strlen(wordp) + 1)
898 >= parse_info.bufMaxSize) {
899 if (realloc_parse_info(token_len + strlen(wordp) + 1) == False0)
900 goto err;
901 }
902 strncpy(&parse_info.buf[parse_info.bufsize], str, token_len)__builtin___strncpy_chk (&parse_info.buf[parse_info.bufsize
], str, token_len, __builtin_object_size (&parse_info.buf
[parse_info.bufsize], 2 > 1 ? 1 : 0))
;
903 strcpy(&parse_info.buf[parse_info.bufsize + token_len], wordp)__builtin___strcpy_chk (&parse_info.buf[parse_info.bufsize
+ token_len], wordp, __builtin_object_size (&parse_info.
buf[parse_info.bufsize + token_len], 2 > 1 ? 1 : 0))
;
904 parse_info.bufsize += token_len + strlen(wordp);
905 parse_info.pre_state = S_VALUE;
906 break;
907 default:
908 goto err;
909 }
910 if (wordp != word)
911 Xfree (wordp)free((wordp));
912 return len + token_len;
913
914err:
915 if (wordp != word)
916 Xfree (wordp)free((wordp));
917 return 0;
918}
919
920static int
921f_default(
922 const char *str,
923 Token token,
924 Database *db)
925{
926 char word[BUFSIZE2048], *p;
927 char* wordp;
928 int len;
929
930 if ((len = strlen (str)) < sizeof word)
931 wordp = word;
932 else
933 wordp = Xmalloc (len + 1)malloc(((len + 1) == 0 ? 1 : (len + 1)));
934 if (wordp == NULL((void*)0))
935 return 0;
936
937 len = get_word(str, wordp);
938 if (len < 1)
939 goto err;
940
941 switch (parse_info.pre_state) {
942 case S_NULL:
943 if (parse_info.category != NULL((void*)0))
944 goto err;
945 p = strdup(wordp);
946 if (p == NULL((void*)0))
947 goto err;
948 parse_info.category = p;
949 parse_info.pre_state = S_CATEGORY;
950 break;
951 case S_CATEGORY:
952 if (parse_info.nest_depth == 0) {
953 if (check_category_end(str)) {
954 /* end of category is detected.
955 clear context and zap to end of this line */
956 clear_parse_info();
957 len = strlen(str);
958 break;
959 }
960 }
961 p = strdup(wordp);
962 if (p == NULL((void*)0))
963 goto err;
964 if (parse_info.name[parse_info.nest_depth] != NULL((void*)0)) {
965 Xfree(parse_info.name[parse_info.nest_depth])free((parse_info.name[parse_info.nest_depth]));
966 }
967 parse_info.name[parse_info.nest_depth] = p;
968 parse_info.pre_state = S_NAME;
969 break;
970 case S_NAME:
971 case S_VALUE:
972 if ((parse_info.bufsize + (int)strlen(wordp) + 1)
973 >= parse_info.bufMaxSize) {
974 if (realloc_parse_info(strlen(wordp) + 1) == False0)
975 goto err;
976 }
977 strcpy(&parse_info.buf[parse_info.bufsize], wordp)__builtin___strcpy_chk (&parse_info.buf[parse_info.bufsize
], wordp, __builtin_object_size (&parse_info.buf[parse_info
.bufsize], 2 > 1 ? 1 : 0))
;
978 parse_info.bufsize += strlen(wordp);
979 parse_info.pre_state = S_VALUE;
980 break;
981 default:
982 goto err;
983 }
984 if (wordp != word)
985 Xfree (wordp)free((wordp));
986 return len;
987
988err:
989 if (wordp != word)
990 Xfree (wordp)free((wordp));
991 return 0;
992}
993
994/************************************************************************/
995
996#ifdef DEBUG
997static void
998PrintDatabase(
999 Database db)
1000{
1001 Database p = db;
1002 int i = 0, j;
1003
1004 printf("***\n*** BEGIN Database\n***\n");
1005 while (p) {
1006 printf("%3d: ", i++);
1007 printf("%s, %s, ", p->category, p->name);
1008 printf("\t[%d: ", p->value_num);
1009 for (j = 0; j < p->value_num; ++j) {
1010 printf("%s, ", p->value[j]);
1011 }
1012 printf("]\n");
1013 p = p->next;
1014 }
1015 printf("***\n*** END Database\n***\n");
1016}
1017#endif
1018
1019static void
1020DestroyDatabase(
1021 Database db)
1022{
1023 Database p = db;
1024
1025 while (p) {
1026 if (p->category != NULL((void*)0)) {
1027 Xfree(p->category)free((p->category));
1028 }
1029 if (p->name != NULL((void*)0)) {
1030 Xfree(p->name)free((p->name));
1031 }
1032 if (p->value != (char **)NULL((void*)0)) {
1033 if (*p->value != NULL((void*)0)) {
1034 Xfree(*p->value)free((*p->value));
1035 }
1036 Xfree(p->value)free((p->value));
1037 }
1038 db = p->next;
1039 Xfree(p)free((p));
1040 p = db;
1041 }
1042}
1043
1044static int
1045CountDatabase(
1046 Database db)
1047{
1048 Database p = db;
1049 int cnt = 0;
1050
1051 while (p) {
1052 ++cnt;
1053 p = p->next;
1054 }
1055 return cnt;
1056}
1057
1058static Database
1059CreateDatabase(
1060 char *dbfile)
1061{
1062 Database db = (Database)NULL((void*)0);
1063 FILE *fd;
1064 Line line;
1065 char *p;
1066 Token token;
1067 int len;
1068 int error = 0;
1069
1070 fd = _XFopenFile(dbfile, "r")fopen(dbfile,"r");
1071 if (fd == (FILE *)NULL((void*)0))
1072 return NULL((void*)0);
1073
1074 bzero(&line, sizeof(Line))__builtin___memset_chk (&line, 0, sizeof(Line), __builtin_object_size
(&line, 0))
;
1075 init_parse_info();
1076
1077 do {
1078 int rc = read_line(fd, &line);
1079 if (rc < 0) {
1080 error = 1;
1081 break;
1082 } else if (rc == 0) {
1083 break;
1084 }
1085 p = line.str;
1086 while (*p) {
1087 int (*parse_proc)(const char *str, Token token, Database *db) = NULL((void*)0);
1088
1089 token = get_token(p);
1090
1091 switch (token_tbl[token].token) {
1092 case T_NEWLINE:
1093 parse_proc = f_newline;
1094 break;
1095 case T_COMMENT:
1096 parse_proc = f_comment;
1097 break;
1098 case T_SEMICOLON:
1099 parse_proc = f_semicolon;
1100 break;
1101 case T_DOUBLE_QUOTE:
1102 parse_proc = f_double_quote;
1103 break;
1104 case T_LEFT_BRACE:
1105 parse_proc = f_left_brace;
1106 break;
1107 case T_RIGHT_BRACE:
1108 parse_proc = f_right_brace;
1109 break;
1110 case T_SPACE:
1111 case T_TAB:
1112 parse_proc = f_white;
1113 break;
1114 case T_BACKSLASH:
1115 parse_proc = f_backslash;
1116 break;
1117 case T_NUMERIC_HEX:
1118 case T_NUMERIC_DEC:
1119 case T_NUMERIC_OCT:
1120 parse_proc = f_numeric;
1121 break;
1122 case T_DEFAULT:
1123 parse_proc = f_default;
1124 break;
1125 }
1126
1127 len = parse_proc(p, token, &db);
1128
1129 if (len < 1) {
1130 error = 1;
1131 break;
1132 }
1133 p += len;
1134 }
1135 } while (!error);
1136
1137 if (parse_info.pre_state != S_NULL) {
1138 clear_parse_info();
1139 error = 1;
1140 }
1141 if (error) {
1142#ifdef DEBUG
1143 fprintf(stderr__stderrp, "database format error at line %d.\n", line.seq);
1144#endif
1145 DestroyDatabase(db);
1146 db = (Database)NULL((void*)0);
1147 }
1148
1149 fclose(fd);
1150 free_line(&line);
1151
1152#ifdef DEBUG
1153 PrintDatabase(db);
1154#endif
1155
1156 return db;
1157}
1158
1159/************************************************************************/
1160
1161#ifndef NOT_X_ENV
1162
1163/* locale framework functions */
1164
1165typedef struct _XlcDatabaseRec {
1166 XrmQuark category_q;
1167 XrmQuark name_q;
1168 Database db;
1169 struct _XlcDatabaseRec *next;
1170} XlcDatabaseRec, *XlcDatabase;
1171
1172typedef struct _XlcDatabaseListRec {
1173 XrmQuark name_q;
1174 XlcDatabase lc_db;
1175 Database database;
1176 int ref_count;
1177 struct _XlcDatabaseListRec *next;
1178} XlcDatabaseListRec, *XlcDatabaseList;
1179
1180/* database cache list (per file) */
1181static XlcDatabaseList _db_list = (XlcDatabaseList)NULL((void*)0);
1182
1183/************************************************************************/
1184/* _XlcGetResource(lcd, category, class, value, count) */
1185/*----------------------------------------------------------------------*/
1186/* This function retrieves XLocale database information. */
1187/************************************************************************/
1188void
1189_XlcGetResource(
1190 XLCd lcd,
1191 const char *category,
1192 const char *class,
1193 char ***value,
1194 int *count)
1195{
1196 XLCdPublicMethodsPart *methods = XLC_PUBLIC_METHODS(lcd)(&(((XLCdPublicMethods) lcd->methods)->pub));
1197
1198 (*methods->get_resource)(lcd, category, class, value, count);
1199 return;
1200}
1201
1202/************************************************************************/
1203/* _XlcGetLocaleDataBase(lcd, category, class, value, count) */
1204/*----------------------------------------------------------------------*/
1205/* This function retrieves XLocale database information. */
1206/************************************************************************/
1207void
1208_XlcGetLocaleDataBase(
1209 XLCd lcd,
1210 const char *category,
1211 const char *name,
1212 char ***value,
1213 int *count)
1214{
1215 XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db)(((XLCdPublic) lcd->core)->pub.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 return;
1225 }
1226 }
1227 *value = (char **)NULL((void*)0);
1228 *count = 0;
1229}
1230
1231/************************************************************************/
1232/* _XlcDestroyLocaleDataBase(lcd) */
1233/*----------------------------------------------------------------------*/
1234/* This function destroy the XLocale Database that bound to the */
1235/* specified lcd. If the XLocale Database is refered from some */
1236/* other lcd, this function just decreases reference count of */
1237/* the database. If no locale refers the database, this function */
1238/* remove it from the cache list and free work area. */
1239/************************************************************************/
1240void
1241_XlcDestroyLocaleDataBase(
1242 XLCd lcd)
1243{
1244 XlcDatabase lc_db = (XlcDatabase)XLC_PUBLIC(lcd, xlocale_db)(((XLCdPublic) lcd->core)->pub.xlocale_db);
1245 XlcDatabaseList p, prev;
1246
1247 for (p = _db_list, prev = (XlcDatabaseList)NULL((void*)0); p;
1248 prev = p, p = p->next) {
1249 if (p->lc_db == lc_db) {
1250 if ((-- p->ref_count) < 1) {
1251 if (p->lc_db != (XlcDatabase)NULL((void*)0)) {
1252 Xfree(p->lc_db)free((p->lc_db));
1253 }
1254 DestroyDatabase(p->database);
1255 if (prev == (XlcDatabaseList)NULL((void*)0)) {
1256 _db_list = p->next;
1257 } else {
1258 prev->next = p->next;
1259 }
1260 Xfree((char*)p)free(((char*)p));
1261 }
1262 break;
1263 }
1264 }
1265 XLC_PUBLIC(lcd, xlocale_db)(((XLCdPublic) lcd->core)->pub.xlocale_db) = (XPointer)NULL((void*)0);
1266}
1267
1268/************************************************************************/
1269/* _XlcCreateLocaleDataBase(lcd) */
1270/*----------------------------------------------------------------------*/
1271/* This function create an XLocale database which correspond to */
1272/* the specified XLCd. */
1273/************************************************************************/
1274XPointer
1275_XlcCreateLocaleDataBase(
1276 XLCd lcd)
1277{
1278 XlcDatabaseList list, new;
1279 Database p, database = (Database)NULL((void*)0);
1280 XlcDatabase lc_db = (XlcDatabase)NULL((void*)0);
1281 XrmQuark name_q;
1282 char *name;
1283 int i, n;
1284
1285 name = _XlcFileName(lcd, "locale");
1286 if (name == NULL((void*)0))
1287 return (XPointer)NULL((void*)0);
1288
1289#ifndef __UNIXOS2__
1290 name_q = XrmStringToQuark(name);
1291#else
1292 name_q = XrmStringToQuark((char*)__XOS2RedirRoot(name));
1293#endif
1294 for (list = _db_list; list; list = list->next) {
1295 if (name_q == list->name_q) {
1296 list->ref_count++;
1297 Xfree (name)free((name));
1298 return XLC_PUBLIC(lcd, xlocale_db)(((XLCdPublic) lcd->core)->pub.xlocale_db) = (XPointer)list->lc_db;
1299 }
1300 }
1301
1302 database = CreateDatabase(name);
1303 if (database == (Database)NULL((void*)0)) {
1304 Xfree (name)free((name));
1305 return (XPointer)NULL((void*)0);
1306 }
1307 n = CountDatabase(database);
1308 lc_db = Xcalloc(n + 1, sizeof(XlcDatabaseRec))calloc(((n + 1) == 0 ? 1 : (n + 1)), (sizeof(XlcDatabaseRec))
)
;
1309 if (lc_db == (XlcDatabase)NULL((void*)0))
1310 goto err;
1311 for (p = database, i = 0; p && i < n; p = p->next, ++i) {
1312 lc_db[i].category_q = XrmStringToQuark(p->category);
1313 lc_db[i].name_q = XrmStringToQuark(p->name);
1314 lc_db[i].db = p;
1315 }
1316
1317 new = Xmalloc(sizeof(XlcDatabaseListRec))malloc(((sizeof(XlcDatabaseListRec)) == 0 ? 1 : (sizeof(XlcDatabaseListRec
))))
;
1318 if (new == (XlcDatabaseList)NULL((void*)0)) {
1319 goto err;
1320 }
1321 new->name_q = name_q;
1322 new->lc_db = lc_db;
1323 new->database = database;
1324 new->ref_count = 1;
1325 new->next = _db_list;
1326 _db_list = new;
1327
1328 Xfree (name)free((name));
1329 return XLC_PUBLIC(lcd, xlocale_db)(((XLCdPublic) lcd->core)->pub.xlocale_db) = (XPointer)lc_db;
1330
1331 err:
1332 DestroyDatabase(database);
1333 if (lc_db != (XlcDatabase)NULL((void*)0)) {
1334 Xfree(lc_db)free((lc_db));
1335 }
1336 Xfree (name)free((name));
1337 return (XPointer)NULL((void*)0);
1338}
1339
1340#endif /* NOT_X_ENV */