2 * Copyright (c) 2009-2011 Alex Hornung <alex@alexhornung.com>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
22 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #define _iswhitespace(X) ((((X) == ' ') || ((X) == '\t'))?1:0)
42 static int line_no
= 1;
44 static int iswhitespace(char c
)
46 return _iswhitespace(c
);
49 static int iscomma(char c
)
55 syntax_error(const char *fmt
, ...)
61 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
63 errx(1, "syntax error on line %d: %s\n", line_no
, buf
);
68 entry_check_num_args(char **tokens
, int num
)
72 for (i
= 0; tokens
[i
] != NULL
; i
++)
76 syntax_error("at least %d tokens were expected but only %d "
77 "were found", num
, i
);
84 line_tokenize(char *buffer
, int (*is_sep
)(char), char comment_char
, char **tokens
)
89 i
= strlen(buffer
) + 1;
92 /* Skip leading white-space */
93 while ((_iswhitespace(buffer
[c
])) && (c
< i
)) c
++;
96 * If this line effectively (after indentation) begins with the comment
97 * character, we ignore the rest of the line.
99 if (buffer
[c
] == comment_char
)
102 tokens
[0] = &buffer
[c
];
103 for (n
= 1; c
< i
; c
++) {
104 if (buffer
[c
] == '"') {
107 if ((c
>= 1) && (&buffer
[c
] != tokens
[n
-1])) {
109 syntax_error("stray opening quote not "
110 "at beginning of token");
114 tokens
[n
-1] = &buffer
[c
+1];
117 if ((c
< i
-1) && (!is_sep(buffer
[c
+1]))) {
119 syntax_error("stray closing quote not "
133 if (is_sep(buffer
[c
])) {
135 while ((_iswhitespace(buffer
[c
])) && (c
< i
)) c
++;
136 tokens
[n
++] = &buffer
[c
--];
150 process_line(FILE* fd
, parser_t parser
, void *arg
)
157 while (((c
= fgetc(fd
)) != EOF
) && (c
!= '\n')) {
158 buffer
[i
++] = (char)c
;
159 if (i
== (sizeof(buffer
) -1))
164 if (feof(fd
) || ferror(fd
))
168 n
= line_tokenize(buffer
, &iswhitespace
, '#', tokens
);
171 * If there are not enough arguments for any function or it is
172 * a line full of whitespaces, we just return here. Or if a
173 * quote wasn't closed.
175 if ((n
< 1) || (tokens
[0][0] == '\0'))
184 parse_options(char *str
, char **options
)
188 i
= line_tokenize(str
, &iscomma
, '#', options
);
190 syntax_error("Invalid expression in options token");
197 process_file(const char *file
, parser_t parser
, void *arg
, int *nlines
)
203 fd
= fopen(file
, "r");
208 while (process_line(fd
, parser
, arg
) == 0)