Mon Jul 1 12:29:50 1996 Roland McGrath <roland@delasyd.gnu.ai.mit.edu>
[kopensolaris-gnu/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 #ifdef ENTDATA
37     struct ENTDATA entdata;
38 #define ENTDATA_DECL(data) struct ENTDATA *const entdata = &data->entdata
39 #else
40 #define ENTDATA_DECL(data)
41 #endif
42     char linebuffer[0];
43   };
44
45 #ifdef ENTDATA
46 /* The function can't be exported, because the entdata structure
47    is defined only in files-foo.c.  */
48 #define parser_stclass static inline
49 #else
50 /* Export the line parser function so it can be used in nss_db.  */
51 #define parser_stclass /* Global */
52 #define parse_line CONCAT(_nss_files_parse_,ENTNAME)
53 #endif
54
55 #define LINE_PARSER(BODY)                                                     \
56 parser_stclass int                                                            \
57 parse_line (char *line, struct STRUCTURE *result,                             \
58             struct parser_data *data, int datalen)                            \
59 {                                                                             \
60   ENTDATA_DECL (data);                                                        \
61   BODY;                                                                       \
62   TRAILING_LIST_PARSER;                                                       \
63   return 1;                                                                   \
64 }
65
66
67 /* Comments can come mid-line; trim the line at the first # seen.  */
68 #define MIDLINE_COMMENTS                                                      \
69   {                                                                           \
70     char *p = strchr (line, '#');                                             \
71     if (p)                                                                    \
72       *p = '\0';                                                              \
73   }
74
75 #define STRING_FIELD(variable, terminator_p, swallow)                         \
76   {                                                                           \
77     variable = line;                                                          \
78     while (!terminator_p (*line))                                             \
79       if (*++line == '\0')                                                    \
80         return 0;                                                             \
81     *line = '\0';                                                             \
82     do                                                                        \
83       ++line;                                                                 \
84     while (swallow && terminator_p (*line));                                  \
85   }
86
87 #define INT_FIELD(variable, terminator_p, swallow, base, convert)             \
88   {                                                                           \
89     char *endp;                                                               \
90     variable = convert (strtol (line, &endp, base));                          \
91     if (endp == line)                                                         \
92       return 0;                                                               \
93     else if (terminator_p (*endp))                                            \
94       do                                                                      \
95         ++endp;                                                               \
96       while (swallow && terminator_p (*endp));                                \
97     else if (*endp != '\0')                                                   \
98       return 0;                                                               \
99     line = endp;                                                              \
100   }
101
102 #define ISCOLON(c) ((c) == ':')
103
104
105 #ifndef TRAILING_LIST_MEMBER
106 #define TRAILING_LIST_PARSER /* Nothing to do.  */
107 #else
108
109 #define TRAILING_LIST_PARSER                                                  \
110 {                                                                             \
111   char **list = parse_list (line, data, datalen);                             \
112   if (list)                                                                   \
113     result->TRAILING_LIST_MEMBER = list;                                      \
114   else                                                                        \
115     return 0;                                                                 \
116 }
117
118 static inline char **
119 parse_list (char *line, struct parser_data *data, int datalen)
120 {
121   char *eol, **list, **p;
122
123   /* Find the end of the line buffer.  */
124   eol = strchr (data->linebuffer, '\0') + 1;
125   /* Adjust the pointer so it is aligned for storing pointers.  */
126   eol += __alignof__ (char *) - 1;
127   eol -= (eol - (char *) 0) % __alignof__ (char *);
128   /* We will start the storage here for the vector of pointers.  */
129   list = (char **) eol;
130
131   p = list;
132   while (1)
133     {
134       char *elt;
135
136       if ((char *) &p[1] - (char *) data > datalen)
137         {
138           /* We cannot fit another pointer in the buffer.  */
139           errno = ERANGE;
140           return NULL;
141         }
142       if (*line == '\0')
143         break;
144
145       elt = line;
146       while (1)
147         {
148           if (TRAILING_LIST_SEPARATOR_P (*line))
149             {
150               *p++ = elt;
151               *line = '\0';
152               do
153                 ++line;
154               while (TRAILING_LIST_SEPARATOR_P (*line));
155               elt = line;
156             }
157           else if (*line == '\0' || *line == '\n')
158             {
159               /* End of the line.  */
160               if (line > elt)
161                 /* Last element.  */
162                 *p++ = elt;
163               *line = '\0';
164               break;
165             }
166           else
167             ++line;
168         }
169     }
170   *p = NULL;
171
172   return list;
173 }
174
175 #define LOOKUP_NAME(nameelt, aliaselt)                                        \
176 {                                                                             \
177   char **ap;                                                                  \
178   if (! strcmp (name, result->nameelt))                                       \
179     break;                                                                    \
180   for (ap = result->aliaselt; *ap; ++ap)                                      \
181     if (! strcmp (name, *ap))                                                 \
182       break;                                                                  \
183   if (*ap)                                                                    \
184     break;                                                                    \
185 }
186
187 #endif