Mon Jun 24 19:57:01 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     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             }
141           else if (*line == '\0' || *line == '\n')
142             {
143               /* End of the line.  */
144               if (line > elt)
145                 /* Last element.  */
146                 *p++ = elt;
147               *line = '\0';
148               break;
149             }
150           else
151             ++line;
152         }
153     }
154   *p = NULL;
155
156   return list;
157 }
158
159 #define LOOKUP_NAME(nameelt, aliaselt)                                        \
160 {                                                                             \
161   char **ap;                                                                  \
162   if (! strcmp (name, result->nameelt))                                       \
163     break;                                                                    \
164   for (ap = result->aliaselt; *ap; ++ap)                                      \
165     if (! strcmp (name, *ap))                                                 \
166       break;                                                                  \
167   if (*ap)                                                                    \
168     break;                                                                    \
169 }
170
171 #endif