Skip to content

Commit 3b1b9df

Browse files
committed
Support reading from input files
1 parent 8b766a0 commit 3b1b9df

File tree

2 files changed

+81
-32
lines changed

2 files changed

+81
-32
lines changed

cypher-lint.1.in

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,11 @@
1919
.SH NAME
2020
cypher\-lint \- a linting tool for Cypher
2121
.SH SYNOPSIS
22-
.B cypher\-lint \fI[options...]\fR
22+
.B cypher\-lint \fI[options] [file ...]\fR
2323
.SH "DESCRIPTION"
24-
\fBcypher\-lint\fR is a linting tool for Cypher.
24+
\fBcypher\-lint\fR is a linting tool for Cypher. It reads from input files,
25+
reports any errors found, and optionally outputs the parsed AST. If \fBfile\fR
26+
is a single dash (`-') or absent, \fBcypher\-lint\fR reads from standard input.
2527
.SH OPTIONS
2628
.TP
2729
.I \-1
@@ -52,8 +54,8 @@ first (note: will result in inconsistent formatting of AST dumps).
5254
.TP
5355
.I \-\-version
5456
Print the cypher\-lint version and exit.
55-
.SH USAGE
56-
.SH ERRORS
57+
.SH EXIT STATUS
58+
\fBcypher\-lint\fR exits 0 if no errors are found, and >0 otherwise.
5759
.SH VERSION
5860
This man page is current for version @VERSION@ of cypher\-lint.
5961
.SH COPYRIGHT

src/bin/cypher-lint.c

Lines changed: 75 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ static struct option longopts[] =
5151
static void usage(FILE *s, const char *prog_name)
5252
{
5353
fprintf(s,
54-
"usage: %s [OPTIONS]\n"
54+
"usage: %s [OPTIONS] [file ...]\n"
5555
"options:\n"
5656
" -1 Only parse the first statement or client-command.\n"
5757
" --ast, -a Dump the AST to stdout.\n"
@@ -64,6 +64,8 @@ static void usage(FILE *s, const char *prog_name)
6464
" the entire input first (note: will result in inconsistent\n"
6565
" formatting of AST dumps).\n"
6666
" --version Output the version of cypher-lint and libcypher-parser\n"
67+
"\n"
68+
"If no input files are specified, then input is read from standard input.\n"
6769
"\n",
6870
prog_name);
6971
}
@@ -80,18 +82,19 @@ struct lint_config
8082
};
8183

8284

83-
static int process(FILE *stream, struct lint_config *config);
84-
static int process_streamed(FILE *stream, struct lint_config *config,
85-
cypher_parser_config_t *cp_config,
85+
static int process(FILE *stream, const char *filename,
86+
struct lint_config *config);
87+
static int process_streamed(FILE *stream, const char *filename,
88+
struct lint_config *config, cypher_parser_config_t *cp_config,
8689
const struct cypher_parser_colorization *error_colorization,
8790
const struct cypher_parser_colorization *output_colorization);
88-
static int process_all(FILE *stream, struct lint_config *config,
89-
cypher_parser_config_t *cp_config,
91+
static int process_all(FILE *stream, const char *filename,
92+
struct lint_config *config, cypher_parser_config_t *cp_config,
9093
const struct cypher_parser_colorization *error_colorization,
9194
const struct cypher_parser_colorization *output_colorization);
9295
static int parse_callback(void *data, cypher_parse_segment_t *segment);
93-
static void print_error(const cypher_parse_error_t *error,
94-
const struct cypher_parser_colorization *colorization);
96+
static void print_error(const cypher_parse_error_t *error, const char *filename,
97+
const struct cypher_parser_colorization *colorization);
9598

9699

97100
int main(int argc, char *argv[])
@@ -169,9 +172,45 @@ int main(int argc, char *argv[])
169172
config.stream = true;
170173
}
171174

172-
if (process(stdin, &config))
175+
if (argc > 0)
173176
{
174-
goto cleanup;
177+
int err = 0;
178+
for (; argc > 0; --argc, ++argv)
179+
{
180+
int res;
181+
if (strcmp(*argv, "-") == 0)
182+
{
183+
res = process(stdin, "<stdin>", &config);
184+
}
185+
else
186+
{
187+
FILE *stream = fopen(*argv, "r");
188+
if (stream == NULL)
189+
{
190+
fprintf(stderr, "%s: %s: %s\n", prog_name, *argv,
191+
strerror(errno));
192+
goto cleanup;
193+
}
194+
res = process(stream, *argv, &config);
195+
if (res < 0)
196+
{
197+
goto cleanup;
198+
}
199+
fclose(stream);
200+
}
201+
err |= res;
202+
}
203+
if (err)
204+
{
205+
goto cleanup;
206+
}
207+
}
208+
else
209+
{
210+
if (process(stdin, NULL, &config))
211+
{
212+
goto cleanup;
213+
}
175214
}
176215

177216
result = EXIT_SUCCESS;
@@ -181,7 +220,7 @@ int main(int argc, char *argv[])
181220
}
182221

183222

184-
int process(FILE *stream, struct lint_config *config)
223+
int process(FILE *stream, const char *filename, struct lint_config *config)
185224
{
186225
cypher_parser_config_t *cp_config = cypher_parser_new_config();
187226
if (cp_config == NULL)
@@ -202,9 +241,9 @@ int process(FILE *stream, struct lint_config *config)
202241
config->colorize_output? cypher_parser_ansi_colorization : NULL;
203242

204243
int err = (config->stream)?
205-
process_streamed(stream, config, cp_config,
244+
process_streamed(stream, filename, config, cp_config,
206245
error_colorization, output_colorization) :
207-
process_all(stream, config, cp_config,
246+
process_all(stream, filename, config, cp_config,
208247
error_colorization, output_colorization);
209248

210249
int errsv = errno;
@@ -216,20 +255,22 @@ int process(FILE *stream, struct lint_config *config)
216255

217256
struct parse_callback_data
218257
{
258+
const char *filename;
219259
struct lint_config *config;
220260
const struct cypher_parser_colorization *error_colorization;
221261
const struct cypher_parser_colorization *output_colorization;
222262
unsigned int nerrors;
223263
};
224264

225265

226-
int process_streamed(FILE *stream, struct lint_config *config,
227-
cypher_parser_config_t *cp_config,
266+
int process_streamed(FILE *stream, const char *filename,
267+
struct lint_config *config, cypher_parser_config_t *cp_config,
228268
const struct cypher_parser_colorization *error_colorization,
229269
const struct cypher_parser_colorization *output_colorization)
230270
{
231271
struct parse_callback_data callback_data =
232-
{ .config = config,
272+
{ .filename = filename,
273+
.config = config,
233274
.error_colorization = error_colorization,
234275
.output_colorization = output_colorization,
235276
.nerrors = 0
@@ -256,7 +297,7 @@ int parse_callback(void *data, cypher_parse_segment_t *segment)
256297
const cypher_parse_error_t *error;
257298
for (; (error = cypher_parse_segment_get_error(segment, i)) != NULL; ++i)
258299
{
259-
print_error(error, cbdata->error_colorization);
300+
print_error(error, cbdata->filename, cbdata->error_colorization);
260301
}
261302

262303
cbdata->nerrors += i;
@@ -272,8 +313,8 @@ int parse_callback(void *data, cypher_parse_segment_t *segment)
272313
}
273314

274315

275-
int process_all(FILE *stream, struct lint_config *config,
276-
cypher_parser_config_t *cp_config,
316+
int process_all(FILE *stream, const char *filename,
317+
struct lint_config *config, cypher_parser_config_t *cp_config,
277318
const struct cypher_parser_colorization *error_colorization,
278319
const struct cypher_parser_colorization *output_colorization)
279320
{
@@ -291,14 +332,21 @@ int process_all(FILE *stream, struct lint_config *config,
291332
const cypher_parse_error_t *error;
292333
for (; (error = cypher_parse_result_get_error(result, i)) != NULL; ++i)
293334
{
294-
print_error(error, error_colorization);
335+
print_error(error, filename, error_colorization);
295336
}
296337

297-
if (config->dump_ast && cypher_parse_result_fprint_ast(result, stdout,
298-
config->width, output_colorization, 0) < 0)
338+
if (config->dump_ast)
299339
{
300-
perror("cypher_parse_result_fprint_ast");
301-
goto cleanup;
340+
if (filename != NULL)
341+
{
342+
printf("%s:\n", filename);
343+
}
344+
if (cypher_parse_result_fprint_ast(result, stdout,
345+
config->width, output_colorization, 0) < 0)
346+
{
347+
perror("cypher_parse_result_fprint_ast");
348+
goto cleanup;
349+
}
302350
}
303351

304352
err = (cypher_parse_result_nerrors(result) == 0)? 0 : 1;
@@ -312,15 +360,14 @@ int process_all(FILE *stream, struct lint_config *config,
312360
}
313361

314362

315-
void print_error(const cypher_parse_error_t *error,
363+
void print_error(const cypher_parse_error_t *error, const char *filename,
316364
const struct cypher_parser_colorization *colorization)
317365
{
318366
struct cypher_input_position pos = cypher_parse_error_position(error);
319367
const char *msg = cypher_parse_error_message(error);
320368
const char *context = cypher_parse_error_context(error);
321369
unsigned int offset = cypher_parse_error_context_offset(error);
322-
fprintf(stderr, "%s %s(line %u, column %u, offset %zu)%s%s\n", msg,
323-
colorization->error_message[0], pos.line, pos.column, pos.offset,
324-
colorization->error_message[1], (context == NULL)? "" : ":");
370+
fprintf(stderr, "%s:%u:%u: %s\n", (filename != NULL)? filename : "<stdin>",
371+
pos.line, pos.column, msg);
325372
fprintf(stderr, "%s\n%*.*s^\n", context, offset, offset, " ");
326373
}

0 commit comments

Comments
 (0)