1 /*
2  * Copyright 2000
3  *      Traakan, Inc., Los Altos, CA
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *      Stanza files look about like this:
35  *              [stanza name line]
36  *              stanza body lines
37  *
38  *      These are used for config files.
39  */
40 
41 
42 #include "ndmlib.h"
43 
44 
ndmstz_getline(FILE * fp,char * buf,int n_buf)45 int ndmstz_getline(FILE* fp, char* buf, int n_buf)
46 {
47   int c;
48   char* p;
49 
50 again:
51   c = getc(fp);
52   if (c == EOF) return EOF;
53 
54   if (c == '[') {
55     /* end-of-stanza */
56     ungetc(c, fp);
57     return -2;
58   }
59 
60   if (c == '#') {
61     /* comment */
62     while ((c = getc(fp)) != EOF && c != '\n') continue;
63     goto again;
64   }
65 
66   ungetc(c, fp);
67   p = buf;
68   while ((c = getc(fp)) != EOF && c != '\n') {
69     if (p < &buf[n_buf - 1]) *p++ = c;
70   }
71   *p = 0;
72   return p - buf;
73 }
74 
ndmstz_getstanza(FILE * fp,char * buf,int n_buf)75 int ndmstz_getstanza(FILE* fp, char* buf, int n_buf)
76 {
77   int c;
78   char* p;
79 
80 again:
81   c = getc(fp);
82   if (c == EOF) return EOF;
83 
84   if (c == '\n') goto again; /* blank line */
85 
86   if (c != '[') {
87     /* not a stanza header, eat line */
88     while ((c = getc(fp)) != EOF && c != '\n') continue;
89     goto again;
90   }
91 
92   p = buf;
93   while ((c = getc(fp)) != EOF && c != '\n' && c != ']') {
94     if (p < &buf[n_buf - 1]) *p++ = c;
95   }
96   *p = 0;
97 
98   if (c == ']') {
99     /* eat rest of line */
100     while ((c = getc(fp)) != EOF && c != '\n') continue;
101   }
102 
103   /* fp is left pointing to begining of first line */
104 
105   return p - buf;
106 }
107 
ndmstz_parse(char * buf,char * argv[],int max_argv)108 int ndmstz_parse(char* buf, char* argv[], int max_argv)
109 {
110   char* p = buf;
111   char* q = buf;
112   int inword = 0;
113   int inquote = 0;
114   int argc = 0;
115   int c;
116 
117   while ((c = *p++) != 0) {
118     if (inquote) {
119       if (c == inquote) {
120         inquote = 0;
121       } else {
122         *q++ = c;
123       }
124       continue;
125     }
126 
127     if (isspace(c)) {
128       if (inword) {
129         *q++ = 0;
130         inword = 0;
131       }
132       continue;
133     }
134 
135     if (!inword) {
136       if (argc > max_argv - 1) break;
137       argv[argc++] = q;
138       inword = 1;
139     }
140 
141     if (c == '"' || c == '\'') {
142       inquote = c;
143       continue;
144     }
145 
146     *q++ = c;
147   }
148   if (inword) *q++ = 0;
149   argv[argc] = 0;
150 
151   return argc;
152 }
153 
154 
155 #ifdef SELF_TEST
156 
main(int ac,char * av[])157 int main(int ac, char* av[])
158 {
159   int i, found, argc;
160   FILE* fp;
161   char buf[512];
162   char* argv[100];
163 
164   if (ac < 2) {
165     printf("bad usage\n");
166     return 1;
167   }
168 
169   fp = fopen(av[1], "r");
170   if (!fp) {
171     perror(av[1]);
172     return 2;
173   }
174 
175   if (ac == 2) {
176     while (ndmstz_getstanza(fp, buf, sizeof buf) >= 0) printf("%s\n", buf);
177   } else {
178     for (i = 2; i < ac; i++) {
179       rewind(fp);
180       found = 0;
181       while (ndmstz_getstanza(fp, buf, sizeof buf) >= 0) {
182         if (strcmp(av[i], buf) == 0) {
183           found = 1;
184           break;
185         }
186       }
187       if (!found) {
188         printf("Search for '%s' failed\n", av[i]);
189         continue;
190       }
191       printf("'%s'\n", buf);
192       printf("========================================\n");
193       while (ndmstz_getline(fp, buf, sizeof buf) >= 0) {
194         printf("= %s", buf);
195         argc = ndmstz_parse(buf, argv, 100);
196         printf(" [%d]\n", argc);
197       }
198       printf("========================================\n");
199     }
200   }
201 
202   fclose(fp);
203 
204   return 0;
205 }
206 
207 #endif /* SELF_TEST */
208