2021-01-12 21:04:43 -08:00
|
|
|
//
|
|
|
|
// bp.c - Source code for the bp parser
|
|
|
|
//
|
|
|
|
// See `man ./bp.1` for more details
|
|
|
|
//
|
2020-09-11 01:28:06 -07:00
|
|
|
#include <fcntl.h>
|
2020-09-13 15:55:09 -07:00
|
|
|
#include <glob.h>
|
2020-09-12 15:49:51 -07:00
|
|
|
#include <limits.h>
|
2020-09-11 01:28:06 -07:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "compiler.h"
|
2020-09-16 19:35:43 -07:00
|
|
|
#include "file_loader.h"
|
2020-09-11 01:28:06 -07:00
|
|
|
#include "grammar.h"
|
2020-12-14 22:20:16 -08:00
|
|
|
#include "json.h"
|
2021-01-08 01:06:43 -08:00
|
|
|
#include "printing.h"
|
2020-09-11 01:28:06 -07:00
|
|
|
#include "utils.h"
|
|
|
|
#include "vm.h"
|
|
|
|
|
|
|
|
static const char *usage = (
|
2020-12-12 16:31:53 -08:00
|
|
|
"BP - a Parsing Expression Grammar command line tool\n\n"
|
2020-09-11 01:28:06 -07:00
|
|
|
"Usage:\n"
|
2020-12-12 16:31:53 -08:00
|
|
|
" bp [flags] <pattern> [<input files>...]\n\n"
|
2020-09-11 01:28:06 -07:00
|
|
|
"Flags:\n"
|
2020-09-14 12:39:31 -07:00
|
|
|
" -h --help print the usage and quit\n"
|
|
|
|
" -v --verbose print verbose debugging info\n"
|
2020-12-12 16:31:53 -08:00
|
|
|
" -e --explain explain the matches\n"
|
2020-12-14 22:32:47 -08:00
|
|
|
" -j --json print matches as a list of JSON objects\n"
|
2020-12-27 19:48:52 -08:00
|
|
|
" -I --inplace modify a file in-place\n"
|
2020-09-14 12:39:31 -07:00
|
|
|
" -i --ignore-case preform matching case-insensitively\n"
|
2020-12-17 16:23:29 -08:00
|
|
|
" -l --list-files list filenames only\n"
|
2020-09-16 22:39:33 -07:00
|
|
|
" -d --define <name>:<def> define a grammar rule\n"
|
|
|
|
" -D --define-string <name>:<def> define a grammar rule (string-pattern)\n"
|
2020-12-12 16:31:53 -08:00
|
|
|
" -p --pattern <pat> provide a pattern (equivalent to bp '\\(<pat>)')\n"
|
2020-09-14 12:39:31 -07:00
|
|
|
" -P --pattern-string <pat> provide a string pattern (may be useful if '<pat>' begins with a '-')\n"
|
|
|
|
" -r --replace <replacement> replace the input pattern with the given replacement\n"
|
|
|
|
" -m --mode <mode> set the behavior mode (defult: find-all)\n"
|
|
|
|
" -g --grammar <grammar file> use the specified file as a grammar\n");
|
2020-09-07 23:05:38 -07:00
|
|
|
|
2020-12-12 16:31:53 -08:00
|
|
|
static print_options_t print_options = 0;
|
|
|
|
|
2021-01-12 22:33:28 -08:00
|
|
|
__attribute__((nonnull))
|
|
|
|
static char *getflag(const char *flag, char *argv[], int *i);
|
|
|
|
__attribute__((nonnull(3)))
|
|
|
|
static int process_file(def_t *defs, const char *filename, vm_op_t *pattern, unsigned int flags);
|
|
|
|
|
2021-01-12 22:22:38 -08:00
|
|
|
//
|
|
|
|
// Return a pointer to the value part of a flag, if present, otherwise NULL.
|
|
|
|
// This works for --foo=value or --foo value
|
|
|
|
//
|
2020-09-11 02:55:15 -07:00
|
|
|
static char *getflag(const char *flag, char *argv[], int *i)
|
|
|
|
{
|
|
|
|
size_t n = strlen(flag);
|
2020-09-14 12:39:31 -07:00
|
|
|
check(argv[*i], "Attempt to get flag from NULL argument");
|
2020-09-11 02:55:15 -07:00
|
|
|
if (strncmp(argv[*i], flag, n) == 0) {
|
|
|
|
if (argv[*i][n] == '=') {
|
|
|
|
return &argv[*i][n+1];
|
|
|
|
} else if (argv[*i][n] == '\0') {
|
2020-09-14 12:39:31 -07:00
|
|
|
check(argv[*i+1], "Expected argument after '%s'\n\n%s", flag, usage);
|
2020-09-11 02:55:15 -07:00
|
|
|
++(*i);
|
|
|
|
return argv[*i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2020-09-13 15:55:09 -07:00
|
|
|
|
2021-01-12 22:22:38 -08:00
|
|
|
//
|
|
|
|
// For a given filename, open the file and attempt to match the given pattern
|
|
|
|
// against it, printing any results according to the flags.
|
|
|
|
//
|
|
|
|
static int process_file(def_t *defs, const char *filename, vm_op_t *pattern, unsigned int flags)
|
2020-09-13 15:55:09 -07:00
|
|
|
{
|
2020-12-12 16:31:53 -08:00
|
|
|
static int printed_matches = 0;
|
2021-01-12 18:35:41 -08:00
|
|
|
int success = 0;
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *f = load_file(NULL, filename);
|
2020-09-16 21:32:08 -07:00
|
|
|
check(f, "Could not open file: %s", filename);
|
2020-12-30 19:42:47 -08:00
|
|
|
if (flags & BP_INPLACE) // Need to do this before matching
|
2020-12-27 19:48:52 -08:00
|
|
|
intern_file(f);
|
2021-01-10 01:45:40 -08:00
|
|
|
match_t *m = match(defs, f, f->contents, pattern, flags);
|
2021-01-12 22:22:38 -08:00
|
|
|
if (m && print_errors(f, m, print_options) > 0)
|
2021-01-13 19:01:49 -08:00
|
|
|
exit(1);
|
2021-01-13 18:56:22 -08:00
|
|
|
|
2020-09-13 15:55:09 -07:00
|
|
|
if (m != NULL && m->end > m->start + 1) {
|
2021-01-12 18:35:41 -08:00
|
|
|
success = 1;
|
2020-12-12 16:31:53 -08:00
|
|
|
++printed_matches;
|
|
|
|
|
2020-12-30 19:42:47 -08:00
|
|
|
if (flags & BP_EXPLAIN) {
|
2020-12-14 21:55:36 -08:00
|
|
|
if (filename)
|
2020-12-14 21:43:06 -08:00
|
|
|
printf("\033[1;4m%s\033[0m\n", filename);
|
2020-12-14 21:55:36 -08:00
|
|
|
visualize_match(m);
|
2020-12-30 19:42:47 -08:00
|
|
|
} else if (flags & BP_LISTFILES) {
|
2020-12-17 16:23:29 -08:00
|
|
|
printf("%s\n", filename);
|
2020-12-30 19:42:47 -08:00
|
|
|
} else if (flags & BP_JSON) {
|
2020-12-12 16:31:53 -08:00
|
|
|
if (printed_matches > 1)
|
2020-12-17 16:23:29 -08:00
|
|
|
printf(",\n");
|
2020-12-14 21:58:38 -08:00
|
|
|
printf("{\"filename\":\"%s\",", filename ? filename : "-");
|
|
|
|
printf("\"tree\":{\"rule\":\"text\",\"start\":%d,\"end\":%ld,\"children\":[",
|
2020-12-12 16:31:53 -08:00
|
|
|
0, f->end - f->contents);
|
2020-12-30 19:42:47 -08:00
|
|
|
json_match(f->contents, m, (flags & BP_VERBOSE) ? 1 : 0);
|
2020-12-12 16:31:53 -08:00
|
|
|
printf("]}}\n");
|
2020-12-30 19:42:47 -08:00
|
|
|
} else if (flags & BP_INPLACE && filename) {
|
2020-12-27 19:48:52 -08:00
|
|
|
FILE *out = fopen(filename, "w");
|
|
|
|
print_match(out, f, m, 0);
|
|
|
|
fclose(out);
|
2020-12-30 16:24:59 -08:00
|
|
|
printf("%s\n", filename);
|
2020-12-12 16:31:53 -08:00
|
|
|
} else {
|
|
|
|
if (printed_matches > 1)
|
|
|
|
fputc('\n', stdout);
|
|
|
|
if (filename) {
|
|
|
|
if (print_options & PRINT_COLOR)
|
2020-12-14 21:43:06 -08:00
|
|
|
printf("\033[1;4;33m%s\033[0m\n", filename);
|
2020-12-12 16:31:53 -08:00
|
|
|
else
|
|
|
|
printf("%s:\n", filename);
|
|
|
|
}
|
2020-12-30 16:21:49 -08:00
|
|
|
print_match(stdout, f, m,
|
|
|
|
filename ? print_options : print_options & (print_options_t)~PRINT_LINE_NUMBERS);
|
2020-12-12 16:31:53 -08:00
|
|
|
}
|
2020-09-13 15:55:09 -07:00
|
|
|
}
|
2021-01-12 18:35:41 -08:00
|
|
|
|
|
|
|
if (m != NULL)
|
|
|
|
destroy_match(&m);
|
2021-01-13 01:48:36 -08:00
|
|
|
|
2021-01-12 18:35:41 -08:00
|
|
|
destroy_file(&f);
|
|
|
|
|
|
|
|
return success;
|
2020-09-13 15:55:09 -07:00
|
|
|
}
|
|
|
|
|
2020-09-11 02:55:15 -07:00
|
|
|
#define FLAG(f) (flag=getflag((f), argv, &i))
|
2020-09-09 22:29:09 -07:00
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2020-09-14 12:16:15 -07:00
|
|
|
unsigned int flags = 0;
|
2020-09-11 02:55:15 -07:00
|
|
|
char *flag = NULL;
|
2020-09-13 23:31:38 -07:00
|
|
|
char path[PATH_MAX] = {0};
|
2020-09-11 02:55:15 -07:00
|
|
|
const char *rule = "find-all";
|
2020-09-09 22:29:09 -07:00
|
|
|
|
2021-01-10 01:45:40 -08:00
|
|
|
def_t *defs = NULL;
|
2020-09-11 01:28:06 -07:00
|
|
|
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *loaded_files = NULL;
|
|
|
|
|
2020-09-13 23:31:38 -07:00
|
|
|
// Load builtins:
|
2021-01-13 18:56:22 -08:00
|
|
|
if (access("/etc/xdg/bp/builtins.bp", R_OK) != -1) {
|
|
|
|
file_t *f = load_file(&loaded_files, "/etc/xdg/bp/builtins.bp");
|
|
|
|
defs = load_grammar(defs, f);
|
|
|
|
}
|
2020-12-12 16:31:53 -08:00
|
|
|
sprintf(path, "%s/.config/bp/builtins.bp", getenv("HOME"));
|
2021-01-13 18:56:22 -08:00
|
|
|
if (access(path, R_OK) != -1) {
|
|
|
|
file_t *f = load_file(&loaded_files, path);
|
|
|
|
defs = load_grammar(defs, f);
|
|
|
|
}
|
2020-09-12 15:11:44 -07:00
|
|
|
|
2020-09-11 02:55:15 -07:00
|
|
|
int i, npatterns = 0;
|
2020-09-14 12:39:31 -07:00
|
|
|
check(argc > 1, "%s", usage);
|
2020-09-11 02:55:15 -07:00
|
|
|
for (i = 1; i < argc; i++) {
|
|
|
|
if (streq(argv[i], "--")) {
|
|
|
|
++i;
|
|
|
|
break;
|
2020-12-14 22:32:47 -08:00
|
|
|
} else if (streq(argv[i], "--help")) {
|
|
|
|
flag_help:
|
2020-09-09 22:29:09 -07:00
|
|
|
printf("%s\n", usage);
|
|
|
|
return 0;
|
2020-12-14 22:32:47 -08:00
|
|
|
} else if (streq(argv[i], "--verbose")) {
|
2020-12-30 19:42:47 -08:00
|
|
|
flags |= BP_VERBOSE;
|
2020-12-14 22:32:47 -08:00
|
|
|
} else if (streq(argv[i], "--explain")) {
|
2020-12-30 19:42:47 -08:00
|
|
|
flags |= BP_EXPLAIN;
|
2020-12-14 22:32:47 -08:00
|
|
|
} else if (streq(argv[i], "--json")) {
|
2020-12-30 19:42:47 -08:00
|
|
|
flags |= BP_JSON;
|
2020-12-27 19:48:52 -08:00
|
|
|
} else if (streq(argv[i], "--inplace")) {
|
2020-12-30 19:42:47 -08:00
|
|
|
flags |= BP_INPLACE;
|
2020-12-14 22:32:47 -08:00
|
|
|
} else if (streq(argv[i], "--ignore-case")) {
|
2020-12-30 19:42:47 -08:00
|
|
|
flags |= BP_IGNORECASE;
|
2020-12-17 16:23:29 -08:00
|
|
|
} else if (streq(argv[i], "--list-files")) {
|
2020-12-30 19:42:47 -08:00
|
|
|
flags |= BP_LISTFILES;
|
2020-09-11 02:55:15 -07:00
|
|
|
} else if (FLAG("--replace") || FLAG("-r")) {
|
2021-01-08 00:57:46 -08:00
|
|
|
// TODO: spoof file as sprintf("pattern => '%s'", flag)
|
|
|
|
// except that would require handling edge cases like quotation marks etc.
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *pat_file = spoof_file(&loaded_files, "<pattern>", "pattern");
|
2020-12-30 19:42:47 -08:00
|
|
|
vm_op_t *patref = bp_pattern(pat_file, pat_file->contents);
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *replace_file = spoof_file(&loaded_files, "<replace argument>", flag);
|
2020-12-30 19:42:47 -08:00
|
|
|
vm_op_t *rep = bp_replacement(replace_file, patref, replace_file->contents);
|
2020-09-28 22:02:00 -07:00
|
|
|
check(rep, "Replacement failed to compile: %s", flag);
|
2021-01-13 18:56:22 -08:00
|
|
|
defs = with_def(defs, replace_file, strlen("replacement"), "replacement", rep);
|
2020-09-11 02:55:15 -07:00
|
|
|
rule = "replace-all";
|
|
|
|
} else if (FLAG("--grammar") || FLAG("-g")) {
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *f = load_file(&loaded_files, flag);
|
2020-09-16 19:35:43 -07:00
|
|
|
if (f == NULL) {
|
2020-12-12 16:31:53 -08:00
|
|
|
sprintf(path, "%s/.config/bp/%s.bp", getenv("HOME"), flag);
|
2021-01-13 18:56:22 -08:00
|
|
|
f = load_file(&loaded_files, path);
|
2020-09-16 19:35:43 -07:00
|
|
|
}
|
|
|
|
if (f == NULL) {
|
2020-12-12 16:31:53 -08:00
|
|
|
sprintf(path, "/etc/xdg/bp/%s.bp", flag);
|
2021-01-13 18:56:22 -08:00
|
|
|
f = load_file(&loaded_files, path);
|
2020-09-11 02:55:15 -07:00
|
|
|
}
|
2020-09-16 19:35:43 -07:00
|
|
|
check(f != NULL, "Couldn't find grammar: %s", flag);
|
2021-01-10 01:45:40 -08:00
|
|
|
defs = load_grammar(defs, f); // Keep in memory for debug output
|
2020-09-11 02:55:15 -07:00
|
|
|
} else if (FLAG("--define") || FLAG("-d")) {
|
|
|
|
char *def = flag;
|
2020-09-16 22:39:33 -07:00
|
|
|
char *eq = strchr(def, ':');
|
|
|
|
check(eq, "Rule definitions must include an ':'\n\n%s", usage);
|
2020-09-10 22:50:49 -07:00
|
|
|
*eq = '\0';
|
2020-09-11 01:28:06 -07:00
|
|
|
char *src = ++eq;
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *def_file = spoof_file(&loaded_files, def, src);
|
2020-12-30 19:42:47 -08:00
|
|
|
vm_op_t *pat = bp_pattern(def_file, def_file->contents);
|
2020-09-28 22:02:00 -07:00
|
|
|
check(pat, "Failed to compile pattern: %s", flag);
|
2021-01-13 18:56:22 -08:00
|
|
|
defs = with_def(defs, def_file, strlen(def), def, pat);
|
2020-09-13 20:33:11 -07:00
|
|
|
} else if (FLAG("--define-string") || FLAG("-D")) {
|
|
|
|
char *def = flag;
|
2020-09-16 22:39:33 -07:00
|
|
|
char *eq = strchr(def, ':');
|
|
|
|
check(eq, "Rule definitions must include an ':'\n\n%s", usage);
|
2020-09-13 20:33:11 -07:00
|
|
|
*eq = '\0';
|
|
|
|
char *src = ++eq;
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *def_file = spoof_file(&loaded_files, def, src);
|
2020-12-30 19:42:47 -08:00
|
|
|
vm_op_t *pat = bp_stringpattern(def_file, def_file->contents);
|
2021-01-10 00:39:34 -08:00
|
|
|
check(pat, "Failed to compile pattern: %s", src);
|
2021-01-13 18:56:22 -08:00
|
|
|
defs = with_def(defs, def_file, strlen(def), def, pat);
|
2020-09-13 23:31:38 -07:00
|
|
|
} else if (FLAG("--pattern") || FLAG("-p")) {
|
2020-09-12 18:20:13 -07:00
|
|
|
check(npatterns == 0, "Cannot define multiple patterns");
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *arg_file = spoof_file(&loaded_files, "<pattern argument>", flag);
|
2020-12-30 19:42:47 -08:00
|
|
|
vm_op_t *p = bp_pattern(arg_file, arg_file->contents);
|
2020-09-28 22:02:00 -07:00
|
|
|
check(p, "Pattern failed to compile: %s", flag);
|
2021-01-13 18:56:22 -08:00
|
|
|
defs = with_def(defs, arg_file, strlen("pattern"), "pattern", p);
|
2020-09-12 20:05:55 -07:00
|
|
|
++npatterns;
|
2020-09-13 23:31:38 -07:00
|
|
|
} else if (FLAG("--pattern-string") || FLAG("-P")) {
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *arg_file = spoof_file(&loaded_files, "<pattern argument>", flag);
|
2020-12-30 19:42:47 -08:00
|
|
|
vm_op_t *p = bp_stringpattern(arg_file, arg_file->contents);
|
2020-09-28 22:02:00 -07:00
|
|
|
check(p, "Pattern failed to compile: %s", flag);
|
2021-01-13 18:56:22 -08:00
|
|
|
defs = with_def(defs, arg_file, strlen("pattern"), "pattern", p);
|
2020-09-12 18:20:13 -07:00
|
|
|
++npatterns;
|
2020-09-13 00:37:17 -07:00
|
|
|
} else if (FLAG("--mode") || FLAG("-m")) {
|
|
|
|
rule = flag;
|
2020-12-14 22:32:47 -08:00
|
|
|
} else if (argv[i][0] == '-' && argv[i][1] && argv[i][1] != '-') { // single-char flags
|
|
|
|
for (char *c = &argv[i][1]; *c; ++c) {
|
|
|
|
switch (*c) {
|
2020-12-17 16:23:29 -08:00
|
|
|
case 'h': goto flag_help; // -h
|
2020-12-30 19:42:47 -08:00
|
|
|
case 'v': flags |= BP_VERBOSE; break; // -v
|
|
|
|
case 'e': flags |= BP_EXPLAIN; break; // -e
|
|
|
|
case 'j': flags |= BP_JSON; break; // -j
|
|
|
|
case 'I': flags |= BP_INPLACE; break; // -I
|
|
|
|
case 'i': flags |= BP_IGNORECASE; break; // -i
|
|
|
|
case 'l': flags |= BP_LISTFILES; break; // -l
|
2020-12-14 22:32:47 -08:00
|
|
|
default:
|
|
|
|
printf("Unrecognized flag: -%c\n\n%s\n", *c, usage);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2020-09-11 02:55:15 -07:00
|
|
|
} else if (argv[i][0] != '-') {
|
|
|
|
if (npatterns > 0) break;
|
2021-01-08 00:57:46 -08:00
|
|
|
// TODO: spoof file with quotation marks for better debugging
|
2021-01-13 18:56:22 -08:00
|
|
|
file_t *arg_file = spoof_file(&loaded_files, "<pattern argument>", argv[i]);
|
2020-12-30 19:42:47 -08:00
|
|
|
vm_op_t *p = bp_stringpattern(arg_file, arg_file->contents);
|
2020-09-28 22:02:00 -07:00
|
|
|
check(p, "Pattern failed to compile: %s", argv[i]);
|
2021-01-13 18:56:22 -08:00
|
|
|
defs = with_def(defs, arg_file, strlen("pattern"), "pattern", p);
|
2020-09-11 02:55:15 -07:00
|
|
|
++npatterns;
|
2020-09-12 20:05:55 -07:00
|
|
|
} else {
|
2020-09-14 12:39:31 -07:00
|
|
|
printf("Unrecognized flag: %s\n\n%s\n", argv[i], usage);
|
2020-09-12 20:05:55 -07:00
|
|
|
return 1;
|
2020-09-09 22:29:09 -07:00
|
|
|
}
|
|
|
|
}
|
2020-09-07 23:05:38 -07:00
|
|
|
|
2020-12-30 19:42:47 -08:00
|
|
|
if (((flags & BP_JSON) != 0) + ((flags & BP_EXPLAIN) != 0) + ((flags & BP_LISTFILES) != 0) > 1) {
|
2020-12-17 16:23:29 -08:00
|
|
|
printf("Please choose no more than one of the flags: -j/--json, -e/--explain, and -l/--list-files.\n"
|
|
|
|
"They are mutually contradictory.\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-09-16 20:38:58 -07:00
|
|
|
if (isatty(STDOUT_FILENO)) {
|
2020-12-12 16:31:53 -08:00
|
|
|
print_options |= PRINT_COLOR | PRINT_LINE_NUMBERS;
|
2020-09-16 20:38:58 -07:00
|
|
|
}
|
|
|
|
|
2021-01-13 18:56:22 -08:00
|
|
|
def_t *pattern_def = lookup(defs, rule);
|
|
|
|
check(pattern_def != NULL, "No such rule: '%s'", rule);
|
|
|
|
vm_op_t *pattern = pattern_def->op;
|
2020-09-09 22:29:09 -07:00
|
|
|
|
2021-01-12 18:35:41 -08:00
|
|
|
int found = 0;
|
2020-12-30 19:42:47 -08:00
|
|
|
if (flags & BP_JSON) printf("[");
|
2020-09-13 15:55:09 -07:00
|
|
|
if (i < argc) {
|
|
|
|
// Files pass in as command line args:
|
|
|
|
for (int nfiles = 0; i < argc; nfiles++, i++) {
|
2021-01-12 22:22:38 -08:00
|
|
|
found += process_file(defs, argv[i], pattern, flags);
|
2020-09-11 02:55:15 -07:00
|
|
|
}
|
2020-09-13 15:55:09 -07:00
|
|
|
} else if (isatty(STDIN_FILENO)) {
|
|
|
|
// No files, no piped in input, so use * **/*:
|
|
|
|
glob_t globbuf;
|
|
|
|
glob("*", 0, NULL, &globbuf);
|
|
|
|
glob("**/*", GLOB_APPEND, NULL, &globbuf);
|
|
|
|
for (size_t i = 0; i < globbuf.gl_pathc; i++) {
|
2021-01-12 22:22:38 -08:00
|
|
|
found += process_file(defs, globbuf.gl_pathv[i], pattern, flags);
|
2020-09-11 02:55:15 -07:00
|
|
|
}
|
2020-09-13 15:55:09 -07:00
|
|
|
globfree(&globbuf);
|
|
|
|
} else {
|
|
|
|
// Piped in input:
|
2021-01-12 22:22:38 -08:00
|
|
|
found += process_file(defs, NULL, pattern, flags);
|
2020-09-07 23:05:38 -07:00
|
|
|
}
|
2020-12-30 19:42:47 -08:00
|
|
|
if (flags & BP_JSON) printf("]\n");
|
2020-09-07 23:05:38 -07:00
|
|
|
|
2021-01-13 01:48:36 -08:00
|
|
|
free_defs(&defs, NULL);
|
2021-01-13 18:56:22 -08:00
|
|
|
while (loaded_files) {
|
|
|
|
file_t *next = loaded_files->next;
|
|
|
|
destroy_file(&loaded_files);
|
|
|
|
loaded_files = next;
|
|
|
|
}
|
2021-01-13 01:48:36 -08:00
|
|
|
|
2021-01-12 18:35:41 -08:00
|
|
|
return (found > 0) ? 0 : 1;
|
2020-09-07 23:05:38 -07:00
|
|
|
}
|
2020-09-07 23:34:41 -07:00
|
|
|
|
2020-09-11 01:38:44 -07:00
|
|
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|