From 17ed36a7a54520e640849103f83fc1bc54e8c009 Mon Sep 17 00:00:00 2001 From: xaqq Date: Wed, 22 Jul 2015 15:47:36 +0200 Subject: [PATCH] Drop PCRE dependency. The config file is now manually parsed instead of using regex. While this is less beautifull, it allows us to drop PCRE as a dependency on Windows. --- CMakeLists.txt | 9 -- README-Windows.txt | 2 - cmake/FixBundle.cmake.in | 2 +- cmake/modules/FindPCRE.cmake | 42 ---------- cmake/modules/Makefile.am | 1 - libnfc/CMakeLists.txt | 13 --- libnfc/conf.c | 154 +++++++++++++++++++++++++++-------- 7 files changed, 122 insertions(+), 101 deletions(-) delete mode 100644 cmake/modules/FindPCRE.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b4aaa8..cf43cbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,15 +112,6 @@ IF(NOT WIN32) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libnfc.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) ENDIF(NOT WIN32) -# Require PCRE for Win32 -IF (WIN32) - FIND_PACKAGE(PCRE REQUIRED) - IF(PCRE_INCLUDE_DIRS) - INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIRS}) - LINK_DIRECTORIES(${PCRE_LIBRARY_DIRS}) - ENDIF(PCRE_INCLUDE_DIRS) -ENDIF(WIN32) - INCLUDE(LibnfcDrivers) IF(PCSC_INCLUDE_DIRS) diff --git a/README-Windows.txt b/README-Windows.txt index 06b9efc..bf4ba69 100644 --- a/README-Windows.txt +++ b/README-Windows.txt @@ -18,7 +18,6 @@ Requirements - MinGW-w64 compiler toolchain [1] - LibUsb-Win32 1.2.5.0 (or greater) [2] - CMake 2.8 [3] -- PCRE for Windows [4] This was tested on Windows 7 64 bit, but should work on Windows Vista and Windows XP and 32 bit as well. @@ -65,4 +64,3 @@ References http://sourceforge.net/projects/tdm-gcc/files/TDM-GCC%20Installer/tdm64-gcc-4.5.1.exe/download [2] http://sourceforge.net/projects/libusb-win32/files/ [3] http://www.cmake.org -[4] http://gnuwin32.sourceforge.net/packages/pcre.htm \ No newline at end of file diff --git a/cmake/FixBundle.cmake.in b/cmake/FixBundle.cmake.in index d11dc8f..6e8f843 100644 --- a/cmake/FixBundle.cmake.in +++ b/cmake/FixBundle.cmake.in @@ -6,6 +6,6 @@ SET(bundle "${CMAKE_INSTALL_PREFIX}/bin/nfc-list@CMAKE_EXECUTABLE_SUFFIX@") # set other_libs to a list of additional libs that cannot be reached by dependency analysis SET(other_libs "") -SET(dirs "@LIBUSB_LIBRARY_DIR@" "@PCRE_BIN_DIRS@") +SET(dirs "@LIBUSB_LIBRARY_DIR@") fixup_bundle("${bundle}" "${other_libs}" "${dirs}") diff --git a/cmake/modules/FindPCRE.cmake b/cmake/modules/FindPCRE.cmake deleted file mode 100644 index 3d043aa..0000000 --- a/cmake/modules/FindPCRE.cmake +++ /dev/null @@ -1,42 +0,0 @@ -# This CMake script wants to use pcre functionality needed for windows -# compilation. However, since PCRE isn't really a default install location -# there isn't much to search. -# -# Operating Systems Supported: -# - Windows (requires MinGW) -# Tested with Windows XP/Windows 7 -# -# This should work for both 32 bit and 64 bit systems. -# -# Author: A. Lian -# - -IF(WIN32) - IF(NOT PCRE_FOUND) - FIND_PATH(PCRE_INCLUDE_DIRS regex.h) - FIND_LIBRARY(PCRE_LIBRARIES NAMES PCRE pcre) - FIND_PATH(PCRE_BIN_DIRS pcre3.dll) - - IF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES AND PCRE_BIN_DIRS) - SET(PCRE_FOUND TRUE) - ENDIF(PCRE_INCLUDE_DIRS AND PCRE_LIBRARIES AND PCRE_BIN_DIRS) - ENDIF(NOT PCRE_FOUND) - - IF(PCRE_FOUND) - IF(NOT PCRE_FIND_QUIETLY) - MESSAGE(STATUS "Found PCRE: ${PCRE_LIBRARIES} ${PCRE_INCLUDE_DIRS} ${PCRE_BIN_DIRS}") - ENDIF (NOT PCRE_FIND_QUIETLY) - ELSE(PCRE_FOUND) - IF(PCRE_FIND_REQUIRED) - MESSAGE(FATAL_ERROR "Could not find PCRE") - ENDIF(PCRE_FIND_REQUIRED) - ENDIF(PCRE_FOUND) - - INCLUDE(FindPackageHandleStandardArgs) - FIND_PACKAGE_HANDLE_STANDARD_ARGS(PCRE DEFAULT_MSG - PCRE_LIBRARIES - PCRE_INCLUDE_DIRS - PCRE_BIN_DIRS - ) - -ENDIF(WIN32) diff --git a/cmake/modules/Makefile.am b/cmake/modules/Makefile.am index 55334ca..52fd92d 100644 --- a/cmake/modules/Makefile.am +++ b/cmake/modules/Makefile.am @@ -2,6 +2,5 @@ EXTRA_DIST = \ COPYING-CMAKE-SCRIPTS \ FindLIBUSB.cmake \ FindPCSC.cmake \ - FindPCRE.cmake \ UseDoxygen.cmake \ LibnfcDrivers.cmake diff --git a/libnfc/CMakeLists.txt b/libnfc/CMakeLists.txt index 7a51bb0..d4a4ec1 100644 --- a/libnfc/CMakeLists.txt +++ b/libnfc/CMakeLists.txt @@ -47,16 +47,6 @@ ENDIF(SPI_REQUIRED) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/buses) -IF(WIN32) - # Windows now requires regex, so we utilize PCRE - # since Windows doesn't get the benefit of finding in CMake - # it has to be added manually - IF(PCRE_FOUND) - INCLUDE_DIRECTORIES(${PCRE_INCLUDE_DIRS}) - LINK_DIRECTORIES(${PCRE_LIBRARY_DIRS}) - ENDIF(PCRE_FOUND) -ENDIF(WIN32) - IF(PCSC_FOUND) INCLUDE_DIRECTORIES(${PCSC_INCLUDE_DIRS}) LINK_DIRECTORIES(${PCSC_LIBRARY_DIRS}) @@ -94,9 +84,6 @@ SET_TARGET_PROPERTIES(nfc PROPERTIES SOVERSION 5 VERSION 5.0.1) IF(WIN32) # Libraries that are windows specific TARGET_LINK_LIBRARIES(nfc wsock32) - IF(PCRE_FOUND) - TARGET_LINK_LIBRARIES(nfc ${PCRE_LIBRARIES}) - ENDIF(PCRE_FOUND) ADD_CUSTOM_COMMAND( OUTPUT libnfc.lib diff --git a/libnfc/conf.c b/libnfc/conf.c index 47b2d03..981e272 100644 --- a/libnfc/conf.c +++ b/libnfc/conf.c @@ -33,9 +33,9 @@ #ifdef CONFFILES #include #include +#include #include #include -#include #include #include @@ -56,8 +56,122 @@ #define LIBNFC_CONFFILE LIBNFC_SYSCONFDIR"/libnfc.conf" #define LIBNFC_DEVICECONFDIR LIBNFC_SYSCONFDIR"/devices.d" +static int +escaped_value(const char line[BUFSIZ], int i, char **value) +{ + if (line[i] != '"') + goto FAIL; + i++; + if (line[i] == 0 || line[i] == '\n') + goto FAIL; + int c = 0; + while (line[i] && line[i] != '"') { + i++; + c++; + } + if (line[i] != '"') + goto FAIL; + *value = malloc(c + 1); + if (!*value) + goto FAIL; + memset(*value, 0, c + 1); + memcpy(*value, &line[i - c], c); + i++; + while (line[i] && isspace(line[i])) + i++; + if (line[i] != 0 && line[i] != '\n') + goto FAIL; + return 0; + +FAIL: + free(*value); + *value = NULL; + return -1; +} + +static int +non_escaped_value(const char line[BUFSIZ], int i, char **value) +{ + int c = 0; + while (line[i] && !isspace(line[i])) { + i++; + c++; + } + *value = malloc(c + 1); + if (!*value) + goto FAIL; + memset(*value, 0, c + 1); + memcpy(*value, &line[i - c], c); + i++; + while (line[i] && isspace(line[i])) + i++; + if (line[i] != 0) + goto FAIL; + return 0; + +FAIL: + free(*value); + *value = NULL; + return -1; +} + +static int +parse_line(const char line[BUFSIZ], char **key, char **value) +{ + *key = NULL; + *value = NULL; + int i = 0; + int c = 0; + + // optional initial spaces + while (isspace(line[i])) + i++; + if (line[i] == 0 || line[i] == '\n') + return -1; + + // key + while (isalnum(line[i]) || line[i] == '_' || line[i] == '.') { + i++; + c++; + } + if (c == 0 || line[i] == 0 || line[i] == '\n') // key is empty + return -1; + *key = malloc(c + 1); + if (!*key) + return -1; + memset(*key, 0, c + 1); + memcpy(*key, &line[i - c], c); + + // space before '=' + while (isspace(line[i])) + i++; + if (line[i] != '=') + return -1; + i++; + if (line[i] == 0 || line[i] == '\n') + return -1; + // space after '=' + while (isspace(line[i])) + i++; + if (line[i] == 0 || line[i] == '\n') + return -1; + if (escaped_value(line, i, value) == 0) + return 0; + else if (non_escaped_value(line, i, value) == 0) + return 0; + + // Extracting key or value failed + free(*key); + *key = NULL; + free(*value); + *value = NULL; + return -1; +} + static bool -conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const char *key, const char *value), void *data) +conf_parse_file(const char *filename, + void (*conf_keyvalue)(void *data, const char *key, const char *value), + void *data) { FILE *f = fopen(filename, "r"); if (!f) { @@ -65,21 +179,6 @@ conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const ch return false; } char line[BUFSIZ]; - const char *str_regex = "^[[:space:]]*([[:alnum:]_.]+)[[:space:]]*=[[:space:]]*(\"(.+)\"|([^[:space:]]+))[[:space:]]*$"; - regex_t preg; - if (regcomp(&preg, str_regex, REG_EXTENDED | REG_NOTEOL) != 0) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Regular expression used for configuration file parsing is not valid."); - fclose(f); - return false; - } - size_t nmatch = preg.re_nsub + 1; - regmatch_t *pmatch = malloc(sizeof(*pmatch) * nmatch); - if (!pmatch) { - log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Not enough memory: malloc failed."); - regfree(&preg); - fclose(f); - return false; - } int lineno = 0; while (fgets(line, BUFSIZ, f) != NULL) { @@ -89,29 +188,18 @@ conf_parse_file(const char *filename, void (*conf_keyvalue)(void *data, const ch case '\n': break; default: { - int match; - if ((match = regexec(&preg, line, nmatch, pmatch, 0)) == 0) { - const size_t key_size = pmatch[1].rm_eo - pmatch[1].rm_so; - const off_t value_pmatch = pmatch[3].rm_eo != -1 ? 3 : 4; - const size_t value_size = pmatch[value_pmatch].rm_eo - pmatch[value_pmatch].rm_so; - char key[key_size + 1]; - char value[value_size + 1]; - strncpy(key, line + (pmatch[1].rm_so), key_size); - key[key_size] = '\0'; - strncpy(value, line + (pmatch[value_pmatch].rm_so), value_size); - value[value_size] = '\0'; + char *key; + char *value; + if (parse_line(line, &key, &value) == 0) { conf_keyvalue(data, key, value); + free(key); + free(value); } else { log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Parse error on line #%d: %s", lineno, line); } } - break; } } - - free(pmatch); - regfree(&preg); - fclose(f); return false; }