diff --git a/Makefile b/Makefile index 4f76894..9d7cdba 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ NAME=bp CC=cc PREFIX=/usr/local SYSCONFDIR=/etc -CFLAGS=-std=c99 -Werror -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -flto=auto +CFLAGS=-std=c99 -Werror -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -flto=auto -fvisibility=hidden CWARN=-Wall -Wextra -Wno-format # -Wpedantic -Wsign-conversion -Wtype-limits -Wunused-result -Wnull-dereference \ # -Waggregate-return -Walloc-zero -Walloca -Warith-conversion -Wcast-align -Wcast-align=strict \ diff --git a/files.c b/files.c index 54da573..afce285 100644 --- a/files.c +++ b/files.c @@ -42,7 +42,7 @@ static void populate_lines(file_t *f) // Read an entire file into memory, using a printf-style formatting string to // construct the filename. // -file_t *load_filef(file_t **files, const char *fmt, ...) +public file_t *load_filef(file_t **files, const char *fmt, ...) { char filename[PATH_MAX+1] = {'\0'}; va_list args; @@ -56,7 +56,7 @@ file_t *load_filef(file_t **files, const char *fmt, ...) // // Read an entire file into memory. // -file_t *load_file(file_t **files, const char *filename) +public file_t *load_file(file_t **files, const char *filename) { int fd = filename[0] == '\0' ? STDIN_FILENO : open(filename, O_RDONLY); if (fd < 0) { @@ -125,7 +125,7 @@ file_t *load_file(file_t **files, const char *filename) // // Set a file struct to represent a region of a different file. // -void slice_file(file_t *slice, file_t *src, const char *start, const char *end) +public void slice_file(file_t *slice, file_t *src, const char *start, const char *end) { memset(slice, 0, sizeof(file_t)); slice->filename = src->filename; @@ -138,7 +138,7 @@ void slice_file(file_t *slice, file_t *src, const char *start, const char *end) // // Create a virtual file from a string. // -file_t *spoof_file(file_t **files, const char *filename, const char *text, ssize_t _len) +public file_t *spoof_file(file_t **files, const char *filename, const char *text, ssize_t _len) { if (filename == NULL) filename = ""; file_t *f = new(file_t); @@ -160,7 +160,7 @@ file_t *spoof_file(file_t **files, const char *filename, const char *text, ssize // Free a file and all memory contained inside its members, then set the input // pointer to NULL. // -void destroy_file(file_t **at_f) +public void destroy_file(file_t **at_f) { file_t *f = (file_t*)*at_f; if (f->filename) @@ -184,7 +184,7 @@ void destroy_file(file_t **at_f) // // Given a pointer, determine which line number it points to. // -size_t get_line_number(file_t *f, const char *p) +public size_t get_line_number(file_t *f, const char *p) { if (f->nlines == 0) return 0; // Binary search: @@ -204,7 +204,7 @@ size_t get_line_number(file_t *f, const char *p) // // Given a pointer, determine which line column it points to. // -size_t get_line_column(file_t *f, const char *p) +public size_t get_line_column(file_t *f, const char *p) { size_t line_no = get_line_number(f, p); return 1 + (size_t)(p - f->lines[line_no]); @@ -213,7 +213,7 @@ size_t get_line_column(file_t *f, const char *p) // // Return a pointer to the line with the specified line number. // -const char *get_line(file_t *f, size_t line_number) +public const char *get_line(file_t *f, size_t line_number) { if (line_number == 0 || line_number > f->nlines) return NULL; return f->lines[line_number - 1]; diff --git a/json.c b/json.c index 445f81b..448dbe7 100644 --- a/json.c +++ b/json.c @@ -5,6 +5,7 @@ #include #include "json.h" +#include "utils.h" __attribute__((nonnull)) static int _json_match(const char *text, match_t *m, int comma, bool verbose); @@ -77,7 +78,7 @@ static int _json_match(const char *text, match_t *m, int comma, bool verbose) // // Print a match object as a JSON object. // -void json_match(const char *text, match_t *m, bool verbose) +public void json_match(const char *text, match_t *m, bool verbose) { (void)_json_match(text, m, 0, verbose); } diff --git a/match.c b/match.c index 20d485b..6336479 100644 --- a/match.c +++ b/match.c @@ -57,7 +57,7 @@ static void default_error_handler(char **msg) { static bp_errhand_t error_handler = default_error_handler; -bp_errhand_t bp_set_error_handler(bp_errhand_t new_handler) +public bp_errhand_t bp_set_error_handler(bp_errhand_t new_handler) { bp_errhand_t old_handler = error_handler; error_handler = new_handler; @@ -817,7 +817,7 @@ match_t *new_match(pat_t *pat, const char *start, const char *end, match_t *chil // If the given match is not currently a child member of another match (or // otherwise reserved) then put it back in the pool of unused match objects. // -void recycle_match(match_t **at_m) +public void recycle_match(match_t **at_m) { match_t *m = *at_m; if (m->children) { @@ -836,7 +836,7 @@ void recycle_match(match_t **at_m) // // Force all match objects into the pool of unused match objects. // -size_t recycle_all_matches(void) +public size_t recycle_all_matches(void) { size_t count = 0; for (match_t *m; (m = in_use_matches); ++count) { @@ -851,7 +851,7 @@ size_t recycle_all_matches(void) // // Free all match objects in memory. // -size_t free_all_matches(void) +public size_t free_all_matches(void) { size_t count = 0; recycle_all_matches(); @@ -866,7 +866,7 @@ size_t free_all_matches(void) // Iterate over matches. // Usage: for (match_t *m = NULL; next_match(&m, ...); ) {...} // -bool next_match(match_t **m, const char *start, const char *end, pat_t *pat, pat_t *defs, pat_t *skip, bool ignorecase) +public bool next_match(match_t **m, const char *start, const char *end, pat_t *pat, pat_t *defs, pat_t *skip, bool ignorecase) { const char *pos; if (*m) { @@ -937,7 +937,7 @@ static match_t *_get_numbered_capture(match_t *m, int *n) // // Get a specific numbered pattern capture. // -match_t *get_numbered_capture(match_t *m, int n) +public match_t *get_numbered_capture(match_t *m, int n) { if (n <= 0) return m; if (m->pat->type == BP_TAGGED || m->pat->type == BP_CAPTURE) { @@ -979,7 +979,7 @@ match_t *_get_named_capture(match_t *m, const char *name, size_t namelen) // // Get a capture with a specific name. // -match_t *get_named_capture(match_t *m, const char *name, ssize_t _namelen) +public match_t *get_named_capture(match_t *m, const char *name, ssize_t _namelen) { size_t namelen = _namelen < 0 ? strlen(name) : (size_t)_namelen; if (m->pat->type == BP_TAGGED) {// || (m->pat->type == BP_CAPTURE && m->pat->args.capture.namelen > 0)) { diff --git a/pattern.c b/pattern.c index 61e6a5d..6c3484c 100644 --- a/pattern.c +++ b/pattern.c @@ -48,7 +48,7 @@ static inline void parse_err(const char *start, const char *end, const char *msg // Allocate a new pattern for this file (ensuring it will be automatically // freed when the file is freed) // -pat_t *allocate_pat(pat_t pat) +public pat_t *allocate_pat(pat_t pat) { static size_t next_pat_id = 1; pat_t *allocated = new(pat_t); @@ -151,7 +151,7 @@ static pat_t *expand_choices(pat_t *first, const char *end, bool allow_nl) // Given two patterns, return a new pattern for the first pattern followed by // the second. If either pattern is NULL, return the other. // -pat_t *chain_together(pat_t *first, pat_t *second) +public pat_t *chain_together(pat_t *first, pat_t *second) { if (first == NULL) return second; if (second == NULL) return first; @@ -169,7 +169,7 @@ pat_t *chain_together(pat_t *first, pat_t *second) // Given two patterns, return a new pattern for matching either the first // pattern or the second. If either pattern is NULL, return the other. // -pat_t *either_pat(pat_t *first, pat_t *second) +public pat_t *either_pat(pat_t *first, pat_t *second) { if (first == NULL) return second; if (second == NULL) return first; @@ -498,7 +498,7 @@ static pat_t *_bp_simplepattern(const char *str, const char *end, bool inside_st // Similar to bp_simplepattern, except that the pattern begins with an implicit // '}' open quote that can be closed with '{' // -maybe_pat_t bp_stringpattern(const char *str, const char *end) +public maybe_pat_t bp_stringpattern(const char *str, const char *end) { __TRY_PATTERN__ if (!end) end = str + strlen(str); @@ -554,7 +554,7 @@ static pat_t *bp_simplepattern(const char *str, const char *end) // Given a pattern and a replacement string, compile the two into a BP // replace pattern. // -maybe_pat_t bp_replacement(pat_t *replacepat, const char *replacement, const char *end) +public maybe_pat_t bp_replacement(pat_t *replacepat, const char *replacement, const char *end) { const char *p = replacement; if (!end) end = replacement + strlen(replacement); @@ -588,7 +588,7 @@ static pat_t *bp_pattern_nl(const char *str, const char *end, bool allow_nl) // // Return a new back reference to an existing match. // -pat_t *bp_raw_literal(const char *str, size_t len) +public pat_t *bp_raw_literal(const char *str, size_t len) { return Pattern(BP_STRING, str, &str[len], len, (ssize_t)len, .string=strndup(str, len)); } @@ -596,7 +596,7 @@ pat_t *bp_raw_literal(const char *str, size_t len) // // Compile a string representing a BP pattern into a pattern object. // -maybe_pat_t bp_pattern(const char *str, const char *end) +public maybe_pat_t bp_pattern(const char *str, const char *end) { str = after_spaces(str, true, end); if (!end) end = str + strlen(str); @@ -611,7 +611,7 @@ maybe_pat_t bp_pattern(const char *str, const char *end) return (maybe_pat_t){.success = false, .value.error.start = str, .value.error.end = end, .value.error.msg = "Failed to parse this pattern"}; } -void free_all_pats(void) +public void free_all_pats(void) { while (allocated_pats) { pat_t *tofree = allocated_pats; @@ -620,7 +620,7 @@ void free_all_pats(void) } } -void delete_pat(pat_t **at_pat, bool recursive) +public void delete_pat(pat_t **at_pat, bool recursive) { pat_t *pat = *at_pat; if (!pat) return; @@ -706,7 +706,7 @@ static int printf_pattern(FILE *stream, const struct printf_info *info, const vo } } -int set_pattern_printf_specifier(char specifier) +public int set_pattern_printf_specifier(char specifier) { return register_printf_specifier(specifier, printf_pattern, printf_pattern_size); } diff --git a/printmatch.c b/printmatch.c index aa2f1d5..8421a83 100644 --- a/printmatch.c +++ b/printmatch.c @@ -178,7 +178,7 @@ static void _explain_matches(match_node_t *firstmatch, int depth, const char *te // // Print a visualization of a match object. // -void explain_match(match_t *m) +public void explain_match(match_t *m) { printf("\033[?7l"); // Disable line wrapping match_node_t first = {.m = m}; @@ -196,7 +196,7 @@ static inline int fputc_safe(FILE *out, char c, print_options_t *opts) return printed; } -int fprint_match(FILE *out, const char *file_start, match_t *m, print_options_t *opts) +public int fprint_match(FILE *out, const char *file_start, match_t *m, print_options_t *opts) { int printed = 0; if (m->pat->type == BP_REPLACE) { diff --git a/utf8.c b/utf8.c index 08e8932..c5fc14b 100644 --- a/utf8.c +++ b/utf8.c @@ -7,6 +7,7 @@ #include #include "utf8.h" +#include "utils.h" #define ARRAY_LEN(a) (sizeof(a)/sizeof((a)[0])) #define likely(x) __builtin_expect((x), 1) @@ -182,7 +183,7 @@ static const uint32_t XID_Continue_only[][2] = { // Return the location of the next character or UTF8 codepoint. // (i.e. skip forward one codepoint at a time, not one byte at a time) // -const char *next_char(const char *str, const char *end) +public const char *next_char(const char *str, const char *end) { if (likely(str+1 <= end) && likely((str[0] & 0x80) == 0x0)) return str+1; @@ -199,7 +200,7 @@ const char *next_char(const char *str, const char *end) // Return the location of the previous character or UTF8 codepoint. // (i.e. skip backwards one codepoint at a time, not one byte at a time) // -const char *prev_char(const char *start, const char *str) +public const char *prev_char(const char *start, const char *str) { if (likely(str-1 >= start) && likely((str[-1] & 0x80) == 0x0)) return str-1; @@ -260,7 +261,7 @@ static bool find_in_ranges(uint32_t codepoint, const uint32_t ranges[][2], size_ return false; } -bool isidstart(const char *str, const char *end) +public bool isidstart(const char *str, const char *end) { if (unlikely(str >= end)) return false; else if (isalpha(*str) || *str == '_') return true; @@ -270,7 +271,7 @@ bool isidstart(const char *str, const char *end) && find_in_ranges(codepoint, XID_Start, ARRAY_LEN(XID_Start)); } -bool isidcontinue(const char *str, const char *end) +public bool isidcontinue(const char *str, const char *end) { if (unlikely(str >= end)) return false; else if (isalnum(*str) || *str == '_') return true; diff --git a/utils.c b/utils.c index edf0176..78b0a25 100644 --- a/utils.c +++ b/utils.c @@ -15,7 +15,7 @@ // Helper function to skip past all spaces (and comments) // Returns a pointer to the first non-space character. // -const char *after_spaces(const char *str, bool skip_nl, const char *end) +public const char *after_spaces(const char *str, bool skip_nl, const char *end) { // Skip whitespace and comments: skip_whitespace: @@ -41,7 +41,7 @@ const char *after_spaces(const char *str, bool skip_nl, const char *end) // Return the first character after a valid BP name, or NULL if none is // found. // -const char *after_name(const char *str, const char *end) +public const char *after_name(const char *str, const char *end) { if (str >= end) return end; if (*str == '|') return &str[1]; @@ -59,7 +59,7 @@ const char *after_name(const char *str, const char *end) // // Check if a character is found and if so, move past it. // -bool matchchar(const char **str, char c, bool skip_nl, const char *end) +public bool matchchar(const char **str, char c, bool skip_nl, const char *end) { const char *next = after_spaces(*str, skip_nl, end); if (next >= end) return false; @@ -73,7 +73,7 @@ bool matchchar(const char **str, char c, bool skip_nl, const char *end) // // Check if a string is found and if so, move past it. // -bool matchstr(const char **str, const char *target, bool skip_nl, const char *end) +public bool matchstr(const char **str, const char *target, bool skip_nl, const char *end) { const char *next = after_spaces(*str, skip_nl, end); if (next + strlen(target) > end) return false; @@ -89,7 +89,7 @@ bool matchstr(const char **str, const char *target, bool skip_nl, const char *en // character that was escaped. // Set *end = the first character past the end of the escape sequence. // -char unescapechar(const char *escaped, const char **after, const char *end) +public char unescapechar(const char *escaped, const char **after, const char *end) { size_t len = 0; unsigned char ret = '\\'; @@ -144,7 +144,7 @@ char unescapechar(const char *escaped, const char **after, const char *end) // // Free memory, but also set the pointer to NULL for safety // -void delete(void *p) +public void delete(void *p) { if (*(void**)p == NULL) errx(EXIT_FAILURE, "attempt to free(NULL)"); diff --git a/utils.h b/utils.h index 1819c75..628492e 100644 --- a/utils.h +++ b/utils.h @@ -20,6 +20,10 @@ __expr; \ }) +#ifndef public +#define public __attribute__ ((visibility ("default"))) +#endif + #define new(t) require(calloc(1, sizeof(t)), "`new(" #t ")` allocation failure") #define checked_strdup(s) require(strdup(s), "`checked_strdup(" #s ")` allocation failure") #define grow(arr,n) require(realloc(arr,sizeof(arr[0])*(n)), "`grow(" #arr ", " #n ")` allocation failure")