diff --git a/src/Makefile.am b/src/Makefile.am index 9b5f4887e..8558df5ef 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -12,7 +12,7 @@ DEFAULT_INCLUDES = -I.. -I/usr/local/include CFLAGS = lib_LTLIBRARIES = libpostal.la -libpostal_la_SOURCES = strndup.c libpostal.c expand.c address_dictionary.c transliterate.c tokens.c trie.c trie_search.c trie_utils.c string_utils.c file_utils.c utf8proc/utf8proc.c normalize.c numex.c features.c unicode_scripts.c address_parser.c address_parser_io.c averaged_perceptron.c crf.c crf_context.c sparse_matrix.c averaged_perceptron_tagger.c graph.c graph_builder.c language_classifier.c language_features.c logistic_regression.c logistic.c minibatch.c float_utils.c ngrams.c place.c near_dupe.c double_metaphone.c geohash/geohash.c dedupe.c string_similarity.c acronyms.c soft_tfidf.c jaccard.c +libpostal_la_SOURCES = strndup.c libpostal.c expand.c address_dictionary.c transliterate.c tokens.c trie.c trie_search.c trie_utils.c string_utils.c file_utils.c utf8proc/utf8proc.c normalize.c numex.c features.c unicode_scripts.c address_parser.c address_parser_io.c averaged_perceptron.c crf.c crf_context.c sparse_matrix.c averaged_perceptron_tagger.c graph.c graph_builder.c language_classifier.c language_features.c logistic_regression.c logistic.c minibatch.c float_utils.c ngrams.c place.c near_dupe.c double_metaphone.c geohash/geohash.c dedupe.c string_similarity.c acronyms.c soft_tfidf.c jaccard.c log/log.c libpostal_la_LIBADD = libscanner.la $(CBLAS_LIBS) libpostal_la_CFLAGS = $(CFLAGS_O2) -D LIBPOSTAL_EXPORTS libpostal_la_LDFLAGS = -version-info @LIBPOSTAL_SO_VERSION@ -no-undefined @@ -28,42 +28,42 @@ libscanner_la_CFLAGS = $(CFLAGS_O0) -D LIBPOSTAL_EXPORTS $(CFLAGS_SCANNER_EXTRA) noinst_PROGRAMS = libpostal bench address_parser address_parser_train address_parser_test build_address_dictionary build_numex_table build_trans_table address_parser_train address_parser_test language_classifier_train language_classifier language_classifier_test near_dupe_test -libpostal_SOURCES = strndup.c main.c json_encode.c file_utils.c string_utils.c utf8proc/utf8proc.c +libpostal_SOURCES = strndup.c main.c json_encode.c file_utils.c string_utils.c utf8proc/utf8proc.c log/log.c libpostal_LDADD = libpostal.la libpostal_CFLAGS = $(CFLAGS_O3) bench_SOURCES = bench.c bench_LDADD = libpostal.la libscanner.la $(CBLAS_LIBS) bench_CFLAGS = $(CFLAGS_O3) -address_parser_SOURCES = strndup.c address_parser_cli.c json_encode.c linenoise/linenoise.c string_utils.c utf8proc/utf8proc.c +address_parser_SOURCES = strndup.c address_parser_cli.c json_encode.c linenoise/linenoise.c string_utils.c utf8proc/utf8proc.c log/log.c address_parser_LDADD = libpostal.la $(CBLAS_LIBS) address_parser_CFLAGS = $(CFLAGS_O3) -near_dupe_test_SOURCES = strndup.c near_dupe_test.c string_utils.c utf8proc/utf8proc.c +near_dupe_test_SOURCES = strndup.c near_dupe_test.c string_utils.c utf8proc/utf8proc.c log/log.c near_dupe_test_LDADD = libpostal.la near_dupe_test_CFLAGS = $(CFLAGS_O3) -build_address_dictionary_SOURCES = strndup.c address_dictionary_builder.c address_dictionary.c file_utils.c string_utils.c trie.c trie_search.c utf8proc/utf8proc.c +build_address_dictionary_SOURCES = strndup.c address_dictionary_builder.c address_dictionary.c file_utils.c string_utils.c trie.c trie_search.c utf8proc/utf8proc.c log/log.c build_address_dictionary_CFLAGS = $(CFLAGS_O3) -build_numex_table_SOURCES = strndup.c numex_table_builder.c numex.c file_utils.c string_utils.c tokens.c trie.c trie_search.c utf8proc/utf8proc.c +build_numex_table_SOURCES = strndup.c numex_table_builder.c numex.c file_utils.c string_utils.c tokens.c trie.c trie_search.c utf8proc/utf8proc.c log/log.c build_numex_table_CFLAGS = $(CFLAGS_O3) -build_trans_table_SOURCES = strndup.c transliteration_table_builder.c transliterate.c trie.c trie_search.c file_utils.c string_utils.c utf8proc/utf8proc.c +build_trans_table_SOURCES = strndup.c transliteration_table_builder.c transliterate.c trie.c trie_search.c file_utils.c string_utils.c utf8proc/utf8proc.c log/log.c build_trans_table_CFLAGS = $(CFLAGS_O3) -address_parser_train_SOURCES = strndup.c address_parser_train.c address_parser.c address_parser_io.c averaged_perceptron.c crf.c crf_context.c sparse_matrix.c graph.c graph_builder.c float_utils.c averaged_perceptron_trainer.c crf_trainer.c crf_trainer_averaged_perceptron.c averaged_perceptron_tagger.c address_dictionary.c normalize.c numex.c features.c unicode_scripts.c transliterate.c trie.c trie_search.c trie_utils.c string_utils.c tokens.c file_utils.c shuffle.c utf8proc/utf8proc.c ngrams.c +address_parser_train_SOURCES = strndup.c address_parser_train.c address_parser.c address_parser_io.c averaged_perceptron.c crf.c crf_context.c sparse_matrix.c graph.c graph_builder.c float_utils.c averaged_perceptron_trainer.c crf_trainer.c crf_trainer_averaged_perceptron.c averaged_perceptron_tagger.c address_dictionary.c normalize.c numex.c features.c unicode_scripts.c transliterate.c trie.c trie_search.c trie_utils.c string_utils.c tokens.c file_utils.c shuffle.c utf8proc/utf8proc.c log/log.c ngrams.c address_parser_train_LDADD = libscanner.la $(CBLAS_LIBS) address_parser_train_CFLAGS = $(CFLAGS_O3) -address_parser_test_SOURCES = strndup.c address_parser_test.c address_parser.c address_parser_io.c averaged_perceptron.c crf.c crf_context.c sparse_matrix.c graph.c graph_builder.c float_utils.c averaged_perceptron_tagger.c address_dictionary.c normalize.c numex.c features.c unicode_scripts.c transliterate.c trie.c trie_search.c trie_utils.c string_utils.c tokens.c file_utils.c utf8proc/utf8proc.c ngrams.c +address_parser_test_SOURCES = strndup.c address_parser_test.c address_parser.c address_parser_io.c averaged_perceptron.c crf.c crf_context.c sparse_matrix.c graph.c graph_builder.c float_utils.c averaged_perceptron_tagger.c address_dictionary.c normalize.c numex.c features.c unicode_scripts.c transliterate.c trie.c trie_search.c trie_utils.c string_utils.c tokens.c file_utils.c utf8proc/utf8proc.c log/log.c ngrams.c address_parser_test_LDADD = libscanner.la $(CBLAS_LIBS) address_parser_test_CFLAGS = $(CFLAGS_O3) -language_classifier_train_SOURCES = strndup.c language_classifier_train.c language_classifier.c language_features.c language_classifier_io.c logistic_regression_trainer.c logistic_regression.c logistic.c sparse_matrix.c sparse_matrix_utils.c features.c minibatch.c float_utils.c stochastic_gradient_descent.c ftrl.c regularization.c cartesian_product.c normalize.c numex.c transliterate.c trie.c trie_search.c trie_utils.c address_dictionary.c string_utils.c file_utils.c utf8proc/utf8proc.c unicode_scripts.c shuffle.c +language_classifier_train_SOURCES = strndup.c language_classifier_train.c language_classifier.c language_features.c language_classifier_io.c logistic_regression_trainer.c logistic_regression.c logistic.c sparse_matrix.c sparse_matrix_utils.c features.c minibatch.c float_utils.c stochastic_gradient_descent.c ftrl.c regularization.c cartesian_product.c normalize.c numex.c transliterate.c trie.c trie_search.c trie_utils.c address_dictionary.c string_utils.c file_utils.c utf8proc/utf8proc.c log/log.c unicode_scripts.c shuffle.c language_classifier_train_LDADD = libscanner.la $(CBLAS_LIBS) language_classifier_train_CFLAGS = $(CFLAGS_O3) -language_classifier_SOURCES = strndup.c language_classifier_cli.c language_classifier.c language_features.c logistic_regression.c logistic.c sparse_matrix.c features.c minibatch.c float_utils.c normalize.c numex.c transliterate.c trie.c trie_search.c trie_utils.c address_dictionary.c string_utils.c file_utils.c utf8proc/utf8proc.c unicode_scripts.c +language_classifier_SOURCES = strndup.c language_classifier_cli.c language_classifier.c language_features.c logistic_regression.c logistic.c sparse_matrix.c features.c minibatch.c float_utils.c normalize.c numex.c transliterate.c trie.c trie_search.c trie_utils.c address_dictionary.c string_utils.c file_utils.c utf8proc/utf8proc.c log/log.c unicode_scripts.c language_classifier_LDADD = libscanner.la $(CBLAS_LIBS) language_classifier_CFLAGS = $(CFLAGS_O3) -language_classifier_test_SOURCES = strndup.c language_classifier_test.c language_classifier.c language_classifier_io.c language_features.c logistic_regression.c logistic.c sparse_matrix.c features.c minibatch.c float_utils.c normalize.c numex.c transliterate.c trie.c trie_search.c trie_utils.c address_dictionary.c string_utils.c file_utils.c utf8proc/utf8proc.c unicode_scripts.c +language_classifier_test_SOURCES = strndup.c language_classifier_test.c language_classifier.c language_classifier_io.c language_features.c logistic_regression.c logistic.c sparse_matrix.c features.c minibatch.c float_utils.c normalize.c numex.c transliterate.c trie.c trie_search.c trie_utils.c address_dictionary.c string_utils.c file_utils.c utf8proc/utf8proc.c log/log.c unicode_scripts.c language_classifier_test_LDADD = libscanner.la $(CBLAS_LIBS) language_classifier_test_CFLAGS = $(CFLAGS_O3) diff --git a/src/libpostal.c b/src/libpostal.c index 066a3015d..e4039cb3e 100644 --- a/src/libpostal.c +++ b/src/libpostal.c @@ -472,3 +472,11 @@ void libpostal_teardown_language_classifier(void) { void libpostal_teardown_parser(void) { address_parser_module_teardown(); } + +void libpostal_log_set_stream(FILE *stream) { + log_set_stream(stream); +} + +FILE *libpostal_log_get_stream() { + return log_get_stream(); +} \ No newline at end of file diff --git a/src/libpostal.h b/src/libpostal.h index 42a13e3cb..b1dc9cb7f 100644 --- a/src/libpostal.h +++ b/src/libpostal.h @@ -329,6 +329,8 @@ typedef struct libpostal_normalized_token { LIBPOSTAL_EXPORT libpostal_normalized_token_t *libpostal_normalized_tokens(char *input, uint64_t string_options, uint64_t token_options, bool whitespace, size_t *n); LIBPOSTAL_EXPORT libpostal_normalized_token_t *libpostal_normalized_tokens_languages(char *input, uint64_t string_options, uint64_t token_options, bool whitespace, size_t num_languages, char **languages, size_t *n); +LIBPOSTAL_EXPORT void libpostal_log_set_stream(FILE *stream); +LIBPOSTAL_EXPORT FILE *libpostal_log_get_stream(); #ifdef __cplusplus } diff --git a/src/log/log.c b/src/log/log.c new file mode 100644 index 000000000..94a71b918 --- /dev/null +++ b/src/log/log.c @@ -0,0 +1,18 @@ +#include +#include +#include "log.h" + +FILE *log_error_stream = NULL; +bool log_error_stream_set = false; + +void log_set_stream (FILE *stream) { + log_error_stream = stream; + log_error_stream_set = true; +} + +FILE *log_get_stream() { + if ( log_error_stream_set ) { + return log_error_stream; + } + return stderr; +} \ No newline at end of file diff --git a/src/log/log.h b/src/log/log.h index 4baf97639..fc22f4ffa 100644 --- a/src/log/log.h +++ b/src/log/log.h @@ -20,36 +20,41 @@ /* safe readable version of errno */ #define clean_errno() (errno == 0 ? "None" : strerror(errno)) +void log_set_stream(FILE *stream); + +FILE *log_get_stream(); + + #if defined (LOG_NO_COLORS) || defined (_WIN32) - #define log_error(M, ...) fprintf(stderr, "ERR " M " at %s (%s:%d) errno:%s\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) - #define log_warn(M, ...) fprintf(stderr, "WARN " M " at %s (%s:%d) errno:%s\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) - #define log_info(M, ...) fprintf(stderr, "INFO " M " at %s (%s:%d)\n", ##__VA_ARGS__, __func__, __FILENAME__, __LINE__) - #define log_debug(M, ...) fprintf(stderr, "DEBUG " M " at %s (%s:%d)\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__) + #define log_error(M, ...) fprintf(log_get_stream(), "ERR " M " at %s (%s:%d) errno:%s\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) + #define log_warn(M, ...) fprintf(log_get_stream(), "WARN " M " at %s (%s:%d) errno:%s\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) + #define log_info(M, ...) fprintf(log_get_stream(), "INFO " M " at %s (%s:%d)\n", ##__VA_ARGS__, __func__, __FILENAME__, __LINE__) + #define log_debug(M, ...) fprintf(log_get_stream(), "DEBUG " M " at %s (%s:%d)\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__) #else - #define log_error(M, ...) fprintf(stderr, "\33[31mERR\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) - #define log_warn(M, ...) fprintf(stderr, "\33[91mWARN\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) - #define log_info(M, ...) fprintf(stderr, "\33[32mINFO\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", ##__VA_ARGS__, __func__, __FILENAME__, __LINE__) - #define log_debug(M, ...) fprintf(stderr, "\33[34mDEBUG\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__) + #define log_error(M, ...) fprintf(log_get_stream(), "\33[31mERR\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) + #define log_warn(M, ...) fprintf(log_get_stream(), "\33[91mWARN\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()) + #define log_info(M, ...) fprintf(log_get_stream(), "\33[32mINFO\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", ##__VA_ARGS__, __func__, __FILENAME__, __LINE__) + #define log_debug(M, ...) fprintf(log_get_stream(), "\33[34mDEBUG\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__) #endif /* NOCOLORS */ #if LOG_LEVEL > LOG_LEVEL_ERROR #undef log_error -#define log_error(M, ...) do { if (0) fprintf(stderr, "\33[31mERR\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()); } while(0) +#define log_error(M, ...) do { if (0) fprintf(log_get_stream(), "\33[31mERR\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()); } while(0) #endif #if LOG_LEVEL > LOG_LEVEL_WARN #undef log_warn -#define log_warn(M, ...) do { if (0) fprintf(stderr, "\33[91mWARN\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()); } while (0) +#define log_warn(M, ...) do { if (0) fprintf(log_get_stream(), "\33[91mWARN\33[39m " M " \33[90m at %s (%s:%d) \33[94merrno: %s\33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__, clean_errno()); } while (0) #endif #if LOG_LEVEL > LOG_LEVEL_INFO #undef log_info -#define log_info(M, ...) do { if (0) fprintf(stderr, "\33[32mINFO\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", ##__VA_ARGS__, __func__, __FILENAME__, __LINE__); } while (0) +#define log_info(M, ...) do { if (0) fprintf(log_get_stream(), "\33[32mINFO\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", ##__VA_ARGS__, __func__, __FILENAME__, __LINE__); } while (0) #endif #if LOG_LEVEL > LOG_LEVEL_DEBUG #undef log_debug -#define log_debug(M, ...) do { if (0) fprintf(stderr, "\33[34mDEBUG\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__); } while (0) +#define log_debug(M, ...) do { if (0) fprintf(log_get_stream(), "\33[34mDEBUG\33[39m " M " \33[90m at %s (%s:%d) \33[39m\n", ##__VA_ARGS__, __func__, __FILE__, __LINE__); } while (0) #endif #endif //LOG_H