]> git.ipfire.org Git - thirdparty/glibc.git/blob - nss/nss_files/files-parse.c
* nss/nss_files/files-parse.c (parse_list): Reset ELT for elements
[thirdparty/glibc.git] / nss / nss_files / files-parse.c
1 /* Common code for file-based database parsers in nss_files module.
2 Copyright (C) 1996 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If
17 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
18 Cambridge, MA 02139, USA. */
19
20 #include <ctype.h>
21 #include <errno.h>
22 #include <string.h>
23 #include <stdlib.h>
24
25
26 #define CONCAT(a,b) CONCAT1(a,b)
27 #define CONCAT1(a,b) a##b
28
29 #ifndef STRUCTURE
30 #define STRUCTURE ENTNAME
31 #endif
32
33
34 struct parser_data
35 {
36 struct CONCAT(ENTNAME,_data) entdata;
37 char linebuffer[0];
38 };
39
40 #define LINE_PARSER(BODY) \
41 static inline int \
42 parse_line (char *line, struct STRUCTURE *result, \
43 struct parser_data *data, int datalen) \
44 { \
45 struct CONCAT(ENTNAME,_data) *const entdata __attribute__ ((unused)) \
46 = &data->entdata; \
47 BODY; \
48 TRAILING_LIST_PARSER; \
49 return 1; \
50 }
51
52
53 /* Comments can come mid-line; trim the line at the first # seen. */
54 #define MIDLINE_COMMENTS \
55 { \
56 char *p = strchr (line, '#'); \
57 if (p) \
58 *p = '\0'; \
59 }
60
61 #define STRING_FIELD(variable, terminator_p, swallow) \
62 { \
63 variable = line; \
64 while (!terminator_p (*line)) \
65 if (*++line == '\0') \
66 return 0; \
67 *line = '\0'; \
68 do \
69 ++line; \
70 while (swallow && terminator_p (*line)); \
71 }
72
73 #define INT_FIELD(variable, terminator_p, swallow, base, convert) \
74 { \
75 char *endp; \
76 variable = convert (strtol (line, &endp, base)); \
77 if (endp == line) \
78 return 0; \
79 else if (terminator_p (*endp)) \
80 do \
81 ++endp; \
82 while (swallow && terminator_p (*endp)); \
83 else if (*endp != '\0') \
84 return 0; \
85 line = endp; \
86 }
87
88 #define ISCOLON(c) ((c) == ':')
89
90
91 #ifndef TRAILING_LIST_MEMBER
92 #define TRAILING_LIST_PARSER /* Nothing to do. */
93 #else
94
95 #define TRAILING_LIST_PARSER \
96 { \
97 char **list = parse_list (line, data, datalen); \
98 if (list) \
99 result->TRAILING_LIST_MEMBER = list; \
100 else \
101 return 0; \
102 }
103
104 static inline char **
105 parse_list (char *line, struct parser_data *data, int datalen)
106 {
107 char *eol, **list, **p;
108
109 /* Find the end of the line buffer. */
110 eol = strchr (line, '\0');
111 /* Adjust the pointer so it is aligned for storing pointers. */
112 eol += (eol - (char *) 0) % __alignof__ (char *);
113 /* We will start the storage here for the vector of pointers. */
114 list = (char **) eol;
115
116 p = list;
117 while (1)
118 {
119 char *elt;
120
121 if ((char *) &p[1] - (char *) data > datalen)
122 {
123 /* We cannot fit another pointer in the buffer. */
124 errno = ERANGE;
125 return NULL;
126 }
127 if (*line == '\0')
128 break;
129
130 elt = line;
131 while (1)
132 {
133 if (TRAILING_LIST_SEPARATOR_P (*line))
134 {
135 *p++ = elt;
136 *line = '\0';
137 do
138 ++line;
139 while (TRAILING_LIST_SEPARATOR_P (*line));
140 elt = line;
141 }
142 else if (*line == '\0' || *line == '\n')
143 {
144 /* End of the line. */
145 if (line > elt)
146 /* Last element. */
147 *p++ = elt;
148 *line = '\0';
149 break;
150 }
151 else
152 ++line;
153 }
154 }
155 *p = NULL;
156
157 return list;
158 }
159
160 #define LOOKUP_NAME(nameelt, aliaselt) \
161 { \
162 char **ap; \
163 if (! strcmp (name, result->nameelt)) \
164 break; \
165 for (ap = result->aliaselt; *ap; ++ap) \
166 if (! strcmp (name, *ap)) \
167 break; \
168 if (*ap) \
169 break; \
170 }
171
172 #endif