More static analyzer cleanup, including switching to use bools where
appropriate and EXIT_SUCESS/EXIT_FAILURE
This commit is contained in:
parent
7f0c3804dc
commit
eece8c8556
2
Makefile
2
Makefile
@ -28,7 +28,7 @@ leaktest:
|
|||||||
valgrind --leak-check=full ./bp -l -g grammars/bp.bp -p Grammar grammars/bp.bp
|
valgrind --leak-check=full ./bp -l -g grammars/bp.bp -p Grammar grammars/bp.bp
|
||||||
|
|
||||||
splint:
|
splint:
|
||||||
splint +posixlib $(CFILES) bp.c
|
splint -posix-lib $(CFILES) bp.c
|
||||||
|
|
||||||
install: $(NAME)
|
install: $(NAME)
|
||||||
mkdir -p -m 755 "$(PREFIX)/share/man/man1" "$(PREFIX)/bin" "$(SYSCONFDIR)/xdg/$(NAME)"
|
mkdir -p -m 755 "$(PREFIX)/share/man/man1" "$(PREFIX)/bin" "$(SYSCONFDIR)/xdg/$(NAME)"
|
||||||
|
94
bp.c
94
bp.c
@ -8,6 +8,7 @@
|
|||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -50,10 +51,11 @@ static const char *usage = (
|
|||||||
#define USE_DEFAULT_CONTEXT -2
|
#define USE_DEFAULT_CONTEXT -2
|
||||||
#define ALL_CONTEXT -1
|
#define ALL_CONTEXT -1
|
||||||
static int context_lines = USE_DEFAULT_CONTEXT;
|
static int context_lines = USE_DEFAULT_CONTEXT;
|
||||||
static unsigned int print_color = 0;
|
static bool print_color = false;
|
||||||
static unsigned int print_line_numbers = 0;
|
static bool print_line_numbers = false;
|
||||||
static unsigned int ignorecase = 0;
|
static bool ignorecase = false;
|
||||||
static unsigned int verbose = 0;
|
static bool verbose = false;
|
||||||
|
static bool git_mode = false;
|
||||||
typedef enum { CONFIRM_ASK, CONFIRM_ALL, CONFIRM_NONE } confirm_t;
|
typedef enum { CONFIRM_ASK, CONFIRM_ALL, CONFIRM_NONE } confirm_t;
|
||||||
static confirm_t confirm = CONFIRM_ALL;
|
static confirm_t confirm = CONFIRM_ALL;
|
||||||
static enum {
|
static enum {
|
||||||
@ -195,7 +197,7 @@ static void cleanup(void)
|
|||||||
static void sig_handler(int sig)
|
static void sig_handler(int sig)
|
||||||
{
|
{
|
||||||
cleanup();
|
cleanup();
|
||||||
if (kill(0, sig)) _exit(1);
|
if (kill(0, sig)) _exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -276,7 +278,7 @@ static int inplace_modify_file(def_t *defs, file_t *f, pat_t *pattern)
|
|||||||
++matches;
|
++matches;
|
||||||
printer_t err_pr = {.file = f, .context_lines = 1, .use_color = 1, .print_line_numbers = 1};
|
printer_t err_pr = {.file = f, .context_lines = 1, .use_color = 1, .print_line_numbers = 1};
|
||||||
if (print_errors(&err_pr, m) > 0)
|
if (print_errors(&err_pr, m) > 0)
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
// Lazy-open file for writing upon first match:
|
// Lazy-open file for writing upon first match:
|
||||||
if (inplace_file == NULL) {
|
if (inplace_file == NULL) {
|
||||||
check(snprintf(tmp_filename, PATH_MAX, "%s.tmp.XXXXXX", f->filename) <= PATH_MAX,
|
check(snprintf(tmp_filename, PATH_MAX, "%s.tmp.XXXXXX", f->filename) <= PATH_MAX,
|
||||||
@ -328,7 +330,7 @@ static int print_matches(def_t *defs, file_t *f, pat_t *pattern)
|
|||||||
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, ignorecase)); ) {
|
for (match_t *m = NULL; (m = next_match(defs, f, m, pattern, ignorecase)); ) {
|
||||||
printer_t err_pr = {.file = f, .context_lines = 1, .use_color = 1, .print_line_numbers = 1};
|
printer_t err_pr = {.file = f, .context_lines = 1, .use_color = 1, .print_line_numbers = 1};
|
||||||
if (print_errors(&err_pr, m) > 0)
|
if (print_errors(&err_pr, m) > 0)
|
||||||
exit(1);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (++matches == 1) {
|
if (++matches == 1) {
|
||||||
if (printed_filenames++ > 0) printf("\n");
|
if (printed_filenames++ > 0) printf("\n");
|
||||||
@ -415,8 +417,8 @@ static int process_dir(def_t *defs, const char *dirname, pat_t *pattern)
|
|||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FLAG(f) (flag=getflag((f), argv, &i))
|
#define FLAG(f) (flag=getflag((f), argv, &argi))
|
||||||
#define BOOLFLAG(f) (boolflag((f), argv, &i))
|
#define BOOLFLAG(f) (boolflag((f), argv, &argi))
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -432,16 +434,16 @@ int main(int argc, char *argv[])
|
|||||||
file_t *local_file = load_filef(&loaded_files, "%s/.config/"BP_NAME"/builtins.bp", getenv("HOME"));
|
file_t *local_file = load_filef(&loaded_files, "%s/.config/"BP_NAME"/builtins.bp", getenv("HOME"));
|
||||||
if (local_file) defs = load_grammar(defs, local_file);
|
if (local_file) defs = load_grammar(defs, local_file);
|
||||||
|
|
||||||
int i, git = 0;
|
int argi;
|
||||||
for (i = 1; i < argc; i++) {
|
for (argi = 1; argi < argc; argi++) {
|
||||||
if (streq(argv[i], "--")) {
|
if (streq(argv[argi], "--")) {
|
||||||
++i;
|
++argi;
|
||||||
break;
|
break;
|
||||||
} else if (BOOLFLAG("-h") || BOOLFLAG("--help")) {
|
} else if (BOOLFLAG("-h") || BOOLFLAG("--help")) {
|
||||||
printf("%s\n", usage);
|
printf("%s\n", usage);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (BOOLFLAG("-v") || BOOLFLAG("--verbose")) {
|
} else if (BOOLFLAG("-v") || BOOLFLAG("--verbose")) {
|
||||||
verbose = 1;
|
verbose = true;
|
||||||
} else if (BOOLFLAG("-e") || BOOLFLAG("--explain")) {
|
} else if (BOOLFLAG("-e") || BOOLFLAG("--explain")) {
|
||||||
mode = MODE_EXPLAIN;
|
mode = MODE_EXPLAIN;
|
||||||
} else if (BOOLFLAG("-j") || BOOLFLAG("--json")) {
|
} else if (BOOLFLAG("-j") || BOOLFLAG("--json")) {
|
||||||
@ -451,9 +453,9 @@ int main(int argc, char *argv[])
|
|||||||
} else if (BOOLFLAG("-C") || BOOLFLAG("--confirm")) {
|
} else if (BOOLFLAG("-C") || BOOLFLAG("--confirm")) {
|
||||||
confirm = CONFIRM_ASK;
|
confirm = CONFIRM_ASK;
|
||||||
} else if (BOOLFLAG("-G") || BOOLFLAG("--git")) {
|
} else if (BOOLFLAG("-G") || BOOLFLAG("--git")) {
|
||||||
git = 1;
|
git_mode = true;
|
||||||
} else if (BOOLFLAG("-i") || BOOLFLAG("--ignore-case")) {
|
} else if (BOOLFLAG("-i") || BOOLFLAG("--ignore-case")) {
|
||||||
ignorecase = 1;
|
ignorecase = true;
|
||||||
} else if (BOOLFLAG("-l") || BOOLFLAG("--list-files")) {
|
} else if (BOOLFLAG("-l") || BOOLFLAG("--list-files")) {
|
||||||
mode = MODE_LISTFILES;
|
mode = MODE_LISTFILES;
|
||||||
} else if (FLAG("-r") || FLAG("--replace")) {
|
} else if (FLAG("-r") || FLAG("--replace")) {
|
||||||
@ -498,17 +500,17 @@ int main(int argc, char *argv[])
|
|||||||
context_lines = 0;
|
context_lines = 0;
|
||||||
else
|
else
|
||||||
context_lines = (int)strtol(flag, NULL, 10);
|
context_lines = (int)strtol(flag, NULL, 10);
|
||||||
} else if (argv[i][0] == '-' && argv[i][1] && argv[i][1] != '-') { // single-char flags
|
} else if (argv[argi][0] == '-' && argv[argi][1] && argv[argi][1] != '-') { // single-char flags
|
||||||
printf("Unrecognized flag: -%c\n\n%s\n", argv[i][1], usage);
|
printf("Unrecognized flag: -%c\n\n%s\n", argv[argi][1], usage);
|
||||||
return 1;
|
return 1;
|
||||||
} else if (argv[i][0] != '-') {
|
} else if (argv[argi][0] != '-') {
|
||||||
if (pattern != NULL) break;
|
if (pattern != NULL) break;
|
||||||
file_t *arg_file = spoof_file(&loaded_files, "<pattern argument>", argv[i]);
|
file_t *arg_file = spoof_file(&loaded_files, "<pattern argument>", argv[argi]);
|
||||||
pat_t *p = bp_stringpattern(arg_file, arg_file->contents);
|
pat_t *p = bp_stringpattern(arg_file, arg_file->contents);
|
||||||
check(p, "Pattern failed to compile: %s", argv[i]);
|
check(p, "Pattern failed to compile: %s", argv[argi]);
|
||||||
pattern = chain_together(arg_file, pattern, p);
|
pattern = chain_together(arg_file, pattern, p);
|
||||||
} else {
|
} else {
|
||||||
printf("Unrecognized flag: %s\n\n%s\n", argv[i], usage);
|
printf("Unrecognized flag: %s\n\n%s\n", argv[argi], usage);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -517,8 +519,8 @@ int main(int argc, char *argv[])
|
|||||||
if (context_lines < 0 && context_lines != ALL_CONTEXT) context_lines = 0;
|
if (context_lines < 0 && context_lines != ALL_CONTEXT) context_lines = 0;
|
||||||
|
|
||||||
if (isatty(STDOUT_FILENO)) {
|
if (isatty(STDOUT_FILENO)) {
|
||||||
print_color = 1;
|
print_color = true;
|
||||||
print_line_numbers = 1;
|
print_line_numbers = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If any of these signals triggers, and there is a temporary file in use,
|
// If any of these signals triggers, and there is a temporary file in use,
|
||||||
@ -526,10 +528,10 @@ int main(int argc, char *argv[])
|
|||||||
int signals[] = {SIGTERM, SIGINT, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGSEGV, SIGTSTP};
|
int signals[] = {SIGTERM, SIGINT, SIGXCPU, SIGXFSZ, SIGVTALRM, SIGPROF, SIGSEGV, SIGTSTP};
|
||||||
struct sigaction sa = {.sa_handler = &sig_handler, .sa_flags = (int)(SA_NODEFER | SA_RESETHAND)};
|
struct sigaction sa = {.sa_handler = &sig_handler, .sa_flags = (int)(SA_NODEFER | SA_RESETHAND)};
|
||||||
for (size_t i = 0; i < sizeof(signals)/sizeof(signals[0]); i++)
|
for (size_t i = 0; i < sizeof(signals)/sizeof(signals[0]); i++)
|
||||||
check(!sigaction(signals[i], &sa, NULL), "Failed to set signal handler");
|
check(sigaction(signals[i], &sa, NULL) == 0, "Failed to set signal handler");
|
||||||
|
|
||||||
// Handle exit() calls gracefully:
|
// Handle exit() calls gracefully:
|
||||||
check(!atexit(&cleanup), "Failed to set cleanup handler at exit");
|
check(atexit(&cleanup) == 0, "Failed to set cleanup handler at exit");
|
||||||
|
|
||||||
// User input/output is handled through /dev/tty so that normal unix pipes
|
// User input/output is handled through /dev/tty so that normal unix pipes
|
||||||
// can work properly while simultaneously asking for user input.
|
// can work properly while simultaneously asking for user input.
|
||||||
@ -564,32 +566,36 @@ int main(int argc, char *argv[])
|
|||||||
free(patstr);
|
free(patstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
check(pattern != NULL, "No pattern was given");
|
||||||
|
|
||||||
// To ensure recursion (and left recursion in particular) works properly,
|
// To ensure recursion (and left recursion in particular) works properly,
|
||||||
// we need to define a rule called "pattern" with the value of whatever
|
// we need to define a rule called "pattern" with the value of whatever
|
||||||
// pattern the args specified, and use `pattern` as the thing being matched.
|
// pattern the args specified, and use `pattern` as the thing being matched.
|
||||||
defs = with_def(defs, strlen("pattern"), "pattern", pattern); // TODO: this is a bit hacky
|
defs = with_def(defs, strlen("pattern"), "pattern", pattern);
|
||||||
pattern = bp_pattern(loaded_files, "pattern");
|
file_t *patref_file = spoof_file(&loaded_files, "<pattern ref>", "pattern");
|
||||||
|
pattern = bp_pattern(patref_file, patref_file->contents);
|
||||||
|
|
||||||
int found = 0;
|
int found = 0;
|
||||||
if (mode == MODE_JSON) printf("[");
|
if (mode == MODE_JSON) printf("[");
|
||||||
if (git) { // Get the list of files from `git --ls-files ...`
|
if (git_mode) { // Get the list of files from `git --ls-files ...`
|
||||||
int fds[2];
|
int fds[2];
|
||||||
check(pipe(fds) == 0, "Failed to create pipe");
|
check(pipe(fds) == 0, "Failed to create pipe");
|
||||||
pid_t child = fork();
|
pid_t child = fork();
|
||||||
check(child != -1, "Failed to fork");
|
check(child != -1, "Failed to fork");
|
||||||
if (child == 0) {
|
if (child == 0) {
|
||||||
char **git_args = calloc((size_t)(2+(argc-i)+1), sizeof(char*));
|
char **git_args = memcheck(calloc((size_t)(2+(argc-argi)+1), sizeof(char*)));
|
||||||
int g = 0;
|
int g = 0;
|
||||||
git_args[g++] = "git";
|
git_args[g++] = "git";
|
||||||
git_args[g++] = "ls-files";
|
git_args[g++] = "ls-files";
|
||||||
while (i < argc) git_args[g++] = argv[i++];
|
while (argi < argc) git_args[g++] = argv[argi++];
|
||||||
check(dup2(fds[STDOUT_FILENO], STDOUT_FILENO), "Failed to hook up pipe to stdout");
|
check(dup2(fds[STDOUT_FILENO], STDOUT_FILENO) == STDOUT_FILENO,
|
||||||
check(!close(fds[STDIN_FILENO]), "Failed to close read end of pipe");
|
"Failed to hook up pipe to stdout");
|
||||||
|
check(close(fds[STDIN_FILENO]) == 0, "Failed to close read end of pipe");
|
||||||
(void)execvp("git", git_args);
|
(void)execvp("git", git_args);
|
||||||
_exit(1);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
check(!close(fds[STDOUT_FILENO]), "Failed to close write end of pipe");
|
check(close(fds[STDOUT_FILENO]) == 0, "Failed to close write end of pipe");
|
||||||
char path[PATH_MAX+2] = {0}; // path + \n + \0
|
char path[PATH_MAX+2] = {'\0'}; // path + \n + \0
|
||||||
while (read(fds[STDIN_FILENO], path, PATH_MAX+1) > 0) { // Iterate over chunks
|
while (read(fds[STDIN_FILENO], path, PATH_MAX+1) > 0) { // Iterate over chunks
|
||||||
for (char *nl; (nl = strchr(path, '\n')); ) { // Iterate over nl-terminated lines
|
for (char *nl; (nl = strchr(path, '\n')); ) { // Iterate over nl-terminated lines
|
||||||
*nl = '\0';
|
*nl = '\0';
|
||||||
@ -597,19 +603,19 @@ int main(int argc, char *argv[])
|
|||||||
memmove(path, nl+1, sizeof(path)-(size_t)(nl+1-path));
|
memmove(path, nl+1, sizeof(path)-(size_t)(nl+1-path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
check(!close(fds[STDIN_FILENO]), "Failed to close read end of pipe");
|
check(close(fds[STDIN_FILENO]) == 0, "Failed to close read end of pipe");
|
||||||
int status;
|
int status;
|
||||||
while (waitpid(child, &status, 0) != child) continue;
|
while (waitpid(child, &status, 0) != child) continue;
|
||||||
check(WIFEXITED(status) && WEXITSTATUS(status) == 0,
|
check((WIFEXITED(status) == 1) && (WEXITSTATUS(status) == 0),
|
||||||
"`git --ls-files` failed. Do you have git installed?");
|
"`git --ls-files` failed. Do you have git installed?");
|
||||||
} else if (i < argc) {
|
} else if (argi < argc) {
|
||||||
// Files pass in as command line args:
|
// Files pass in as command line args:
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
for (int nfiles = 0; i < argc; nfiles++, i++) {
|
for (int nfiles = 0; argi < argc; nfiles++, argi++) {
|
||||||
if (stat(argv[i], &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) // Symlinks are okay if manually specified
|
if (stat(argv[argi], &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) // Symlinks are okay if manually specified
|
||||||
found += process_dir(defs, argv[i], pattern);
|
found += process_dir(defs, argv[argi], pattern);
|
||||||
else
|
else
|
||||||
found += process_file(defs, argv[i], pattern);
|
found += process_file(defs, argv[argi], pattern);
|
||||||
}
|
}
|
||||||
} else if (isatty(STDIN_FILENO)) {
|
} else if (isatty(STDIN_FILENO)) {
|
||||||
// No files, no piped in input, so use files in current dir, recursively
|
// No files, no piped in input, so use files in current dir, recursively
|
||||||
@ -636,7 +642,7 @@ int main(int argc, char *argv[])
|
|||||||
free_all_matches();
|
free_all_matches();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return (found > 0) ? 0 : 1;
|
return (found > 0) ? EXIT_SUCCESS : EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
||||||
|
6
files.c
6
files.c
@ -93,7 +93,7 @@ file_t *load_file(file_t **files, const char *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
finished_loading:
|
finished_loading:
|
||||||
if (fd != STDIN_FILENO) check(!close(fd), "Failed to close file");
|
if (fd != STDIN_FILENO) check(close(fd) == 0, "Failed to close file");
|
||||||
f->end = &f->contents[length];
|
f->end = &f->contents[length];
|
||||||
populate_lines(f);
|
populate_lines(f);
|
||||||
if (files != NULL) {
|
if (files != NULL) {
|
||||||
@ -131,7 +131,7 @@ void intern_file(file_t *f)
|
|||||||
size_t size = (size_t)(f->end - f->contents);
|
size_t size = (size_t)(f->end - f->contents);
|
||||||
char *buf = xcalloc(sizeof(char), size + 1);
|
char *buf = xcalloc(sizeof(char), size + 1);
|
||||||
memcpy(buf, f->contents, size);
|
memcpy(buf, f->contents, size);
|
||||||
check(!munmap(f->contents, size),
|
check(munmap(f->contents, size) == 0,
|
||||||
"Failure to un-memory-map some memory");
|
"Failure to un-memory-map some memory");
|
||||||
f->contents = buf;
|
f->contents = buf;
|
||||||
f->end = buf + size;
|
f->end = buf + size;
|
||||||
@ -156,7 +156,7 @@ void destroy_file(file_t **f)
|
|||||||
|
|
||||||
if ((*f)->contents) {
|
if ((*f)->contents) {
|
||||||
if ((*f)->mmapped) {
|
if ((*f)->mmapped) {
|
||||||
check(!munmap((*f)->contents, (size_t)((*f)->end - (*f)->contents)),
|
check(munmap((*f)->contents, (size_t)((*f)->end - (*f)->contents)) == 0,
|
||||||
"Failure to un-memory-map some memory");
|
"Failure to un-memory-map some memory");
|
||||||
(*f)->contents = NULL;
|
(*f)->contents = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
2
files.h
2
files.h
@ -13,7 +13,7 @@ typedef struct file_s {
|
|||||||
const char *filename;
|
const char *filename;
|
||||||
char *contents, **lines, *end;
|
char *contents, **lines, *end;
|
||||||
size_t nlines;
|
size_t nlines;
|
||||||
/*@only@*/ struct allocated_pat_s *pats;
|
struct allocated_pat_s *pats;
|
||||||
unsigned int mmapped:1;
|
unsigned int mmapped:1;
|
||||||
} file_t;
|
} file_t;
|
||||||
|
|
||||||
|
8
json.c
8
json.c
@ -4,17 +4,17 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "json.h"
|
||||||
|
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
static int _json_match(const char *text, match_t *m, int comma, unsigned int verbose);
|
static int _json_match(const char *text, match_t *m, int comma, bool verbose);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Helper function for json_match().
|
// Helper function for json_match().
|
||||||
// `comma` is used to track whether a comma will need to be printed before the
|
// `comma` is used to track whether a comma will need to be printed before the
|
||||||
// next object or not.
|
// next object or not.
|
||||||
//
|
//
|
||||||
static int _json_match(const char *text, match_t *m, int comma, unsigned int verbose)
|
static int _json_match(const char *text, match_t *m, int comma, bool verbose)
|
||||||
{
|
{
|
||||||
if (!verbose) {
|
if (!verbose) {
|
||||||
if (m->pat->type != BP_REF) {
|
if (m->pat->type != BP_REF) {
|
||||||
@ -49,7 +49,7 @@ static int _json_match(const char *text, match_t *m, int comma, unsigned int ver
|
|||||||
//
|
//
|
||||||
// Print a match object as a JSON object.
|
// Print a match object as a JSON object.
|
||||||
//
|
//
|
||||||
void json_match(const char *text, match_t *m, unsigned int verbose)
|
void json_match(const char *text, match_t *m, bool verbose)
|
||||||
{
|
{
|
||||||
(void)_json_match(text, m, 0, verbose);
|
(void)_json_match(text, m, 0, verbose);
|
||||||
}
|
}
|
||||||
|
6
json.h
6
json.h
@ -4,8 +4,12 @@
|
|||||||
#ifndef JSON__H
|
#ifndef JSON__H
|
||||||
#define JSON__H
|
#define JSON__H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
void json_match(const char *text, match_t *m, unsigned int verbose);
|
void json_match(const char *text, match_t *m, bool verbose);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
// vim: ts=4 sw=0 et cino=L2,l1,(0,W4,m1
|
||||||
|
11
match.c
11
match.c
@ -33,17 +33,18 @@ static match_t *unused_matches = NULL;
|
|||||||
static match_t *in_use_matches = NULL;
|
static match_t *in_use_matches = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
__attribute__((returns_nonnull))
|
||||||
static match_t *new_match(void);
|
static match_t *new_match(void);
|
||||||
__attribute__((nonnull, pure))
|
__attribute__((nonnull, pure))
|
||||||
static inline const char *next_char(file_t *f, const char *str);
|
static inline const char *next_char(file_t *f, const char *str);
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
static const char *match_backref(const char *str, match_t *cap, unsigned int ignorecase);
|
static const char *match_backref(const char *str, match_t *cap, bool ignorecase);
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
static match_t *get_capture_by_num(match_t *m, int *n);
|
static match_t *get_capture_by_num(match_t *m, int *n);
|
||||||
__attribute__((nonnull, pure))
|
__attribute__((nonnull, pure))
|
||||||
static match_t *get_capture_by_name(match_t *m, const char *name);
|
static match_t *get_capture_by_name(match_t *m, const char *name);
|
||||||
__attribute__((hot, nonnull(2,3,4)))
|
__attribute__((hot, nonnull(2,3,4)))
|
||||||
static match_t *match(def_t *defs, file_t *f, const char *str, pat_t *pat, unsigned int flags);
|
static match_t *match(def_t *defs, file_t *f, const char *str, pat_t *pat, bool ignorecase);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Return the location of the next character or UTF8 codepoint.
|
// Return the location of the next character or UTF8 codepoint.
|
||||||
@ -69,7 +70,7 @@ static inline const char *next_char(file_t *f, const char *str)
|
|||||||
// Attempt to match text against a previously captured value.
|
// Attempt to match text against a previously captured value.
|
||||||
// Return the character position after the backref has matched, or NULL if no match has occurred.
|
// Return the character position after the backref has matched, or NULL if no match has occurred.
|
||||||
//
|
//
|
||||||
static const char *match_backref(const char *str, match_t *cap, unsigned int ignorecase)
|
static const char *match_backref(const char *str, match_t *cap, bool ignorecase)
|
||||||
{
|
{
|
||||||
if (cap->pat->type == BP_REPLACE) {
|
if (cap->pat->type == BP_REPLACE) {
|
||||||
const char *text = cap->pat->args.replace.text;
|
const char *text = cap->pat->args.replace.text;
|
||||||
@ -126,7 +127,7 @@ static const char *match_backref(const char *str, match_t *cap, unsigned int ign
|
|||||||
//
|
//
|
||||||
// Find the next match after prev (or the first match if prev is NULL)
|
// Find the next match after prev (or the first match if prev is NULL)
|
||||||
//
|
//
|
||||||
match_t *next_match(def_t *defs, file_t *f, match_t *prev, pat_t *pat, unsigned int ignorecase)
|
match_t *next_match(def_t *defs, file_t *f, match_t *prev, pat_t *pat, bool ignorecase)
|
||||||
{
|
{
|
||||||
const char *str;
|
const char *str;
|
||||||
if (prev) {
|
if (prev) {
|
||||||
@ -147,7 +148,7 @@ match_t *next_match(def_t *defs, file_t *f, match_t *prev, pat_t *pat, unsigned
|
|||||||
// match object, or NULL if no match is found.
|
// match object, or NULL if no match is found.
|
||||||
// The returned value should be free()'d to avoid memory leaking.
|
// The returned value should be free()'d to avoid memory leaking.
|
||||||
//
|
//
|
||||||
static match_t *match(def_t *defs, file_t *f, const char *str, pat_t *pat, unsigned int ignorecase)
|
static match_t *match(def_t *defs, file_t *f, const char *str, pat_t *pat, bool ignorecase)
|
||||||
{
|
{
|
||||||
switch (pat->type) {
|
switch (pat->type) {
|
||||||
case BP_LEFTRECURSION: {
|
case BP_LEFTRECURSION: {
|
||||||
|
3
match.h
3
match.h
@ -4,12 +4,13 @@
|
|||||||
#ifndef MATCH__H
|
#ifndef MATCH__H
|
||||||
#define MATCH__H
|
#define MATCH__H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
__attribute__((nonnull(2,4)))
|
__attribute__((nonnull(2,4)))
|
||||||
match_t *next_match(def_t *defs, file_t *f, match_t *prev, pat_t *pat, unsigned int flags);
|
match_t *next_match(def_t *defs, file_t *f, match_t *prev, pat_t *pat, bool ignorecase);
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
match_t *get_capture(match_t *m, const char **id);
|
match_t *get_capture(match_t *m, const char **id);
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
__attribute__((nonnull))
|
__attribute__((returns_nonnull, nonnull))
|
||||||
pat_t *new_pat(file_t *f, const char *start, enum pattype_e type);
|
pat_t *new_pat(file_t *f, const char *start, enum pattype_e type);
|
||||||
__attribute__((nonnull(1,2)))
|
__attribute__((nonnull(1,2)))
|
||||||
pat_t *bp_stringpattern(file_t *f, const char *str);
|
pat_t *bp_stringpattern(file_t *f, const char *str);
|
||||||
|
8
types.h
8
types.h
@ -81,7 +81,7 @@ typedef struct pat_s {
|
|||||||
//
|
//
|
||||||
// Pattern matching result object
|
// Pattern matching result object
|
||||||
//
|
//
|
||||||
typedef struct match_s {
|
typedef /*@refcounted@*/ struct match_s {
|
||||||
// Where the match starts and ends (end is after the last character)
|
// Where the match starts and ends (end is after the last character)
|
||||||
const char *start, *end;
|
const char *start, *end;
|
||||||
struct match_s *child, *nextsibling;
|
struct match_s *child, *nextsibling;
|
||||||
@ -91,7 +91,7 @@ typedef struct match_s {
|
|||||||
#ifdef DEBUG_HEAP
|
#ifdef DEBUG_HEAP
|
||||||
struct match_s **atme;
|
struct match_s **atme;
|
||||||
#endif
|
#endif
|
||||||
int refcount;
|
/*@refs@*/ int refcount;
|
||||||
// If skip_replacement is set to 1, that means the user wants to not print
|
// If skip_replacement is set to 1, that means the user wants to not print
|
||||||
// the replaced text when printing this match:
|
// the replaced text when printing this match:
|
||||||
// TODO: this is a bit hacky, there is probably a better way to go about
|
// TODO: this is a bit hacky, there is probably a better way to go about
|
||||||
@ -106,7 +106,7 @@ typedef struct def_s {
|
|||||||
size_t namelen;
|
size_t namelen;
|
||||||
const char *name;
|
const char *name;
|
||||||
pat_t *pat;
|
pat_t *pat;
|
||||||
/*@only@*/ struct def_s *next;
|
struct def_s *next;
|
||||||
} def_t;
|
} def_t;
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -114,7 +114,7 @@ typedef struct def_s {
|
|||||||
// file is freed.
|
// file is freed.
|
||||||
//
|
//
|
||||||
typedef struct allocated_pat_s {
|
typedef struct allocated_pat_s {
|
||||||
/*@only@*/ struct allocated_pat_s *next;
|
struct allocated_pat_s *next;
|
||||||
pat_t pat;
|
pat_t pat;
|
||||||
} allocated_pat_t;
|
} allocated_pat_t;
|
||||||
|
|
||||||
|
12
utils.c
12
utils.c
@ -50,27 +50,27 @@ const char *after_name(const char *str)
|
|||||||
//
|
//
|
||||||
// Check if a character is found and if so, move past it.
|
// Check if a character is found and if so, move past it.
|
||||||
//
|
//
|
||||||
int matchchar(const char **str, char c)
|
bool matchchar(const char **str, char c)
|
||||||
{
|
{
|
||||||
const char *next = after_spaces(*str);
|
const char *next = after_spaces(*str);
|
||||||
if (*next == c) {
|
if (*next == c) {
|
||||||
*str = &next[1];
|
*str = &next[1];
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check if a string is found and if so, move past it.
|
// Check if a string is found and if so, move past it.
|
||||||
//
|
//
|
||||||
int matchstr(const char **str, const char *target)
|
bool matchstr(const char **str, const char *target)
|
||||||
{
|
{
|
||||||
const char *next = after_spaces(*str);
|
const char *next = after_spaces(*str);
|
||||||
if (strncmp(next, target, strlen(target)) == 0) {
|
if (strncmp(next, target, strlen(target)) == 0) {
|
||||||
*str = &next[strlen(target)];
|
*str = &next[strlen(target)];
|
||||||
return 1;
|
return true;
|
||||||
}
|
}
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
8
utils.h
8
utils.h
@ -4,14 +4,16 @@
|
|||||||
#ifndef UTILS__H
|
#ifndef UTILS__H
|
||||||
#define UTILS__H
|
#define UTILS__H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "match.h"
|
#include "match.h"
|
||||||
|
|
||||||
#define streq(a, b) (strcmp(a, b) == 0)
|
#define streq(a, b) (strcmp(a, b) == 0)
|
||||||
#define check(cond, ...) do { if (!(cond)) { (void)fprintf(stderr, __VA_ARGS__); (void)fwrite("\n", 1, 1, stderr); exit(1); } } while(0)
|
#define check(cond, ...) do { if (!(cond)) { (void)fprintf(stderr, __VA_ARGS__); (void)fwrite("\n", 1, 1, stderr); exit(EXIT_FAILURE); } } while(0)
|
||||||
#define new(t) memcheck(calloc(1, sizeof(t)))
|
#define new(t) memcheck(calloc(1, sizeof(t)))
|
||||||
#define xcalloc(a,b) memcheck(calloc(a,b))
|
#define xcalloc(a,b) memcheck(calloc(a,b))
|
||||||
#define xrealloc(a,b) memcheck(realloc(a,b))
|
#define xrealloc(a,b) memcheck(realloc(a,b))
|
||||||
@ -23,9 +25,9 @@ const char *after_name(const char *str);
|
|||||||
__attribute__((pure, nonnull, returns_nonnull))
|
__attribute__((pure, nonnull, returns_nonnull))
|
||||||
const char *after_spaces(const char *str);
|
const char *after_spaces(const char *str);
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
int matchchar(const char **str, char c);
|
bool matchchar(const char **str, char c);
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
int matchstr(const char **str, const char *target);
|
bool matchstr(const char **str, const char *target);
|
||||||
__attribute__((nonnull))
|
__attribute__((nonnull))
|
||||||
size_t unescape_string(char *dest, const char *src, size_t bufsize);
|
size_t unescape_string(char *dest, const char *src, size_t bufsize);
|
||||||
__attribute__((returns_nonnull))
|
__attribute__((returns_nonnull))
|
||||||
|
Loading…
Reference in New Issue
Block a user