summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:43:19 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-02 18:43:19 +0300
commit5c7048091e3a191e8a34f26852a8976b254e339b (patch)
treef1008a55d8ecb3304b5f51ea549156eaba21843b
parent5fad10f89c485cfdc7b99011f07609f8871160d4 (diff)
parent49980df270e6a39738a0c886c1eef6b42e782edb (diff)
downloadProject-Tick-5c7048091e3a191e8a34f26852a8976b254e339b.tar.gz
Project-Tick-5c7048091e3a191e8a34f26852a8976b254e339b.zip
Add 'genqrcode/' from commit '49980df270e6a39738a0c886c1eef6b42e782edb'
git-subtree-dir: genqrcode git-subtree-mainline: 5fad10f89c485cfdc7b99011f07609f8871160d4 git-subtree-split: 49980df270e6a39738a0c886c1eef6b42e782edb
-rw-r--r--genqrcode/.github/workflows/cmake.yml55
-rw-r--r--genqrcode/.github/workflows/configure.yml26
-rw-r--r--genqrcode/.gitignore58
-rw-r--r--genqrcode/CMakeLists.txt201
-rw-r--r--genqrcode/COPYING502
-rw-r--r--genqrcode/ChangeLog1826
-rw-r--r--genqrcode/Doxyfile1781
-rw-r--r--genqrcode/Makefile.am48
-rw-r--r--genqrcode/NEWS360
-rw-r--r--genqrcode/README.md235
-rw-r--r--genqrcode/TODO5
-rw-r--r--genqrcode/acinclude.m41391
-rwxr-xr-xgenqrcode/autogen.sh35
-rw-r--r--genqrcode/bitstream.c231
-rw-r--r--genqrcode/bitstream.h43
-rw-r--r--genqrcode/cmake/FindIconv.cmake115
-rw-r--r--genqrcode/configure.ac153
-rw-r--r--genqrcode/libqrencode.pc.in11
-rwxr-xr-xgenqrcode/makeREADME.sh10
-rw-r--r--genqrcode/mask.c356
-rw-r--r--genqrcode/mask.h38
-rw-r--r--genqrcode/mmask.c177
-rw-r--r--genqrcode/mmask.h34
-rw-r--r--genqrcode/mqrspec.c232
-rw-r--r--genqrcode/mqrspec.h150
-rw-r--r--genqrcode/qrenc.c1451
-rw-r--r--genqrcode/qrencode.1.in140
-rw-r--r--genqrcode/qrencode.c921
-rw-r--r--genqrcode/qrencode.h593
-rw-r--r--genqrcode/qrencode_inner.h88
-rw-r--r--genqrcode/qrinput.c1639
-rw-r--r--genqrcode/qrinput.h124
-rw-r--r--genqrcode/qrspec.c514
-rw-r--r--genqrcode/qrspec.h174
-rw-r--r--genqrcode/rsecc.c149
-rw-r--r--genqrcode/rsecc.h31
-rw-r--r--genqrcode/split.c323
-rw-r--r--genqrcode/split.h47
-rw-r--r--genqrcode/tests/CMakeLists.txt81
-rw-r--r--genqrcode/tests/Makefile.am86
-rw-r--r--genqrcode/tests/URI_testset.inc1273
-rw-r--r--genqrcode/tests/common.c285
-rw-r--r--genqrcode/tests/common.h56
-rw-r--r--genqrcode/tests/create_frame_pattern.c170
-rw-r--r--genqrcode/tests/create_mqr_frame_pattern.c170
-rw-r--r--genqrcode/tests/datachunk.c178
-rw-r--r--genqrcode/tests/datachunk.h20
-rw-r--r--genqrcode/tests/decoder.c953
-rw-r--r--genqrcode/tests/decoder.h43
-rw-r--r--genqrcode/tests/framebin0 -> 477320 bytes
-rw-r--r--genqrcode/tests/prof_qrencode.c102
-rw-r--r--genqrcode/tests/pthread_qrencode.c135
-rwxr-xr-xgenqrcode/tests/release_check.sh33
-rw-r--r--genqrcode/tests/rscode.c274
-rw-r--r--genqrcode/tests/rscode.h40
-rw-r--r--genqrcode/tests/rsecc_decoder.c64
-rw-r--r--genqrcode/tests/rsecc_decoder.h7
-rwxr-xr-xgenqrcode/tests/test_all.sh3
-rwxr-xr-xgenqrcode/tests/test_basic.sh13
-rw-r--r--genqrcode/tests/test_bitstream.c257
-rwxr-xr-xgenqrcode/tests/test_configure.sh61
-rw-r--r--genqrcode/tests/test_estimatebit.c183
-rw-r--r--genqrcode/tests/test_mask.c411
-rw-r--r--genqrcode/tests/test_mmask.c155
-rw-r--r--genqrcode/tests/test_monkey.c582
-rw-r--r--genqrcode/tests/test_mqrspec.c181
-rwxr-xr-xgenqrcode/tests/test_qrenc.sh45
-rw-r--r--genqrcode/tests/test_qrencode.c1073
-rw-r--r--genqrcode/tests/test_qrinput.c1130
-rw-r--r--genqrcode/tests/test_qrspec.c319
-rw-r--r--genqrcode/tests/test_rs.c126
-rw-r--r--genqrcode/tests/test_split.c553
-rw-r--r--genqrcode/tests/test_split_urls.c92
-rw-r--r--genqrcode/tests/view_qrcode.c641
-rwxr-xr-xgenqrcode/use/config.rpath684
75 files changed, 24746 insertions, 0 deletions
diff --git a/genqrcode/.github/workflows/cmake.yml b/genqrcode/.github/workflows/cmake.yml
new file mode 100644
index 0000000000..1fd5c4d65d
--- /dev/null
+++ b/genqrcode/.github/workflows/cmake.yml
@@ -0,0 +1,55 @@
+name: CMake-build
+
+on: [push, pull_request]
+
+env:
+ BUILD_TYPE: Release
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest, windows-latest]
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: run vcpkg
+ if: matrix.os == 'windows-latest'
+ uses: lukka/run-vcpkg@v6
+ with:
+ vcpkgArguments: getopt:x64-windows libiconv:x64-windows libpng:x64-windows
+ vcpkgDirectory: '${{ github.workspace }}/vcpkg'
+ vcpkgGitCommitId: '2a42024b53ebb512fb5dd63c523338bf26c8489c'
+ appendedCacheKey: ${{ hashFiles( '${{ github.workspace }}/.github/workflows/cmake.yml' ) }}
+
+ - name: brew setup
+ if: matrix.os == 'macos-latest'
+ run: brew install pkg-config libpng
+
+ - name: Create Build Environment
+ run: cmake -E make_directory ${{runner.workspace}}/build
+
+ - name: Configure CMake
+ if: matrix.os != 'windows-latest'
+ shell: bash
+ working-directory: ${{runner.workspace}}/build
+ run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DWITH_TESTS=yes -DBUILD_SHARED_LIBS=on
+
+ - name: Configure CMake for Windows
+ if: matrix.os == 'windows-latest'
+ shell: bash
+ working-directory: ${{runner.workspace}}/build
+ run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake -DWITH_TESTS=yes
+
+
+ - name: Build
+ working-directory: ${{runner.workspace}}/build
+ shell: bash
+ run: cmake --build . --config $BUILD_TYPE -j 2
+
+ - name: Test
+ working-directory: ${{runner.workspace}}/build
+ shell: bash
+ run: ctest -C $BUILD_TYPE
diff --git a/genqrcode/.github/workflows/configure.yml b/genqrcode/.github/workflows/configure.yml
new file mode 100644
index 0000000000..6fcf4d1a13
--- /dev/null
+++ b/genqrcode/.github/workflows/configure.yml
@@ -0,0 +1,26 @@
+name: build
+
+on: [push, pull_request]
+
+jobs:
+ build:
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [ubuntu-latest, macos-latest]
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: brew setup
+ if: matrix.os == 'macos-latest'
+ run: brew install automake autoconf pkg-config libpng
+ - name: generate configure script
+ run: ./autogen.sh
+ - name: configure
+ run: ./configure --with-tests
+ - name: make
+ run: make -j 2
+ - name: make check
+ run: make check
+ - name: make distcheck
+ run: make -j 2 distcheck
diff --git a/genqrcode/.gitignore b/genqrcode/.gitignore
new file mode 100644
index 0000000000..4b558b6c30
--- /dev/null
+++ b/genqrcode/.gitignore
@@ -0,0 +1,58 @@
+*.[oa]
+*.lo
+*.la
+*.gcno
+*.gcov
+*.gcda
+.deps/
+.libs/
+autom4te.cache/
+m4/
+CMakeLists.txt.user
+CMakeCache.txt
+CTestTestfile.cmake
+CMakeFiles/
+cmake_install.cmake
+Makefile
+Makefile.in
+README
+build
+config.log
+configure
+config.status
+config.h
+config.h.in
+aclocal.m4
+libtool
+stamp-h1
+qrencode
+qrencode.1
+libqrencode.pc
+tests/create_frame_pattern
+tests/create_mqr_frame_pattern
+tests/pthread_qrencode
+tests/prof_qrencode
+tests/test_bitstream
+tests/test_estimatebit
+tests/test_mask
+tests/test_mmask
+tests/test_monkey
+tests/test_mqrspec
+tests/test_qrencode
+tests/test_qrinput
+tests/test_qrspec
+tests/test_rs
+tests/test_split
+tests/test_split_urls
+tests/view_qrcode
+use/compile
+use/config.guess
+use/config.sub
+use/depcomp
+use/install-sh
+use/ltmain.sh
+use/missing
+use/test-driver
+html/
+massif.out.*
+gmon.out
diff --git a/genqrcode/CMakeLists.txt b/genqrcode/CMakeLists.txt
new file mode 100644
index 0000000000..773e037492
--- /dev/null
+++ b/genqrcode/CMakeLists.txt
@@ -0,0 +1,201 @@
+cmake_minimum_required(VERSION 3.1.0)
+
+project(QRencode VERSION 4.1.1 LANGUAGES C)
+
+option(WITH_TOOLS "Build utility tools" YES )
+option(WITH_TESTS "Build tests" NO )
+option(WITHOUT_PNG "Disable PNG support" NO)
+option(GPROF "Generate extra code to write profile information" OFF)
+option(COVERAGE "Generate extra code to write coverage information" OFF)
+option(ASAN "Use AddressSanitizer" OFF)
+option(BUILD_SHARED_LIBS "Enable build of shared libraries" NO)
+
+if(BUILD_TESTING)
+ set(WITH_TESTS ON)
+ message(DEPRECATION "use WITH_TESTS option instead BUILD_TESTING")
+endif()
+
+list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+set(CMAKE_THREAD_PREFER_PTHREAD ON)
+find_package(Threads)
+find_package(PNG)
+find_package(Iconv)
+
+if(CMAKE_USE_PTHREADS_INIT)
+ add_definitions(-DHAVE_LIBPTHREAD=1)
+ # for libqrencode.pc
+ set(LIBPTHREAD ${CMAKE_THREAD_LIBS_INIT})
+endif()
+
+## Check for system include files
+include(CheckIncludeFile)
+include(CheckFunctionExists)
+
+check_include_file(dlfcn.h HAVE_DLFCN_H )
+check_include_file(inttypes.h HAVE_INTTYPES_H)
+check_include_file(memory.h HAVE_MEMORY_H )
+check_include_file(stdint.h HAVE_STDINT_H )
+check_include_file(stdlib.h HAVE_STDLIB_H )
+check_include_file(strings.h HAVE_STRINGS_H )
+check_include_file(string.h HAVE_STRING_H )
+check_include_file(getopt.h HAVE_GETOPT_H )
+check_include_file(sys/time.h HAVE_SYS_TIME_H)
+check_include_file(time.h HAVE_TIME_H )
+check_include_file(pthread.h HAVE_PTHREAD_H )
+
+check_function_exists(strdup HAVE_STRDUP)
+
+if(HAVE_STRDUP)
+ add_definitions(-DHAVE_STRDUP=1)
+endif()
+
+if(CMAKE_COMPILER_IS_GNUCXX)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
+endif()
+
+if(GPROF)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg")
+endif()
+
+if(COVERAGE)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
+endif()
+
+if(ASAN)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls")
+endif()
+
+add_definitions(-DMAJOR_VERSION=${PROJECT_VERSION_MAJOR})
+add_definitions(-DMINOR_VERSION=${PROJECT_VERSION_MINOR})
+add_definitions(-DMICRO_VERSION=${PROJECT_VERSION_PATCH})
+add_definitions(-DVERSION="${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
+add_definitions(-DHAVE_SDL=0)
+
+if(MSVC)
+ set(CMAKE_DEBUG_POSTFIX "d")
+
+ add_definitions(-Dstrcasecmp=_stricmp)
+ add_definitions(-Dstrncasecmp=_strnicmp)
+ add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+ add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE)
+
+ if(WITH_TOOLS)
+ find_path(GETOPT_INCLUDE_DIR getopt.h PATH_SUFFIXES include)
+ find_library(GETOPT_LIBRARIES getopt PATH_SUFFIXES lib)
+ include_directories(${GETOPT_INCLUDE_DIR})
+ endif(WITH_TOOLS)
+endif(MSVC)
+
+set(QRENCODE_SRCS qrencode.c
+ qrinput.c
+ bitstream.c
+ qrspec.c
+ rsecc.c
+ split.c
+ mask.c
+ mqrspec.c
+ mmask.c)
+
+set(QRENCODE_HDRS qrencode_inner.h
+ qrinput.h
+ bitstream.h
+ qrspec.h
+ rsecc.h
+ split.h
+ mask.h
+ mqrspec.h
+ mmask.h)
+
+if(BUILD_SHARED_LIBS)
+ if(MSVC)
+ set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
+ endif()
+ add_library(qrencode SHARED ${QRENCODE_SRCS} ${QRENCODE_HDRS})
+ set_target_properties(qrencode PROPERTIES VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} SOVERSION ${PROJECT_VERSION_MAJOR})
+else()
+ add_library(qrencode ${QRENCODE_SRCS} ${QRENCODE_HDRS})
+endif()
+if(CMAKE_USE_PTHREADS_INIT)
+ target_link_libraries(qrencode Threads::Threads)
+endif()
+
+include(GNUInstallDirs)
+set(prefix "${CMAKE_INSTALL_PREFIX}")
+set(exec_prefix "${CMAKE_INSTALL_FULL_BINDIR}")
+set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}")
+set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}")
+set(VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
+
+configure_file(qrencode.1.in qrencode.1 @ONLY)
+configure_file(libqrencode.pc.in libqrencode.pc @ONLY)
+
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/qrencode.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libqrencode.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+install(FILES qrencode.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+install(TARGETS qrencode DESTINATION ${CMAKE_INSTALL_LIBDIR})
+
+## Build utility tools
+if(WITH_TOOLS)
+ if(NOT WITHOUT_PNG)
+ add_definitions(-DHAVE_PNG=1)
+ endif()
+ add_executable(qrenc qrenc.c)
+ set_target_properties(qrenc PROPERTIES OUTPUT_NAME qrencode)
+
+ if(NOT WITHOUT_PNG)
+ target_link_libraries(qrenc qrencode PNG::PNG)
+ else()
+ target_link_libraries(qrenc qrencode)
+ endif()
+
+ if(MSVC)
+ target_link_libraries(qrenc ${GETOPT_LIBRARIES})
+ endif(MSVC)
+
+ install(TARGETS qrenc DESTINATION ${CMAKE_INSTALL_BINDIR})
+endif()
+
+if(WITH_TESTS)
+ enable_testing()
+ add_definitions(-DWITH_TESTS=)
+ add_definitions(-DSTATIC_IN_RELEASE=)
+ add_subdirectory(tests)
+else()
+ add_definitions(-DSTATIC_IN_RELEASE=static)
+endif()
+
+## ==============================================================================
+##
+## Configuration summary
+##
+## ==============================================================================
+
+message(STATUS "------------------------------------------------------------" )
+message(STATUS "[QRencode] Configuration summary." )
+message(STATUS "------------------------------------------------------------ ")
+message(STATUS " System configuration:" )
+message(STATUS " .. Processor type .............. = ${CMAKE_SYSTEM_PROCESSOR}")
+message(STATUS " .. CMake executable ............ = ${CMAKE_COMMAND}" )
+message(STATUS " .. CMake version ............... = ${CMAKE_VERSION}" )
+message(STATUS " .. System name ................. = ${CMAKE_SYSTEM}" )
+message(STATUS " .. C++ compiler ................ = ${CMAKE_CXX_COMPILER}" )
+message(STATUS " .. C compiler .................. = ${CMAKE_C_COMPILER}" )
+message(STATUS " .. size(void*) ................. = ${CMAKE_SIZEOF_VOID_P}" )
+message(STATUS " Dependencies:" )
+#message(STATUS " .. Doxygen ..................... = ${DOXYGEN_EXECUTABLE}" )
+message(STATUS " .. Thread library of the system = ${CMAKE_THREAD_LIBS_INIT}")
+message(STATUS " .. Iconv ....................... = ${ICONV_FOUND}" )
+message(STATUS " .... Iconv includes ............ = ${ICONV_INCLUDE_DIR}" )
+message(STATUS " .... Iconv library ............. = ${ICONV_LIBRARIES}" )
+message(STATUS " .. ZLIB ........................ = ${ZLIB_FOUND}" )
+message(STATUS " .. PNG ......................... = ${PNG_FOUND}" )
+message(STATUS " .... PNG includes .............. = ${PNG_INCLUDE_DIR}" )
+message(STATUS " .... PNG library ............... = ${PNG_LIBRARIES}" )
+#message(STATUS " .. Memory checker .............. = ${MEMORYCHECK_COMMAND}" )
+message(STATUS " Project configuration:" )
+message(STATUS " .. Build test programs ........ = ${WITH_TESTS}" )
+message(STATUS " .. Build utility tools ........ = ${WITH_TOOLS}" )
+message(STATUS " .. Disable PNG support ........ = ${WITHOUT_PNG}" )
+message(STATUS " .. Installation prefix ......... = ${CMAKE_INSTALL_PREFIX}" )
+message(STATUS "------------------------------------------------------------ ")
diff --git a/genqrcode/COPYING b/genqrcode/COPYING
new file mode 100644
index 0000000000..4362b49151
--- /dev/null
+++ b/genqrcode/COPYING
@@ -0,0 +1,502 @@
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
diff --git a/genqrcode/ChangeLog b/genqrcode/ChangeLog
new file mode 100644
index 0000000000..79713f070d
--- /dev/null
+++ b/genqrcode/ChangeLog
@@ -0,0 +1,1826 @@
+2021.01.08 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [develop]
+ * tests/test_qrinput.c:
+ - A minor memory leak bug in a test case has been fixed.
+ * README.md:
+ - 'libpng12-dev' has been corrected to 'libpng-dev'. (closes #170)
+ (Thanks to @a6q)
+ * .github/workflows/cmake.yml:
+ - Updated 'run-vcpkg' package to v6.
+ - vcpkg's git commit ID has been updated to the latest master.
+
+2020.09.29 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [develop]
+ * qrencode.c:
+ - Removed unused code.
+ * qrencode.h:
+ - Added a sample code snippet to the document.
+
+2020.09.28 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [hotfix]
+ * qrinput.c, tests/test_estimatebit.c:
+ - Fixed a bug in the estimation of the Micro QR Code's data length
+ in QRinput_estimateBitStreamSizeOfEntry() has been fixed.
+ - Fixed a bug in the calculation of the Micro QR Code's data capacity in
+ QRinput_encodeBitStream().
+ - A test case to test the bugs above has been added.
+ - Level check failure in QRinput_new2() on Windows has been fixed.
+ * Bumped version to 4.1.1.
+ [develop]
+ * tests/release_check.sh:
+ - Release checker script has been added. Currently it checks only the
+ version numbers among scripts.
+ * configure.ac:
+ - '--enable-mudflap' option has been deleted. (mudflap is deprecated
+ since GCC 4.9)
+ * qrencode.h:
+ - Comments for QRcode_APIVersion() has been slightly improved.
+
+2020.09.27 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [develop]
+ * NEWS:
+ - All tab characters have been replaced with spaces.
+ * qrenc.c, qrencode.1.in:
+ - The effects of '--type' option's 'ASCII' and 'ASCIIi' have been
+ swapped. (closes #142)
+ * .github/workflows/{configure,cmake}.yml:
+ - CI scripts have been improved to utilze multiple cores and cache.
+ * tests/{test_basic.sh, test_qrenc.sh}:
+ - Code cleanups.
+ [code cleanups]
+ * various files:
+ - Cleanup compiler warnings.
+ [develop]
+ * Merged 'code cleanups' branch.
+ * qrenc.c:
+ - Text output bug of structured append has been fixed.
+
+2020.09.26 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [develop]
+ * tests/test_qrencode.c:
+ - Minor memory leak bug in a test case has been fixed.
+ * COPYING:
+ - Updated to the latest revision.
+ * qrenc.c:
+ - Some URLs' schemes have been updated to https from http.
+ * README.md, qrenc.c, qrencode.1.in, qrencode.[ch]:
+ - Copyright year has been updated.
+ * .github/workflows/{configure,cmake,cmake-windows}.yml:
+ - Workflow names have been improved.
+ * .travis.yml:
+ - Migration to Github Actions has been completed.
+ * .github/workflows/{configure,cmake,cmake-windows}.yml:
+ - CI scripts have been improved.
+ * README.md, makeREADME.sh:
+ - Status badge has been changed to show the result from the Github Actions
+ instead of Travis CI.
+
+2020.09.22 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [develop]
+ * mask.c, qrencode.h:
+ - Typos and grammer errors have been fixed.
+ * Merge branch 'optimization'.
+
+2020.09.21 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [optimization]
+ * tests/prof_qrencode.c:
+ - Test numbers are extended.
+ * mask.c:
+ - Minor optimizations.
+
+2020.08.30 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [develop]
+ * .github/workflows/configure.yml:
+ - Added macOS CI script.
+ * qrencode.1.in, qrenc.c:
+ - Detailed description of text output types has been added.
+ (closes #142)
+ * qrenc.c:
+ - Invalid XPM output has been fixed. (Thanks to @dlitz and @cbrt64)
+ (closes #136)
+ [optimization]
+ * qrencode.c:
+ - A tail recursion in FrameFiller_next() has been eliminated.
+
+2020.08.29 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [release-4.1.0]
+ * .github/workflows/{cmake,configure,cmake-windows}.yml:
+ - Github actions CI scripts have been added.
+ * tests/test_bitstream.c:
+ - Fixed memory leak.
+ * configure.ac, tests/{prof,pthread}_qrencode.c:
+ - Make configure to define HAVE_SYS_TIME_H in config.h.
+ * CMakeLists.txt:
+ - 'wingetopt' has been replaced to 'getopt'.
+ * qrencode.c, tests/test_qrencode.c:
+ - ECLEVEL check has been improved.
+ * .gitignore:
+ - Added 'use/test-driver'.
+ [master]
+ * merged release-4.1.0.
+ * version 4.1.0 has been released.
+
+2020.08.28 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [develop]
+ * Made a develoment branch.
+ * test_qrspec.c:
+ - Typo fixes.
+ * qrinput.[ch], tests/{test_qrencode.c, test_qrinput.c}:
+ - A precise boundary check has been introduced to
+ QRinput_estimateVersion(). (closes #160)
+ * qrinput.c, qrencode.c, tests/test_qrencode.c, qrenc.c, qrencode.1.in:
+ - QRinput_encodeMode*() now throws ERANGE when encoding Micro QR Code
+ and an appropriate version number was not specified.
+ - Now Micro QR Code also allows auto version adjustment.
+ * qrenc.c, qrencode.1.in:
+ - The synopsis has been improved. (Thanks to @jidanni) (closes #155)
+ - A new option '--strict-version' has been introduced.
+ * split.c:
+ - A tail recursion has been eliminated. (Thanks to @4061N) (closes #144)
+ * tests/*:
+ - All test programs are now TAP-ready. Now you can run all test programs
+ by 'make check'.(Thanks to @jtojnar) (closes #117)
+ * qrinput.c:
+ - Return value was ignored. (Thanks to @xiaoyur347) (closed #143)
+ * README.md, NEWS:
+ - Various documentation improvements and updates.
+ [release-4.1.0]
+ * Bumped version to 4.1.0.
+ * qrencode.h:
+ - Document improvements.
+ * qrenc.c, qrencode.1.in:
+ - Added 'UTF8i' and 'ANSIUTF8i' to the descriptions of the corresponding
+ options. (Thanks to @Khoyo) (merged #138)
+
+2020.02.23 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master]
+ * CMakeLists.txt, README.md:
+ - Merged #158 (Thanks to @neheb):
+ - Fixed the compile-time issue of the environment without libpng.
+
+2020.02.23 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master]
+ * README.md:
+ - Merged #151 (Thanks to @NancyLi1013):
+ - Added vcpkg installation instructions.
+
+2018.11.09 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master]
+ * configure.ac, README.md:
+ - Merged #137 (Thanks to @abelbeck and @charmander):
+ - 'too many arguments' bug has been fixed.
+
+2018.07.28 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master]
+ * CMakeLists.txt:
+ - Merged #133 (Thanks to @sdf5):
+ - Change CMAKE_SORUCE_DIR to CMAKE_CURRENT_SORUCE_DIR in
+ CMAKE_MODULE_PATH
+
+2018.06.14 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master]
+ * qrenc.c, qrencode.1.in, README.md, NEWS:
+ - UTF8 mode now supports ANSI256 color. (Thanks to András Veres-
+ Szentkirályi)
+
+2018.06.07 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master]
+ * CMakeLists.txt, tests/CMakeLists.txt:
+ - Merged #131 (Thanks to @mgorny):
+ - Update paths inside the pkg-config file to respect GNUInstallDirs.
+ - Improve pthread support for the main library when building via CMake.
+ - Always build libdecoder as static library.
+
+2018.06.06 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master, 4.0]
+ * tests/Makefile.am:
+ - Add missing test_basic.sh to EXTRA_DIST. (merged #127) (Thanks to
+ @mgorny)
+ * CMakeLists.txt:
+ - Use CMake GNUInstallDirs module to provide variables for configurable
+ install directories. (merged #128) (Thanks to @mgorny)
+ [4.0]
+ * configure.ac, CMakeLists.txt, README.md:
+ - Bumped version to 4.0.2.
+ [master]
+ * tests/{Makefile.am, CMakeLists.txt, test_qrspec.c}:
+ - Fix running test_qrspec when building out-of-source. (merged #129)
+ (Thanks to @mgorny)
+
+2018.06.04 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master, 4.0]
+ * CMakeLists.txt:
+ - STATIC_IN_RELEASE is now set to "static" when WITH_TESTS is disabled.
+ (closes #126)
+ - Tabs expaned.
+ [4.0]
+ * configure.ac, CMakeLists.txt, README.md:
+ - Bumped version to 4.0.1.
+
+2018.06.02 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master, 4.0]
+ * CMakeLists.txt:
+ - Added "WITHOUT_PNG" option that builds qrencode without PNG support.
+ (closes #125)
+
+2018.06.01 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master, 4.0]
+ * README.md:
+ - Added some notes of how to use autogen.sh. (closes #122) (Thanks to
+ @thebunnyrules)
+
+2017.10.20 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master]
+ * qrenc.c:
+ - Adds the --inline option, which omits the xml tag for SVG output.
+ (merged #110) (Thanks to @jp-bennett)
+ - Short option '-I' for '--inline' disabled.
+ * qrencode.1.in:
+ - Added some missing descriptions.
+ * README.md:
+ - Acknowledgments updated.
+
+2017.10.13 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master, 4.0]
+ * qrencode.h:
+ - Fix build on windows with Visual Studio. (merged #108) (Thanks to
+ @Ation)
+ [master]
+ * README.md:
+ - libqrencode now advertised as a "fast and compact" library.
+
+2017.10.08 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master]
+ * qrenc.c, qrinput.c, rsecc.c, tests/common.c, tests/decoder.c:
+ - Fixed some warnings. (closing #89 and #102)
+
+2017.10.06 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [master]
+ * tests/test_{all,basic}.sh:
+ - All tests except test_configure.sh can be run by test_basic.sh now.
+ - test_all.sh activates test_basic.sh + test_configure.sh.
+ - test_basic.sh is better during active development, especially when you
+ gave additional options to configure script.
+ * split.c, qrspec.c, mqrspec.c, mask.c, mmask.c, qrencode.c, qrinput.c,
+ rsecc.c, qrencode.c:
+ - Fixed some warnings. (closing #89 and #102)
+
+2017.10.05 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [4.0]
+ * tests/test_{mask,mmask,qrspec,mqrspec,split_urls,qrencode}.c:
+ - Removed or commented out unused functions.
+ - Command line option introduced for verbose debug information.
+
+2017.10.02 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [4.0]
+ * bitstream.h, qrencode.c, qrencode_inner.h:
+ - Memory alignment improved.
+ * tests/test_qrencode.c:
+ - Error messages improved.
+ * tests/{common.h datachunk.h, decoder.h, rscode.h, rsecc_decoder.h}:
+ - Reserved macro names are replaced.
+ * bitstream.[ch]:
+ - Some variables' type changed from int to size_t. (closing #89 and
+ #102)
+ * tests/common.[ch], tests/test_split_url.c:
+ - Fixed some warnings.
+ * NEWS:
+ - Format fixes.
+ * tests/test_mask.c:
+ - Fixed some warnings.
+ * qrencode.h, qrinput.h, mqrspec.c:
+ - Comment format fixes.
+ * various files in tests:
+ - Fixed some warnings.
+ * tests/test_qrencode.c:
+ - Removed unused function.
+ * tests/test_qrinput.c:
+ - Added a new test function.
+
+2017.09.29 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [4.0]
+ * README.md:
+ - Format fixes.
+ * rsecc.[ch]:
+ - Some variables' type changed from int to size_t. (closing #89 and
+ #102)
+
+2017.09.21 Kentaro Fukuchi <kentaro@fukuchi.org>
+ [4.0]
+ * qrencode.1.in, NEWS:
+ - Release date has been updated.
+ - Documentation updated.
+ * Version 4.0.0 has been released.
+
+2017.09.11 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Read buffer is now allocated as a static array to avoid malloc().
+ Suppresses memory leak warnings. (Thanks to @c-273)
+ * README.md:
+ - INSTALL and ACKNOWLEDGMENTS sections are updated.
+ * makeREADME.sh:
+ - Now it removes the attention line for github.com users.
+ * tests/test_qrenc.sh:
+ - Experimental test script for the command 'qrencode'.
+ - Dedicated to @c-273, who warned the possible memory leaks of qrencode.
+ (See #102)
+ * qrencode.spec.in, Makefile.am, configure.ac:
+ - SPEC file has been removed. (closes #105)
+ * Makefile.am:
+ - The generation rule for README has been improved.
+ [4.0]
+ * 4.0 branch has been started.
+ * README.md:
+ - Version number added to the 1st line.
+ - Fixed the URL to the badge of Travis CI.
+ [master]
+ * qrencode.[ch]:
+ - Symbol data representation of QRcode object has been slightly changed.
+ This change does not affect to most applications.
+ - If your application uses bits other than the LSB, read the comments of
+ QRCode class carefully.
+ * tests/test_qrencode.c:
+ - Modified correct pattern of a test referring non-LSB bits of QRCode.
+ * tests/view_qrcode.c:
+ - Now you can identify the feature of modules by color.
+
+2017.09.07 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * *.[ch]:
+ - Copyright year updated for the next major update.
+ * tests/test_configure.sh:
+ - Added some progress messages.
+ * tests/test_all.sh:
+ - Added test_configure.sh to the list.
+ * Makefile.am, tests/Makefile.am:
+ - Added some EXTRA_DIST files.
+ - Moved some EXTRA_DIST files from Makefile.am to tests/Makefile.am.
+ * makeREADME.sh:
+ - Newly added.
+ * configure.ac, CMakeLists.txt, README, README.md:
+ - Bumped version to 4.0.0, preparing for major update.
+ * .travis.yml:
+ - Configuration improved.
+ * Makefile.am, README:
+ - Added a new rule to generate README from README.md.
+ - README is no longer needed in the source tree.
+ * .gitignore:
+ - Added 'CTestTestfile.cmake'.
+ - Added 'README'
+ * README.md:
+ - Added Katsumi Saito, the contributor of SPEC file, has been added to
+ the section of ACKNOWLEDGMENTS. We apologize for this lack of
+ acknowledgment.
+
+2017.09.06 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * mqrspec.h:
+ - Documentation update.
+ * qrencode.[ch]:
+ - QRcode_clearCache() has been defined as a deprecated function for
+ backward compatibility.
+ * qrenc.c:
+ - Copyright year updated.
+ * NEWS, README, README.md:
+ - Documentation update.
+ * use/config.rpath:
+ - Updated to the newer version bundled with gettext-0.19.8.1.
+ * qrencode.1.in:
+ - Copyright year updated.
+
+2017.09.02 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * configure.ac:
+ - Replaced AC_PROG_RANLIB with LT_INIT.
+
+2017.08.04 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * CMakeLists.txt:
+ - Getopt.h is checked only by WITH_TOOLS. (merged #101) (Thanks to
+ @KangLin)
+ * README, README.md:
+ - ACKNOWLEDGMENTS has been updated.
+
+2017.03.15 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * ChangeLog, NEWS, TODO:
+ - Typos fixed. (merged #95) (Thanks to @jwilk)
+ * README, README.md:
+ - ACKNOWLEDGMENTS has been updated.
+ * README, README.md, qrenc.c, qrencode.1.in, qrencode.spec.in:
+ - The URI to the primary site has been updated. (http->https)
+ * CMakeLists.txt:
+ - Add version of shared library. (merged #96) (Thanks to @vanillahsu)
+
+2017.02.05 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * README, README.md:
+ - Added some notes to compile test programs. (closes #93)
+ * CMakeList.txt:
+ - Added BUILD_SHARED_LIBS option with MSVC export all. (merged #92)
+ (Thanks to @vilppuvuorinen)
+
+2017.02.03 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * CMakeLists.txt, cmake/FIND*.cmake, tests/CMakeLists.txt:
+ - Merged #91. (Thanks to @aleksey-nikolaev)
+ - CMake support has been improved greatly.
+ * README, README.md:
+ - ACKNOWLEDGMENTS has been updated.
+ - Some text cleanups.
+ * tests/frame, .gitignore:
+ - Empty frame data "tests/frame" has been included in the source tree.
+ * .travis.yml
+ - Stopped creating empty frame data.
+ - Bug fix.
+
+2016.11.20 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * tests/test_qrinput.c, tests/test_qrspec.c:
+ - Some warnings suppresed.
+
+2016.11.17 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * CMakeLists.txt, tests/CMakeLists.txt, travis.yml, tests/common.h,
+ tests/decoder.c, .gitignore:
+ - Merged #85. (Thanks to @misery)
+ * NEWS:
+ - Release note for version 4 has been updated.
+
+2016.09.19 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * qrenc.c, qrencode.c, split.c:
+ - Merged #82. (Thanks to @UniQP)
+ - Various code cleanups.
+ * *.h:
+ - Removed double underscores (__) from macro names in include guards.
+ (follows C99 standard)
+ * configure.ac, *.c:
+ - Renamed __STATIC macro to STATIC_IN_RELEASE. (follows C99 standard)
+ * qrencode.c:
+ - Removed unnecessary 'extern' from some functions.
+
+2016.09.18 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * CMakeLists.txt:
+ - Merged #83. (Thanks to @misery)
+ - This allows CMake users building the library without configure script.
+ IF you are using incomplete UNIX-like environment and configure script
+ does not work as expected, try CMake.
+ * README, README.md:
+ - Added some notes about CMake.
+
+2016.05.18 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * acinclude.m4:
+ - iconv.m4 has been updated to serial 19.
+ * configure.ac, Makefile.am, tests/Makefile.am:
+ - MinGW support has been improved.
+ * README, README.md:
+ - ACKNOWLEDGMENTS has been updated.
+ * qrencode.c:
+ - Memory leak bug fixed. (Closes #81. Thanks to @win32asm)
+ * Various code cleanups. (Merged #72. Thanks to @UniQP)
+
+2016.05.15 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * configure.ac:
+ - Merged pull-request #80. (Thanks to @EckoEdc)
+ - Add LDFLAGS for mingw compilation.
+
+2016.04.02 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * tests/common.h:
+ - Code refactoring.
+ - New debug functions have been added.
+ * tests/decoder.[ch], tests/test_monkey.c:
+ - QRcode_extractBits() has been extended. This will be used later.
+ * tests/decoder.[ch]:
+ - eccResult has been added to QRdata.
+ - Code refactoring.
+ * tests/decoder.[ch], tests/datachunk.[ch], tests/Makefile.am:
+ - Code refactoring.
+
+2016.03.30 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * bitstream.[ch], tests/test_bitstream.c:
+ - Added new function BitStream_newWithBits() and tests for it.
+ * tests/decoder.[ch], tests/test_monkey.c:
+ - Code refactoring.
+
+2016.03.29 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * tests/view_qrcode.c:
+ - Added mask=-2 mode for debug purpose.
+ * bitstream.c, qrencode.c:
+ - Incorrect bit padding has been fixed. (Thanks to Yuji Ueno)
+ * tests/test_bitstream.c, tests/test_qrencode.c:
+ - Incorrect bit padding has been fixed.
+ * README:
+ - ACKNOWLEDGMENTS has been updated.
+ * README.md:
+ - ACKNOWLEDGMENTS has been updated.
+ - Some missed contributors have been added to README.md.
+
+2016.02.21 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * configure.ac, tests/common.h, tests/view_qrcode.c:
+ - Migrated from SDL 1.2 to 2.0.
+ * README, README.md:
+ - Improved the install instruction. (Thanks to Ronald Michaels)
+
+2015.11.04 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * qrspec.h, mqrspec.h:
+ - Typo fix. (Thanks to @qianchenglenger)
+ * qrenc.c:
+ - Merged pull-request #74. (Thanks to @mgorny)
+ - Added support for UTF8i and ANSIUTF8i formats that provide reverse
+ mappings of UTF8 and ANSIUTF8 formats respective. This is useful for
+ black-on-white media.
+ * configure.ac, Makefile.am, qrenc.c, rsecc.c:
+ - Added new configure option "--without-png". (closes #70)
+
+2015.05.13 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * mqrspec.c:
+ - Typo fix.
+ * README, README.md:
+ - Text format improved.
+ * NEWS:
+ - Slightly updated.
+
+2015.05.06 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * qrenc.c:
+ - New option "--svg-path" has been added, that uses a single path
+ instead of multiple rectangles to draw the modules.
+ (cherry-picked from #41) (Thanks to @Oblomov)
+ * tests/test_qrenc.sh, tests/test_images/.gitignore:
+ - Added an unfinished test script for qrencode has been added.
+
+2015.05.05 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * qrencode.1.in, qrenc.c:
+ - Usage improved. (closes #62) (Thanks to @minus7)
+ - Typo fix. (Thanks to Ian Sweet (@Isweet))
+ * README, README.md:
+ - The list of contributors updated: '@' prefix added for github
+ usernames.
+ * qrenc.c:
+ - X Pixmap (XPM) support has been added. (closes #52)
+ (Thanks to @tklauser)
+ * qrspec.h, mqrspec.h, qrencode.h:
+ - empty descriptions of some @params are filled.
+ * rsecc.[ch], README:
+ - Short note about the credit has been improved.
+ * Some code cleanups.
+
+2015.05.04 Kentaro Fukuchi <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Merge pull request #63 from tklauser/qrenc-array-overflow-fix
+ - qrenc: Fix array overrun in color_set (Thanks to @tklauser and
+ @win32asm)
+ * split.c:
+ - Merge pull request #67 from siggi-heltau/patch-1
+ - The variable name "new" has been renamed to "newstring" because "new"
+ is a reserved word in C++. (Thanks to @siggi-heltau)
+ * qrenc.c:
+ - Added -r option to read input data from a file in addition to STDIN
+ and the command line. (cherry-picked from #68)
+ (Thanks to Robert Petersen)
+ - Typo fix. (cherry-picked from #68) (Thanks to Robert Petersen)
+ - long option "readin" has been changed to "read-from".
+ * qrencode.1.in:
+ - Updated the usage.
+ * README:
+ - Updated the list of contributors.
+ * tests/Makefile.am
+ - Added URI_testset.inc to EXTRA_DIST.
+ * .gitignore
+ - Added some patterns to ignore some generated files. (Thanks to
+ @tklauser, closes #64)
+
+2014.09.23 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * README, README.md:
+ - Some typo fixes. (Thanks to Danomi Manchego)
+
+2014.09.18 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * tests/view_qrcode.c:
+ - Rollbacked the previous change (6a4b2e3710b) around the main part.
+ * rsecc.c:
+ - Some code cleanups.
+ * tests/rsecc_decoder.[ch], tests/test_rs.c, Makefile.am:
+ - Syndrome checker has been added.
+
+2014.09.17 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * configure.ac:
+ - Added "-pthread" option to CFLAGS. (Thanks to Danomi Manchego)
+ * tests/Makefile.am:
+ - Removed explicit "-lpthread" which is not required anymore.
+
+2014.09.09 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * NEWS:
+ - Added an entry about 4.0.0. (not released yet)
+ * mask.[ch], tests/test_mask.c:
+ - Run length calculation has been slightly improved.
+ - Reduce malloc calls.
+ * qrspec.[ch], mqrspec.[ch]:
+ - Frame caches have been eliminated. It improves both memory efficiency
+ and performance... Wait, caches were completely meaningless? orz...
+ * qrencode.[ch]:
+ - QRcode_clearCache() has been eliminated.
+ * tests/prof_qrencode.c, tests/pthread_qrencode.c, tests/test_mask.c,
+ tests/test_mmask.c, tests/test_monkey.c, tests/test_mqrspec.c,
+ tests/test_qrencode.c, tests/test_qrspec.c:
+ - Removed cache clearing calls.
+ * qrencode.c:
+ - FrameFiller now allocated in stack, not heap.
+ * rsecc.c:
+ - Introduced mutex to avoid race condition.
+
+2014.09.08 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Added color support for EPS output.
+
+2014.08.18 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * configure.ac:
+ - Added new option "--enable-asan" that enables AddressSanitizer.
+
+2014.08.15 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * tests/view_qrcode.c:
+ - Version number check improved for Micro QR Code.
+
+2014.08.05 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * configure.ac, Makefile.am, tests/Makefile.am:
+ - Added some conditional flags for configuration/building process.
+ - HAVE_PNG and HAVE_SDL can be referred from both Makefile and program
+ code.
+ * tests/view_qrcode.c:
+ - Use SDL_WaitEvent() instead of SDL_PollEvent().
+ * tests/common.h:
+ - Added show_QRcode() for testing purposes. (Thanks to Sunil Maganally)
+ * tests/*.c:
+ - main()'s arguments now correctly declared.
+
+2014.07.25 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * tests/URI_testset.inc, tests/test_split_urls.c, tests/Makefile.am,
+ .gitignore:
+ - A new test suite evaluating splitting efficiency has been added.
+ - Still undertrial.
+
+2014.07.24 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrinput.c:
+ - Code refactoring (QRinput_Struct_count has been added).
+ - And more code cleanups.
+ - Avoid to add a Structued-append chunk when only one symbol is
+ generated. (Thanks to Yoshimichi Inoue)
+ * tests/test_qrinput.c:
+ - New test has been added.
+ * qrinput.c, qrencode.1.in:
+ - Added new option, "verbose".
+ * tests/common.h:
+ - printQRinputStruct() has been added.
+ * rsecc.{c,h}:
+ - Copyright notice and credit has been corrected.
+ * README, README.md:
+ - ACKNOWLEDGMENTS updates.
+ [3.4]
+ - Bumped version to 3.4.4.
+ * Version 3.4.4 has been released.
+
+2014.07.08 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c, qrinput.c, tests/test_qrinput.c:
+ - Code cleanups.
+ - Some possible minor bugs has been fixed.
+
+2014.07.07 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Serious typo fix.
+
+2014.07.06 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c, qrencode.1.in:
+ - Added a new image type PNG32 (direct color mode). (Thanks to Greg Hart)
+
+2014.07.04 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * use/config.rpath:
+ - Updated to the newer version bundled with gettext-0.18.3.2.
+ * acinclude.m4:
+ - Added iconv.m4, lib-{link,ld,prefix}.m4 for Mac OS.
+ * autogen.sh:
+ - mkdir m4 if not exist.
+ * qrencode.h:
+ - Fixed some doxygen commands.
+
+2014.06.27 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c, qrencode.1.in:
+ - Merged pull-request #44. (Thanks to Antenore)
+ - Fixed some format issues.
+
+2014.06.22 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrencode.c:
+ - A memory leak bug has been fixed. (Thanks to @win32asm)
+ * bitstream.c:
+ - Check return value of BitStream_expand. (PR #46, Thanks to @tklauser)
+
+2014.02.14 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrinput.c:
+ - Minor documentation fix.
+ * qrenc.c:
+ - Error message improved.
+
+2014.02.09 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * .travis.yaml:
+ - Configuration file for Travis CI. (Thanks to Danil Dörrhöfer)
+ * configure.ac:
+ - Fixed some warnings.
+
+2014.01.15 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Merged pull request 78d44fd - commandline argument --help and -V is
+ printed to stdout, instead of stderr.
+
+2014.01.04 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * rsecc.[ch]:
+ - Code cleanups.
+
+2013.10.27 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrinput.c:
+ - Bug in QRinput_insertFNC1Header() has been fixed. (Thanks to David
+ Binderman)
+ * qrinput.c, test/decoder.[ch]:
+ - Code cleanup.
+
+2013.09.08 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * tests/test_qrencode.c:
+ - Small bug fix.
+
+2013.09.06 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - bzero() has been replaced with memset(). (Thanks to Gavin Andresen)
+ * qrspec.c, qrinput.c:
+ - QRspec_getMinimumVersion() now returns maximum version number for
+ excessive input, instead of -1. Closes #31. (Thanks to Danil
+ Dörrhöfer)
+ * tests/test_qrencode.c:
+ - New tests for excessive or maximum input have been added.
+ * tests/test_qrinput.c:
+ - A deprecatd test has been removed.
+ [reduce_malloc]
+ * bitstream.c:
+ - Minimum length of bit buffer has been extended to 128. In many cases
+ the library needs 128 bits at least to generate a symbol.
+ [master]
+ * merged reduce_malloc branch.
+
+2013.08.22 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * configure.ac:
+ - Avoid to use sdl-config. (Thanks to Heiko Becker)
+
+2013.08.15 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * rsecc.[ch], qrencode.c, tests/test_rc.c:
+ - Code cleanups and refactoring.
+ - Bug fix.
+ * configure.ac:
+ - Bumped version to 3.9.0, preparing for major update.
+ * qrenc.c:
+ - Copyright year in usage has been updated.
+ - Help message improved.
+
+2013.08.15 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * rsecc.[ch], rscode.[ch], Makefile.am, qrencode.c:
+ - Reed-Solomon error correction code has been completely rewritten.
+ - Phil Karn's code has been removed (moved to tests).
+ * tests/test_rs.c, tests/test_qrencode.c, tests/rscode.[ch], tests/Makefile.am:
+ - Test codes related to ECC have been updated.
+ - Phil Karn's code has been moved to tests, just for test purpose.
+ * tests/test_mqrspec.c:
+ - Code cleanup.
+
+2013.07.29 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.4]
+ * configure.ac, README, NEWS:
+ - Bumped version to 3.4.3.
+
+2013.07.16 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - missing break in switch. (Thanks to ßlúèÇhîp)
+ * qrinput.c:
+ - missing/redundant breaks in some switch statements.
+
+2013.06.17 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Merged pull request #29. (Thanks to Daniel Dörrhöfer)
+ - Run length encoding has been made non-default.
+ - New option "--rle" has been instroduced to enable run length encoding
+ for SVG format.
+
+2013.03.30 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrinput.c:
+ - Renamed a variable ("index") to avoid compile-time warning. (Thanks to
+ Emmanuel Blot)
+ - Range check improved.
+ * autogen.sh:
+ - bug fix.(Thanks to Emmanuel Blot)
+
+2013.03.26 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Memory leak bug has been fixed. (Thanks to Hassan Hajji)
+ - Buffer overrun bug has been fixed.
+ - Code cleanups.
+
+2013.03.01 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * README, NEWS:
+ - Documentation update.
+ * Version 3.4.2 has been released.
+
+2013.02.26 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * split.c, tests/test_split.c:
+ - Applied Viona's bug fix patch. (Thanks to Viona)
+ - Additional switching cost between AN and Num mode has been included
+ correctly.
+ - Additional switching cost between 8 and AN/Num mode has been included
+ correctly.
+ - New test case has been added.
+
+2013.02.16 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.4, master]
+ * configure.ac, README, NEWS:
+ - Bumped version to 3.4.2.
+
+2013.02.16 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Now it includes "string.h" by itself for libpng16. (Thanks to Petr)
+
+2012.11.30 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrencode.h
+ - Doxygen documents improved.
+
+2012.11.09 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrinput.c:
+ - Code cleanup.
+
+2012.11.08 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrinput.c:
+ - Memory leak bug has been fixed. (issue #24) (Thanks to chisj)
+ * qrencode.c:
+ - Incorrect bit extraction bug in QRcode_encodeMaskMQR() has been fixed.
+ (issue #25) (Thanks to vlad417)
+ * tests/test_qrencode.c:
+ - Added NUL checks for malloc-related bugs using failmalloc.
+ - Added a new test for issue #25. (Thanks to vlad417)
+
+2012.10.21 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrinput.c:
+ - Unnecessary "goto ABORT" eliminated.
+
+2012.10.17 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.4]
+ * NEWS:
+ - Release note has been written.
+ * Version 3.4.1 has been released.
+
+2012.10.15 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.4]
+ * configure.ac:
+ - HAVE_LIBPTHREAD was not correctly defined in config.h.in.
+ * tests/test_configure.sh:
+ - New test script checking autoconf-related scripts has been added.
+ * configure.ac, README, NEWS:
+ - Bumped version to 3.4.1.
+
+2012.10.15 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.4]
+ * Version 3.4.0 has been released.
+ [master]
+ * Merged 3.4.0.
+
+2012.10.13 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.4]
+ * qrencode.h:
+ - Documentation improved.
+ - Copyright year has been updated.
+ * Doxyfile:
+ - Rebased on a template from Doxygen 1.7.6.1.
+
+2012.10.09 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.4]
+ * configure.ac, README, NEWS:
+ - Bumped version to 3.4.0.
+ * qrencode.1.in:
+ - Added SVG option to --type.
+ * qrenc.c:
+ - Usage improved.
+ - Inkscape-friendly SVG output.
+
+2012.09.29 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [reduce_malloc]
+ * bstream.h:
+ - Added a new function "BitStream_reset()".
+ * qrinput.c:
+ - Reduced the use of dynamic memory allocation.
+ - Performance improved.
+ - Interfaces of QRinput_getBitStream() and QRinput_mergeBitStream() have
+ been changed.
+
+2012.09.25 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [reduce_malloc]
+ * qrinput.c, tests/qrinput.c:
+ - Reduced the use of dynamic memory allocation.
+
+2012.09.25 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Input validation improved. (Thanks to Yann Droneaud)
+ * README:
+ - Contributors list has been updated.
+ - Added a note about autogen.sh.
+
+2012.09.24 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * tests/test_bitstream.c:
+ - Added new test.
+ * tests/test_{monkey,qrspec}.c:
+ - Warnings suppressed.
+ [reduce_malloc]
+ * bitstream.[ch]:
+ - Reduced the use of dynamic memory allocation.
+
+2012.09.22 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Color palette support has been added. Currently PNG and SVG are
+ supported
+ * qrencode.1.in:
+ - "--foreground" and "--background" options have been added.
+
+2012.09.19 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * README:
+ - Contributors list has been updated.
+ * qrencode.1.in:
+ - Followed Unicode block elements patch.
+
+2012.09.18 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Merge pull request #19 from mezcalero/master (Unicode block elements
+ support).
+
+2012.09.13 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Set XML(SVG) declaration's 'standalone' to 'yes'.
+
+2012.09.03 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - A bug introduced in 'b3d5f7' has been reverted. (Thanks to Terry)
+
+2012.09.03 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Integrated David's SVG patch.
+
+2012.04.21 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Incorrect arguments order has been fixed. (Thank to Fred Steinhaeuser)
+
+2012.04.18 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.3]
+ * qrenc.c:
+ - EPS dot size bug has been fixed (closes: #12).
+ * Version 3.3.1 has been released.
+
+2012.04.11 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [master]
+ * qrenc.c:
+ - Paper size and margin are now set properly in SVG output.
+
+2012.04.10 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [master]
+ * Following fixes have been contributed by Yutaka Niibe.
+ * qrencode.1.in:
+ - "Hyphen-used-as-minus-sign" error has been fixed.
+ * configure.ac, libqrencode.pc.in, tests/Makefile.am:
+ - Explicit link to libpthread has been eliminated.
+ * qrenc.c:
+ - Pulled Repox's SVG patch (Pull request #10).
+ - Slightly simplified.
+ [3.3]
+ * README, configure.ac:
+ - Bumped version to 3.3.1.
+
+2012.04.01 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.3]
+ * qrenc.c:
+ - ASCII mode has been added. (Thanks to Ralf Ertzinger)
+ - Small code cleanups.
+ - ASCII mode now handles ".txt" suffix correctly.
+ * NEWS, README:
+ - Documentation updates.
+ * Version 3.3.0 has been released.
+ [master]
+ * Merged to 3.3.0.
+
+2012.03.31 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.2]
+ * README, NEWS, configure.ac:
+ - Bumped version to 3.2.1.
+ * Version 3.2.1 has been released.
+ [3.3]
+ * qrenc.c:
+ - Copyright year has been updated.
+
+2012.03.30 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * libqrencode.pc.in :
+ - Replaced obsolete macro LIBPTHREAD with LIBS. (thx to gniibe)
+ * configure.ac:
+ - Checks $ac_cv_lib_pthread_pthread_mutex_init instead of
+ HAVE_LIBPTHREAD. (thx to gniibe)
+
+2012.02.28 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [master, 3.2.1]
+ * .gitignore:
+ - Added "tests/pthread_qrencode".
+ [3.3]
+ * 3.3 branch has been started.
+ - 3.2.1 has been canceled.
+ * configure.ac, README, NEWS:
+ - Version number changes.
+
+2012.01.31 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [master]
+ * Recent 3.2 branch has been merged into the master.
+ * qrenc.c:
+ - Quick bug fix introduced in 09b72eb3070a36461eb83c1ec5237e4855ee515b.
+
+2012.01.19 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.2.1]
+ * configure.ac, qrencode.[hc], qrenc.c, tests/test_qrencode.c:
+ - QRcode_APIVersion() and QRcode_APIVersionString() have been added.
+ - New macro values {MAJOR,MINOR,MICRO}_VERSION have been introduced.
+ - New tests have been added.
+ * qrenc.c:
+ - Removed a useless storage class specifier from enum imageType.
+ [master, 3.2.1]
+ * Pulled moshen:write_ansi.
+ [3.2.1]
+ * tests/decoder.c:
+ - Bug fix.
+ * qrenc.c:
+ - Code refactoring.
+ - Now you can omit "-o -" for EPS and ANSI output.
+ - Default margin size has been rollbacked to 4 for ANSI(256).
+ * README:
+ - Added Colin (moshen@github) to ACKNOWLEDGMENTS.
+ - Added zapster's real name to ACKNOWLEDGMENTS.
+
+2011.12.12 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.2.1]
+ * configure.ac, README:
+ - Bumped version to 3.2.1.
+
+2011.12.12 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c, qrencode.1.in:
+ - Usage updates.
+
+2011.12.11 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrenc.c:
+ - Pulled Zapster's EPS support patch.
+ - Some code cleanups.
+
+2011.11.26 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.2.0]
+ * qrencode.1.in:
+ - "RESOURCES" section has been added.
+ * README:
+ - URL to the main web site updated.
+ * Version 3.2.0 has been released.
+
+2011.11.23 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.2.0]
+ * qrencode.1.in:
+ - Added descriptions of "-d" and "-M".
+
+2011.11.3 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.2.0]
+ * tests/view_qrcode.c:
+ - Messages improved.
+ * mmask.c:
+ - A bug in mask evaluation function has been eliminatd.
+ * tests/test_mmask.c:
+ - New test case has been added.
+ * qrenc.c:
+ - Micro QR Code support is now marked as "experimental" explicitly.
+ * tests/test_qrinput.c, tests/test_qrencode.c:
+ - Added some test cases.
+
+2011.10.23 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ [3.2.0]
+ * 3.2 branch has been started.
+ * README, NEWS, configure.ac:
+ - Version number changes.
+ - Micro QR Code support is now marked as "experimental" explicitly.
+
+2011.10.23 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * mask.c, mmask.c, tests/common.h:
+ - Eliminated unused valiables.
+ * tests/test_qrencode.c:
+ - Some assertions added.
+
+2011.10.18 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * test/test_mask.c:
+ - To call QRspec_clearCache() at exit.
+
+2011.10.17 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * configure.ac:
+ - Now the latest PNG library is chosen when the configure script is
+ executed.
+ * Copyright year has been updated.
+
+2011.10.17 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * mask.c:
+ - Unneeded zero-clear has been eliminated from Mask_calcRunLength().
+ - A rounding-down error in N4 calculation has been fixed.
+ (Thanks to Adam Shepherd)
+ * tests/test_mask.c:
+ - Fixed some test cases.
+
+2011.10.17 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * mask.c:
+ - A bug in N3 penalty calculation functoin has been fixed.
+ (Thanks to Adam Shepherd)
+ * mask.h, tests/test_mask.c:
+ - Test cases for Mask_calcN1N3() have been added.
+ - Wrong test cases have been corrected.
+
+2011.10.16 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * mask.[ch]:
+ - Mask_calcRunLength() has been refactored out from Mask_evaluateSymbol().
+ * test/test_mask.c:
+ - New test code for Mask_calcRunLength has been added.
+
+2011.10.13 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * mask.[ch]:
+ - Mask_calcN2() has been refactored out from Mask_evaluateSymbol().
+ * test/test_mask.c:
+ - New test code for Mask_calcN2 has been added.
+ * README:
+ - Added a URL to the git repository.
+
+2011.08.13 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * configure.ac:
+ - Added "AC_PROG_RANLIB" (bug report from dev66)
+
+2011.08.07 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * libqrencode.pc.in:
+ - Cflags has been set. (issue #2)(Thanks to ryo-on)
+
+2011.05.05 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * split.c:
+ - strdup() code has been added for non-POSIX environments. (Thanks to
+ Seth Sims)
+ * configure.ac:
+ - Added AC_CHECK_FUNC([strdup]) for non-POSIX environments.
+ - Now mudflapth is used instead of mudflap when pthread is enabled.
+ * *.c:
+ - '#include "config.h"' has been moved to the top of the code and
+ wrapped with #if HAVE_CONFIG_H - #endif.
+
+2011.04.06 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * qrinput.c:
+ - Initializaion was missed in QRinput_insertFNC1Header().
+
+2011.02.09 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * tests/view_qrcode.c:
+ - "-h" had required an argument.
+
+2010.10.09 Kentaro FUKUCHI <kentaro@fukuchi.org>
+ * Copyright year and mail address were updated.
+ * README, qrencode.spec.in:
+ - The URL of qrencode's page has been updated.
+ * Makefile.am:
+ - Added ACLOCAL_AMFLAGS.
+ * use/config.rpath:
+ - Now explicitly included because required by AM_ICONV_LINK in
+ configure.ac.
+
+2010.02.03 Kentaro FUKUCHI <fukuchi@megaui.net>
+ [3.1.1]
+ * qrencode.c, README:
+ - Copyright year updates.
+ * Bumped version to 3.1.1.
+ * Version 3.1.1 has been released.
+
+2010.01.27 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrinput.c, qrencode.h:
+ - 8bit encoding improved.
+ - QRinput_encodeModeECI(), QRinput_appendECIheader(),
+ QRinput_estimateBitsModeECI() have been added.
+ * tests/test_qrinput.c:
+ - Some tests for ECI header have been added.
+ * qrinput.[ch]:
+ - STRUCTURE_HEADER_BITS was renamed to STRUCTURE_HEADER_SIZE.
+ - MODE_INDICATOR_SIZE has been added.
+ - QRinput_isSplittableMode() has been added.
+ * qrspec.c:
+ - QRspec_maximumWords() now returns 0 if the entry cannot be split.
+ - Now includes "qrinput.h" for QRinput_isSplittableMode().
+
+2010.01.25 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.h:
+ - QR_MODE_{ECI,FNC1A,FNC1B} have been added to QRencodeMode.
+ * qrspec.h, mqrspec.h, qrinput.c:
+ - QRSPEC_MODEID_* and MQRSPEC_MODEID_* have been added, and hard coded
+ numbers were replaced with them.
+ * qrenc.c:
+ - Modified usage.
+ * qrinput.h:
+ - Added a new field to QRinput for FNC1 support.
+ * qrinput.c, qrencode.h:
+ - Added new functions to set FNC1 flag.
+ - FNC1 second position encoding now supported.
+
+2010.01.22 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * tests/test_qrspec.c:
+ - Code cleanup.
+ * tests/decoder.[ch], tests/test_qrencode.c:
+ - Added tests for Micro QR Code.
+
+2010.01.20 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.c:
+ - Bug fix.
+ * tests/decoder.[ch]:
+ - Code refactoring.
+ * tests/test_{qrencode,mask,monkey}.c, Makefile.am:
+ - New tests added.
+ * qrencode_inner.h:
+ - Typo fix.
+ * NEWS:
+ - Updated.
+ * qrinput.c:
+ - Possible memory errors fixed.
+ * configure.ac, tests/Makefile.am:
+ - Added iconv checks.
+
+2010.01.18 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * configure.ac:
+ - Configuration cleanups.
+ * tests/Makefile.am:
+ - Wrong conditional branch fixed.
+ * tests/decoder.[ch], tests/Makefile.am:
+ - Decoding function has been added.
+ * tests/test_{qrinput,qrspec,qrencode}.c:
+ - New tests added.
+
+2010.01.16 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.[ch]:
+ - QRcode_encodeData{,MQR,Structured}() have been added.
+ * tests/test_qrencode.c:
+ - New test has been added.
+
+2009.11.27 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.h:
+ - Typo fixes.
+
+2009.11.06 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * NEWS, README:
+ - Documents updated.
+ * qrspec.[ch], mqrspec.[ch]:
+ - *_clearCache were not thread safe.
+ - "Thread unsafe" warnings were removed.
+ * rscode.[ch]
+ - free_rs_cache was not thread safe.
+ - "Thread unsafe" warnings were removed.
+
+2009.09.28 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrenc.c:
+ - David's patch has been applied. (Thanks to David)
+ - New options '-d' and '--dpi' have been added.
+ - Typo fixes.
+ * tests/view_qrcode.c:
+ - Typo fixes.
+
+2009.06.08 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.c:
+ - FrameFiller_nextMQR() has integrated to FrameFiller_next().
+ - FrameFiller_new() now requires mqr flag.
+ * qrencode.[ch], tests/prof_qrencode.c, tests/test_{qrencode,monkey}.c:
+ - QRcode_clearCache() has been added.
+ * configure.ac, qrencode_inner.h, qrencode.c, mask.[ch], mmask.[ch],
+ qrinput.h, qrspec.c, tests/common.h:
+ - A macro WITH_TESTS has been introduced.
+ - "#ifdef __STATIC" has been replaced with "#ifdef __WITH_TESTS".
+ - Some definitions in qrencode_inner.h have been moved to appropriate
+ header files.
+ - Including config.h became mandatory for test programs.
+ * tests/pthread_qrencode.c, tests/Makefile.am:
+ - New test program has been added.
+ * rscode.c:
+ - config.h was not included.
+ * mask.c:
+ - Race condition problem has been solved.
+
+2009.06.06 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrenc.c, tests/view_qrcode.c:
+ - Experimental support of Micro QR Code has been implemented.
+ * qrencode.[ch]:
+ - QRinput_setVersionAndErrorCorrectionLevel() has been added.
+ * tests/common.h, tests/test_split.c:
+ - Code cleanups.
+ - printFrame() and printQRcode() have been added.
+ * tests/test_qrencode.c:
+ - Some tests have been added.
+ * qrspec.h, mqrspec.h, qrencode.h:
+ - Definitions of {MQR,QR}SPEC_VERSION_MAX are moved to qrencode.h.
+ * qrinput.c, qrencode.h, tests/test_qrencode.c:
+ - Size check has been removed from QRinput_convertData() for MQR.
+ - QRinput_convertData() throws ERANGE when the input is too large.
+ - QRinput_appendPadding*() throws ERANGE when the input is too large.
+ - As a result, QRencode_encodeString*() throws ERANGE in that cases.
+ - Some assertion checks of errno added to test_qrencode.
+ * Bumped version to 3.9.0.
+ - Next public release will be 4.0.0.
+
+2009.06.06 Kentaro FUKUCHI <fukuchi@megaui.net>
+ [3.1.0]
+ * Version 3.1.0 has been released.
+
+2009.06.05 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.h, qrencode_inner.h, tests/test_qrencode.c:
+ - FrameFiller_next() has improved.
+ - FrameFiller_nextMQR() has been added.
+ - FrameFiller_test() FrameFiller_testMQR() have been added.
+ - Tests of FrameFiller added and improved.
+
+2009.06.04 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Makefile.am:
+ - Dependency check was incorrect because of misconfiguration.
+ * mask.c, mmask.c:
+ - Error check has been added to {Mask,MMask}_makeMask().
+ * mqrspec.[ch], qrinput.c:
+ - MQRspec_getDataLength() now returns in byte.
+ - MQRspec_getDataLengthBit() returns in bit instead.
+ * qrencode.[ch], qrencode_inner.h:
+ - QRencode_encodeStringMQR() and its 8bit version are added.
+ - QRcode_encodeMaskMQR() has been added.
+
+2009.06.01 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * tests/prof_qrencode.c:
+ - Error check has been added.
+ * tests/common.h:
+ - Bug fixed.
+ * qrinput.c, qrencode.h:
+ - QRinput_Struct_appendInput() and QRinput_splitQRinputToStruct() now
+ checks mqr flag.
+ * tests/test_bitstream.c:
+ - New test of 4bit padding of _toByte().
+
+2009.05.30 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * configure.ac, libqrencode.pc.in:
+ - New option "--enable-thread-safety" has been added. This option is
+ enabled by default.
+ * rscode.c, qrspec.c:
+ - libqrencode has become thread-safe! (probably)
+ * tests/common.h:
+ - sprintfBin() removed, printBstream() added.
+ * qrinput.[ch], qrencode.[ch], mqrspec.c:
+ - Functions for Micro QR Code encoding have been added.
+ * tests/common.h:
+ - Utility functions improved.
+ * tests/*.c:
+ - Code cleanups.
+ - Tests for Micro QR Code added.
+
+2009.05.30 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrinput.c:
+ - padlen check was wrong in QRinput_appendPaddingBit().
+ * tests/test_qrinput.c:
+ - Stop printing bstream->data.
+ - test_padding2() has been added.
+
+2009.05.21 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.c, qrencode_inner.h:
+ - MQRraw_* has been implemented.
+ - Code cleanups. Struct QRRaw_code is slightly changed.
+ * tests/test_qrencode.c:
+ - Added new test.
+
+2009.05.20 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Merged from 3.1.0 branch. (rev 2248:HEAD)
+ * mqrspec.[ch], tests/create_mqr_frame_pattern.c:
+ - MQRspec_getEccSpec() has been deleted.
+ * tests/create_mqr_frame_pattern.c, tests/Makefile.am:
+ - Newly added.
+ * mask.[ch], tests/test_mask.c, qrencode_inner.h:
+ - Code cleanups.
+ - Unnecessary memcpy has been eliminated.
+ - New test program has been added.
+ * mmask.[ch], qrencode_inner.h, tests/test_mmask.c, Makefile.am, tests/Makefile.am:
+ - Mask module for Micro QR Code has been added.
+
+2009.05.20 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrenc.c, qrinput.c, qrencode.c:
+ - Some compile warnings cleared.
+ * qrencode.c, tests/test_qrencode.c:
+ - NULL check of an input arg has been added to
+ QRcode_encodeString8bit().
+ - NULL check test and empty string test have been added for
+ QRcode_encodeString8bit().
+ * qrinput.h, qrencode_inner.h, split.c:
+ - Copyright year updates.
+ * split.[ch]:
+ - Split_splitStringToQRinput() set errno EINVAL if input string is
+ NULL or empty.
+ - Documentation improved.
+ * qrenc.c:
+ - perror() is now used to show the details of some errors.
+ * qrencode.[ch]:
+ - Some functions now set errno appropriately.
+ - Typo fixes.
+
+2009.05.20 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * tests/create_frame_pattern.c, tests/Makefile.am:
+ - New test tool "create_frame_pattern" has been added.
+ * tests/test_qrspec.c:
+ - test_alignment1() has been replaced with test_newframe().
+ test_newframe() compares newly created frames with frame pattern
+ data created by create_frame_pattern.
+ * tests/frame, tests/Makefile.am:
+ - Pattern file "frame" has been added to EXTRA_DIST.
+ * mask.c:
+ - Very small improvement. Unnecessary malloc()s are reduced.
+ * tests/test_qrencode.c:
+ - Two new tests have been added.
+ * split.c:
+ - NULL check and string length check have been added.
+ * qrspec.c, tests/test_qrinput.c:
+ - Forgotten padding bits bug has been fixed. (enbugged at 2009.5.18)
+ - New test for the bug above has been added.
+ * qrspec.[ch], qrencode_inner.h:
+ - Some function becomes __STATIC and their declarations have been
+ moved to qrencode_inner.h.
+ * tests/prof_qrencode.c:
+ - Now liberates all heap at the end of the program.
+
+2009.05.19 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.c, qrencode_inner.h:
+ - calloc() is now used to initialize rsblock.
+ - Number of malloc()s in RSblock_initBlock() has been integrated to
+ one malloc() in QRraw_new().
+ * rscode.c:
+ - A very small code improvement.
+ * qrinput.[ch]:
+ - More return value checks.
+ - Code cleanups.
+ * tests/common.h, tests/test_{split,monkey,qrinput}.c:
+ - Tests improved.
+ * qrspec.[ch], tests/test_qrspec.c:
+ - Code cleanups.
+ - QRspec_rs{Data,Ecc}Length() have been added.
+ * tests/view_qrcode.c:
+ - Code cleanups.
+ - Disabled mask setting in structured mode.
+ * tests/common.h:
+ - assert_nothing() has been added.
+ * qrinput.c, qrencode.c, tests/test_*.c:
+ - Various *_free() now allow NULL pointer. (nothing performed)
+ * qrspec.[ch]:
+ - Alignment pattern is now put by QRspec_putAlignmentPattern().
+ QRspec_getAlignmentPattern() and QRspec_freeAlignment() have been
+ removed.
+
+2009.05.18 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.c:
+ - More return value checks.
+ * bitstream.c:
+ - BitStream_free() allows NULL pointer (nothing performed).
+ * qrinput.c:
+ - QRinput_List_freeEntry() and QRinput_free() allow NULL pointer.
+ - QRinput_createPaddingBit() has been replaced with
+ QRinput_appendPaddingBit().
+ - QRinput_convertData() now sets errno to EINVAL when input is too
+ large.
+ - More return value checks. Mainly for ENOMEM error.
+
+2009.05.18 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Merged from 3.1.0 branch.
+
+2009.05.16 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.h:
+ - Indent improvement.
+ * Makefile.am:
+ - qrencode.spec has been added to EXTRA_DIST.
+
+2009.05.14 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrinput.c, qrencode.c, qrspe.c:
+ - More return value checks. Mainly for ENOMEM error.
+ * qrspec.[ch], qrencode.c, tests/test_qrspec.c:
+ - QRspec_getEccSpec() now accepts an int array instead to return
+ multiple values instead of returning dynamic allocated array.
+ * mask.c, rscode.c:
+ - More return value checks from malloc().
+ * configure.ac:
+ - Added "--enable-mudflap" option.
+ * rscode.[ch]:
+ - Added free_rs_cache() for debug purpose.
+ * tests/test_{monkey,qrencode,rs}.c:
+ - Call free_rs_cache() at the end of the tests.
+ * qrencode.c:
+ - QRraw_new() and RSblock_init() have been improved.
+ - Eliminated unnecessary calls of init_rs().
+ * autogen.sh, configure.ac:
+ - Darwin workarounds.
+ * tests/common.h, tests/test_bitstream.c:
+ - New tests have been added.
+
+2009.05.12 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * bitstream.c:
+ - BitStream_toByte() had returned non-NULL for an empty BitStream.
+ * tests/test_bitstream.c:
+ - test_null() has been added.
+ * qrinput.c:
+ - A possible memory leak has been eliminated. It happened when a wrong
+ version number was given.
+ * tests/test_qriput.c:
+ - Memory leaks have been eliminated.
+
+2009.05.01 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Bumped version to 3.1.0.
+
+2009.04.30 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * bitstream.[ch]:
+ - Internal representation of BitStream has been changed from
+ NUL-terminated string to unsigned char array.
+ * tests/common.h, tests/test_{bitstream,qrinput}.c:
+ - Some test sequences have been updated (see above).
+
+2009.03.25 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * configure.ac:
+ - "--without-tests" has become default setting.
+ * bitstream.[ch]:
+ - Now functions strictly check return value from malloc() and return
+ error if it fails.
+
+2008.10.31 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * tests/commo.h:
+ - __FUNCTION__ has been replaced with __func__, to follow the C99
+ standard.
+ - The way of variadic macros has been changed, to follow the C99
+ standard.
+
+2008.10.11 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode_inner.h:
+ - Now this header is called only by test programs.
+ * qrencode.c, qrencode_inner.h:
+ - Some definitions and declares written in qrencode_inner.h have been
+ moved into qrencode.c:
+ - QRraw_*() have been declared as __STATIC.
+ * mask.[ch], qrencode.c, qrencode_inner.h:
+ - Mask_makeMask() now requires QRecLevel.
+ - QRencode_writeFormatInformation() has been renamed and moved to
+ Mask_writeFormatInformation(), and become __STATIC.
+ * tests/*.c:
+ - Unneeded #include "qrencode_inner.h" have been removed.
+
+2008.10.11 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * autogen.sh:
+ - Darwin workaround.
+ * configure.ac:
+ - Now config.h offers "__STATIC" macro becomes "static" when
+ "--without-tests" is specified. This macro is useful for functions
+ called from test programs but not from other library codes.
+ * qrinput.c:
+ - Very little performance improvement.
+ * mask.c:
+ - Code cleanups.
+
+2008.09.12 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * tests/view_qrcode.c:
+ - Unused variable 'pitch' has been removed from draw_QRcode().
+
+2008.06.03 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Merged to the main trunk.
+
+2008.06.01 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrenc.c:
+ - Now it does not show the full usage when unrecognized options are
+ given.
+ - When "--help" is given, it displays the long usage.
+ * Version 3.0.3 has been released.
+
+2008.05.26 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrenc.c, tests/view_qrcode.c:
+ - getopt_long_only() has been replaced with getopt_long() which is
+ widely available. (Thanks to Gavan Fantom)
+ - Now it accepts long options.
+ * qrencode.1.in:
+ - followed the above changes.
+ * Bumped version to 3.0.3.
+
+2008.05.18 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrspec.c:
+ - The bit order of "Version information" has been corrected.
+ (Thanks to Paul Janssesn)
+ * configure.ac, Makefile.am:
+ - The "--without-tests" has been added to the configure script.
+ * qrencode.spec.in:
+ - Uses "--without-tests".
+ * Version 3.0.2 has been released.
+
+2008.05.14 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * various files:
+ - Some compile-time warnings/erros with g++ have been fixed.
+ (Thanks to wangsai)
+
+2008.05.09 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrenc.c:
+ - Now qrencode writes an image file in binary mode for non-POSIX
+ platform, such as MS-Windows. (bug report from Paul Janssens)
+ * Makefile.am:
+ - tests/test_all.sh has been added.
+ * tests/test_all.sh:
+ - Now it exits immediately if any test fails.
+ * Version 3.0.1 has been released.
+
+2008.05.01 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.spec.in:
+ - Added the man page to the files section.
+
+2008.04.30 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Version 3.0.0 has been released.
+
+2008.04.23 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Version 3.0.0rc3 has been released.
+ - This will probably be the final release candidate, if all goes well.
+
+2008.04.23 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * split.c:
+ - Split_identifyMode() now uses isdigit() and isalnum() macros.
+ * qrinput.c:
+ - Error checks have been improved.
+ * qrenc.c, tests/view_qrcode.c:
+ - Return value checks have been added.
+ - Structured-append encode with version 0 now returns error.
+ * qrencode.[ch]:
+ - QRencode_encodeStructuredInput() -> QRencode_encodeInputStructured()
+ (for consistency with other QRencode_encode*Structured() functions)
+ * mask.c:
+ - A code block never called has been eliminated.
+
+2008.04.14 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Version 3.0.0rc2 has been released.
+
+2008.04.20 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.h:
+ - QR_MODE_NUL has been added to QRencodeMode. Basically it is used
+ only by Split_identifyMode().
+ * qrinput.[ch], split.c:
+ - QRinput_identifyMode() has been moved to split.c, changed to static
+ and now needs a hint.
+ * split.c:
+ - Auto-splitting has been improved.
+ * qrinput.c:
+ - A memory leak has been fixed.
+ * configure.ac:
+ - The "--enable-gprof" and "--enable-gcov" options have been added.
+ * Makefile.am:
+ - man1_MANS has been moved into the "if BUILD_TOOLS - endif" block.
+
+2008.04.14 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Version 3.0.0rc1 has been released.
+
+2008.04.14 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Bumped version to 3.0.0.
+ * qrencode.[ch]:
+ - QRcode_encodeInput() has changed the API. Previously it takes a
+ QRinput, version and level, but now it takes only a QRinput, because
+ QRinput holds the version and level in it. From 3.0.0, you should
+ set them by calling QRinput_setVersion() and
+ QRinput_setErrorCorrectionLevel(), or use QRinput_new2() to
+ instantiate a QRinput object.
+
+2008.04.14 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrspe.c:
+ - NULL check has been added.
+ * split.[ch]:
+ - API changed.
+ * qrencode.c:
+ - Arguments (version and level) are now checked in QRcode_encodeMask().
+ Internal functions trust the arguments are valid.
+ - Error checks improved.
+ * qrinput.c:
+ - Error checks improved.
+ * qrencode.h:
+ - Documentation improvements.
+
+2008.04.13 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.c, qrencode_inner.h, tests/view_qrcode.c:
+ - Changed API of QRcode_encodeMask().
+ * qrencode.[ch], qrinput.[ch], split.[ch]:
+ - Some functions now set errno appropriately.
+
+2008.04.09 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.h, qrinput.c:
+ - QRinput_Struct_insertStructuredAppendHeaders() and
+ QRinput_insertStructuredAppendHeader now returns error, when the
+ input contains too many structured inputs.
+ * qrencode.c:
+ - QRcode_encodeInputToStructured() now returns NULL when
+ QRinput_splitQRinputToStruct() fails.
+ * tests/view_qrcode.c:
+ - Segmentation fault bug has been fixed. (see previous memo)
+
+2008.04.08 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrinput.c:
+ - Fixed a bug in QRinput_estimateBitStreamSizeOfEntry(). It could
+ overestimate the size.
+ * rscode.c:
+ - Optimized the order of the parameters equality test in init_rs().
+ * qrspec.c, qrspec.h:
+ - Added QRspec_clearCache().
+ * tests/test_estimatebit.c:
+ - Bug fixed in test_numbit3().
+
+2008.04.07 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Bumped version to 2.1.0.
+ * Structured append is now supported (patches from Yusuke Mihara):
+ - Two new types, QRcode_List and QRinput_Struct, have been added.
+ - Following functions have been added:
+ - QRcode_encodeStructuredInput()
+ - QRcode_encodeStringStructured()
+ - QRcode_encodeString8bitStructured()
+ - Some functions to handle structured append symbols have been added.
+ See Doxygen-ized descriptions for the details.
+ * qrenc.c:
+ - "-S" option has been added for structured append.
+ * split.h:
+ - "extern" was dropped.
+ * qrinput.h, qrencode.h:
+ - Moved declarations of QRinput_{get,set}{Version,ErrorCorrectionLevel}
+ from qrinput.h to qrencode.h. Now they are publicly accessible.
+ * qrencode.h, qrinput.h, qrinput.c:
+ - Added QRinput_new2().
+ - QRinput_newEntry(), QRinput_freeEntry have been renamed to
+ QRinput_List_newEntry(), QRinput_List_freeEntry().
+ * split.c:
+ - Bug fix: Split_eat8() now eats at least 1 byte. Previously it could
+ produce a 0-length input entry.
+
+2008.01.23 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.1.in, Makefile.am, configure.ac:
+ - Manpage of qrencode has been added.
+ * qrenc.c, tests/view_qrcode.c:
+ - Usage message has been updated.
+
+2008.01.18 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * split.c:
+ - Bug fixes.
+ * tests/test_split.c:
+ - Followed recent API changes.
+ - Added new test "test_toupper()".
+ * qrenc.c, tests/view_qrcode.c:
+ - Source-level compatibility has been improved.
+ - view_qrcode now accepts stdin like qrencode.
+ - Usage message has been updated/fixed.
+ * Copyright year has been updated.
+
+2008.01.16 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrinput.c, split.c:
+ - Case-sensitive mode becomes now default mode.
+ - Alphabet-Numeric mode now encodes only upper-case alphabet and
+ numeric characters. If "-i" option is given, split.c converts
+ lower-case characters to upper-case characters at first.
+ * qrenc.c, tests/view_qrcode.c:
+ - Case-sensitive mode becomes now default mode.
+ - Option "-i" has been added.
+
+2007.12.14 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * tests/test_qrencode.c:
+ - New test has been added.
+ * tests/view_qrcode.c:
+ - Options supported.
+ - Default mask is now -1 (auto).
+
+2007.12.13 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.[ch]:
+ - QRcode_writeFormatInformation now returns a number of dark modules.
+ * mask.c:
+ - The mask evaluation function now writes format information before
+ evaluation. (Philippe Delcroix)
+ * split.[ch]:
+ - Case-sensitive mode has been added to QRcode_encodeString().
+ - "-8" option has been added to qrenc.c.
+ - "-c" now encodes in improved case-sensitive mode.
+ * tests/test_{split,qrencode}.c:
+ - test_split*() have been moved to test_split.c.
+
+2007.12.10 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Bumped version to 2.0.0.
+ * Merged to main trunk.
+ * mask.[ch], split.[ch]:
+ - Masking functions and splitString functions are separated from
+ qrencode.c.
+ * mqrspec.[ch]:
+ - Specification of Micro QR code has been added, but not used yet.
+
+2007.03.24 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Bumped version to 1.0.2.
+
+2007.03.24 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode.c (QRcode_splitStringToQRinput):
+ - a small bug fix. (Thanks to NANKI Haruo)
+ * qrencode.h:
+ - "extern "C"" barrier has been added for C++.
+ * test/view_qrcode.c:
+ - a typo fix.
+
+2006.12.27 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Bumped version to 1.0.1.
+
+2006.12.27 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrenc.c, qrencode.[ch]:
+ - Added force 8-bit encoding mode.
+ * Makefile.am :
+ - Automake/Autoconf files have been added to dist-package.
+
+2006.12.17 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * qrencode_inner.h, qrencode.c:
+ - Removed unused member variable "b2" from QRRawCode.
+ * configure.ac, Makefile.am, acinclude.m4:
+ - Better configuration of libpng. (now uses pkg-config correctly)
+
+2006.12.02 Kentaro FUKUCHI <fukuchi@megaui.net>
+ * Bumped version to 1.0.0.
diff --git a/genqrcode/Doxyfile b/genqrcode/Doxyfile
new file mode 100644
index 0000000000..a2a015120c
--- /dev/null
+++ b/genqrcode/Doxyfile
@@ -0,0 +1,1781 @@
+# Doxyfile 1.7.6.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME = QRencode
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "QR Code encoder"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = YES
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = YES
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = YES
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = YES
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = NO
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = qrencode.h
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+# for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# style sheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE = 4
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the
+# mathjax.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH = http://www.mathjax.org/mathjax
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG = NO
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
diff --git a/genqrcode/Makefile.am b/genqrcode/Makefile.am
new file mode 100644
index 0000000000..d631b6dfe6
--- /dev/null
+++ b/genqrcode/Makefile.am
@@ -0,0 +1,48 @@
+AUTOMAKE_OPTIONS = foreign
+ACLOCAL_AMFLAGS=-I m4
+
+SUBDIRS = .
+
+if BUILD_TESTS
+SUBDIRS += tests
+endif
+
+lib_LTLIBRARIES = libqrencode.la
+
+libqrencode_la_SOURCES = qrencode.c qrencode_inner.h \
+ qrinput.c qrinput.h \
+ bitstream.c bitstream.h \
+ qrspec.c qrspec.h \
+ rsecc.c rsecc.h \
+ split.c split.h \
+ mask.c mask.h \
+ mqrspec.c mqrspec.h \
+ mmask.c mmask.h
+
+libqrencode_la_LDFLAGS = -version-number $(MAJOR_VERSION):$(MINOR_VERSION):$(MICRO_VERSION)
+
+include_HEADERS = qrencode.h
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libqrencode.pc
+noinst_DATA = README
+README_markdown_optional := $(wildcard README.md)
+README: $(README_markdown_optional)
+ $(if $(README_markdown_optional), ./makeREADME.sh)
+
+EXTRA_DIST = libqrencode.pc.in autogen.sh configure.ac acinclude.m4 \
+ Makefile.am tests/Makefile.am \
+ qrencode.1.in Doxyfile \
+ CMakeLists.txt cmake/FindIconv.cmake
+
+if BUILD_TOOLS
+bin_PROGRAMS = qrencode
+qrencode_SOURCES = qrenc.c
+qrencode_CFLAGS = $(png_CFLAGS)
+qrencode_LDADD = libqrencode.la $(png_LIBS)
+man1_MANS = qrencode.1
+endif
+
+if MINGW
+libqrencode_la_LDFLAGS += -no-undefined -avoid-version -Wl,--nxcompat -Wl,--dynamicbase
+endif
diff --git a/genqrcode/NEWS b/genqrcode/NEWS
new file mode 100644
index 0000000000..aa9aba274d
--- /dev/null
+++ b/genqrcode/NEWS
@@ -0,0 +1,360 @@
+libqrencode NEWS - Overview of changes
+======================================
+
+Version x.x.x (2020.xx.xx)
+--------------------------
+* Command line tool "qrencode" has been improved:
+ * The effects of '--type' option's 'ASCII' and 'ASCIIi' have been swapped.
+ (Thanks to Yannick Schinko)
+* Some minor bug fixes. (Thanks to Darsey Litzenberger and Edward E.)
+* Some performance improvements.
+
+
+Version 4.1.1 (2020.9.28)
+-------------------------
+* Some minor bugs in Micro QR Code generation have been fixed.
+ * The data capacity calculations are now correct. These bugs probably did not
+ affect the Micro QR Code generation.
+
+
+Version 4.1.0 (2020.8.29)
+-------------------------
+* Command line tool "qrencode" has been improved:
+ * New option "--inline" has been added. (Thanks to @jp-bennett)
+ * New option "--strict-version" has been added.
+ * UTF8 mode now supports ANSI256 color. (Thanks to András Veres-
+ Szentkirályi)
+* Micro QR Code no longer requires to specify the version number.
+* 'make check' allows to run the test programs. (Thanks to Jan Tojnar)
+* Some compile time warnings have been fixed.
+* Various CMake support improvements. (Thanks to @mgorny and @sdf5)
+* Some minor bug fixes. (Thanks to Lonnie Abelbeck and Frédéric Wang)
+* Some documentation/manpage improvements. (Thanks to Dan Jacobson)
+* Some performance improvements. (Thanks to @4061N and Mika Lindqvist)
+
+Release Note:
+The internal representation of the output code has been slightly changed -
+the second bit from LSB side now represents; 1:ECC bit / 0:data bit.
+This change is only for debug purposes and does not affect user applications.
+
+
+Version 4.0.2 (2018.6.6)
+------------------------
+* Build script fixes. (Thanks to @mgorny)
+
+
+Version 4.0.1 (2018.6.4)
+------------------------
+* CMake support improved.
+* New test scripts have been added.
+* Some compile time warnings have been fixed.
+
+
+Version 4.0.0 (2017.9.21)
+-------------------------
+* Memory efficiency has been improved.
+* QRcode_clearCache() has been deprecated.
+* Error correction code generating functions have been improved.
+* Command line tool "qrencode" has been improved:
+ * XPM support. (Thanks to Tobias Klauser)
+ * PNG32 (direct color mode) support. (Thanks to Greg Hart)
+ * EPS output now supports foreground and background color.
+ * New options "-r" and "--svg-path" have been added.
+ (Thanks to Robert Petersen and @Oblomov)
+* CMake support has been added. (optional) (Thanks to @misery)
+* Various bug fixes.
+* Various performance improvements.
+
+Release Note:
+While the API has not been changed since the previous major release, we
+incremented the major version number of libqrencode to 4 because the
+implementation of the library has been largely changed.
+
+This release improves the performance and memory footprints of code generation.
+
+Now you can build libqrencode with CMake.
+
+If you build the test programs, please note that the required SDL version has
+been changed from 1.2 to 2.0.
+
+
+Version 3.4.4 (2014.7.24)
+-------------------------
+* Bug fix release. (Thanks to Yoshimichi Inoue)
+* New option "--verbose" has been added to the command line tool.
+
+Release Note:
+When only one symbol is generated in structured-append mode, the library had
+inserted unnecessary chunk to the symbol and some QR Code readers fail to read
+it. Now the library omits the chunk and generate a symbol identical to non-
+structured symbol.
+
+
+Version 3.4.3 (2013.8.12)
+-------------------------
+* New option "--rle" has been added to the command line tool (Thanks to Daniel
+ Dörrhöfer)
+* Bug fixes. (Thanks to Hassan Hajji, Emmanuel Blot, and ßlúèÇhîp)
+
+Release Note:
+This release contains a couple of bug fixes and a new minor feature of the
+command line tool. Some minor bugs in the library have been fixed.
+
+Run Length Encoding (RLE) for SVG output decreases the size of the output file,
+but it makes complicated to edit the image by SVG editors. A newly introduced
+command line option "--rle" enables RLE. RLE will not be applied if it is not
+given.
+
+
+Version 3.4.2 (2013.3.1)
+------------------------
+* Bug fix release. (Thanks to chisj, vlad417, Petr and Viona)
+
+Release Note:
+Micro QR Code encoder had a bug that caused incorrect output (issue #25). Now
+the bug has been fixed. Memory leak bug (#24) and insufficient string splitting
+bug have been fixed.
+
+
+Version 3.4.1 (2012.10.17)
+--------------------------
+* Bug fix release.
+
+Release Note:
+Mutual exclusion did not work correctly since 3.3.1. If your application uses
+libqrencode in multithreaded environment, it is strongly recommended to update
+it.
+
+
+Version 3.4.0 (2012.10.15)
+--------------------------
+* SVG, UTF8, and ANSIUTF8 output supports have been added to the command line
+ tool. (Thanks to Dan Storm, David Dahl, and Lennart Poettering)
+* Colored QR Code support.
+* Bug fixes. (Thanks to Terry Burton, Fred Steinhaeuser, and Yann Droneaud)
+
+Release Note:
+Three new output format, SVG, UTF8, and ANSIUTF8 have been added to the command
+line tool. UTF8 and ANSIUTF8 are another text art mode, using Unicode block
+elements for high-resolution text output. Long-awaited colored QR code has been
+introduced. Try "--foreground" and "--background" options to set the colors.
+Currently PNG and SVG supports colored output.
+
+
+Version 3.3.1 (2012.4.18)
+-------------------------
+* Bugs in command line tool, manual, configure script, and libtool files have
+ been fixed. (Thanks to Yutaka Niibe and Rob Ryan)
+
+
+Version 3.3.0 (2012.4.1)
+-------------------------
+* EPS, ANSI, and ASCII text output supports have been added.
+ (Thanks to Zapster, Colin, and Ralf)
+* QRcode_APIVersion() and QRcode_APIVersionString() have been added.
+
+Release Note:
+Three new output format, EPS, ANSI, and ASCII text, have been added to the
+command line tool. ANSI and ASCII mode ignore "-size" option. Give "-t ASCIIi"
+to get an ASCII-mode symbol in inverted color.
+
+QRcode_APIVersion() is requested by Matthew Baker for better support of Python
+ctypes binding. Check them out at https://code.google.com/p/libqrencode-ctypes/
+
+
+Version 3.2.1 (2012.4.1)
+------------------------
+* Bugs in configure script and libtool file has been fixed. (Thanks to Yutaka
+ Niibe)
+
+
+Version 3.2.0 (2011.11.26)
+--------------------------
+* "--dpi" (or "-d") option has been added to qrencode. This option set DPI
+ information in an output PNG image. (Thanks to David Dahl)
+* New option "--enable-thread-safety" has been added to the configure script
+ that makes the library thread-safe. It is enabled by default.
+* QRcode_encodeData(), QRcode_encodeDataMQR, QRcode_encodeDataStructured() have
+ been added for binary data encoding including '\0'.
+* Typo and bug fixes.
+* Experimental Micro QR Code support has been added.
+* "--micro" (or "-M") option for Micro QR Code has been added to qrencode.
+ (experimental)
+
+Release Note:
+Binary data including '\0' is now supported. To encode a binary data, give "-8"
+option to qrencode, and let qrencode obtain data via standard input like
+"qrencode -8 -o output.png < binary". "--dpi" and "-d" are also added to embed
+DPI information to PNG file.
+
+A bug in the mask pattern evaluation routine has been fixed. In some cases,
+libqrencode may generate a different symbol from the one that was generated by
+the prior libqrencode because of this bug fix, but the embedded data are not
+affected. The symbols generated by the old libqrencode are valid.
+
+Experimental support of Micro QR Code encoder has been added. Some functions
+(QRcode_*MQR()) have been added to the library. The command line tool generates
+Micro QR Code when "--micro" or "-M" is given.
+
+
+Version 3.1.1 (2010.2.3)
+------------------------
+* A bug in the library has been fixed.
+
+Release Note:
+Libqrecode had generated incorrect QR Code in some cases. Symbols larger than
+version 5 (error correction level Q and H) were affected. In many cases this
+bug did not cause serious damage thanks to the error correction mechanism, but
+we highly recommend you to encode symbols again using this release.
+
+
+Version 3.1.0 (2009.6.6)
+------------------------
+* Various code cleanups and performance improves.
+* Strict internal error checks have been added.
+* "--without-tests" has become default setting. Specify "--with-tests" to
+ compile test programs.
+* Some memory leak bugs have been fixed.
+
+Release Note:
+This release focuses on the code cleanup and performance improve. Encoding time
+has been improved, drastically in large symbols. Basically this update only
+changes its internal code. The API is not changed, no need to recompile user
+applications that includes only qrencode.h. If your application refers the
+internal data representation (not recommended), see ChangeLog for further
+information.
+
+
+Version 3.0.3 (2008.6.1)
+------------------------
+* Portability enhancement. (Thanks to Gavan Fantom)
+* The command line tool "qrencode" now accepts long options. See the man page
+ for the detailed instruction.
+
+Release Note:
+This release improves the portability of our command line tool "qrencode".
+The library is not changed so that any applications using libqrencode are not
+affected.
+
+From this release, qrencode accepts "long" options, such as "--help". See the
+manpage for the detailed instructions.
+
+Qrencode now uses getopt_long() instead of getopt_long_only() which is not
+available in some operating systems. If the getopt_long() is not provided or
+the implementation of it is not compatible with GNU's one, please try
+qrencode-3.0.3-gnulib, that contains the source code of the getopt_long().
+Gnulib version is a test release. If you feel happy with it, please let us know
+and the future releases will include gnulib.
+
+
+Version 3.0.2 (2008.5.18)
+-------------------------
+* Some compile-time warnings/errors with g++ have been fixed.
+ (Thanks to wangsai)
+* The bit order of "Version information" has been corrected.
+ Symbols greater than version 6 were affected. (Thanks to Paul Janssesn)
+* The "--without-tests" option has been added to the configure script.
+
+
+Version 3.0.1 (2008.5.9)
+------------------------
+* A bug fix for non-POSIX platform. (Thanks to Paul Janssens)
+* The RPM spec file now packages the man page correctly.
+
+
+Version 3.0.0 (2008.4.30)
+-------------------------
+* The interface of QRencode_encodeInput() has been changed. User applications
+ using it must be modified.
+* Structured append support has been added. (patches from Yusuke Mihara)
+* The "-S" option for structured append has been added to qrencode and
+ view_qrcode.
+* Some functions now set errno to indicate errors.
+* Some bug fixes.
+
+Release Note:
+Now libqrencode supports "structured-append" of symbols. A large data set can
+be split into multiple QR code symbols. The basic usage of structured-append
+is not so different from the single symbol encoding: just call
+QRcode_encodeStringStructured() or QRcode_encodeString8bitStructured() and
+they return a list of symbols. Instead of giving a string, you can encode
+an explicitly typed data. See the manual generated by Doxygen for the detailed
+usage.
+
+Many thanks to Yusuke Mihara, who contributed a patch to add support of
+structured-append to version 1.0.2.
+
+API changes:
+
+* Incompatible API changes:
+ - QRencode_encodeInput
+* New types:
+ - QRinput_Struct
+ - QRcode_List
+* New functions:
+ - QRinput_new2
+ - QRinput_Struct_new
+ - QRinput_Struct_setParity
+ - QRinput_Struct_appendInput
+ - QRinput_Struct_free
+ - QRinput_Struct_insertStructuredAppendHeaders
+ - QRinput_splitQRinputToStruct
+ - QRcode_encodeStructuredInput
+ - QRcode_encodeStringStructured
+ - QRcode_encodeString8bitStructured
+ - QRcode_List_size
+ - QRcode_List_free
+* Declarations moved to qrencode.h:
+ - QRinput_getErrorCorrectionLevel
+ - QRinput_setErrorCorrectionLevel
+ - QRinput_getVersion
+ - QRinput_setVersion
+
+
+Version 2.0.0 (2008.1.24)
+-------------------------
+* "-i" option to ignore case distinctions has been added to qrencode and
+ view_qrcode.
+* "-c" option (case-sensitive mode) of qrencode is now enabled by default and
+ has been improved. See details in Release Note section.
+* "-8" option has been added to qrencode to encode whole data in 8-bit mode.
+* tests/view_qrcode now accepts various options like qrencode.
+* Man page has been added.
+* Code cleanup.
+* The mask evaluation bug has been fixed. (Philippe Delcroix)
+
+* API changes
+ - QRcode_encodeString() now receives case-sensitive flag.
+ - QRcode_encodeStringCase() has been removed.
+ - QRcode_encodeString8bit() has been added.
+
+Release Note:
+Previously libqrencode encodes lower-case alphabet characters in Alphabet-
+Numeric mode (upper-case alphabet and numeric) by default. According to the
+specification of QR code, however, it is clearly claimed that Alphabet-Numeric
+mode provides only upper-case alphabet (+ numeric and some symbol) characters.
+Since this version, libqrencode distinguishes lower-case and upper-case of
+alphabet characters by default. Because of that, "-c" option of qrencode
+is now deprecated, and "-i" option has been added. By giving "-i", qrencode
+converts lower-case characters to upper-case if possible, then encode a QR code
+symbol. Please read qrencode.h for the details about API changes if you are
+going to use this library.
+
+Many thanks to NANKI Haruo for his suggestions.
+
+
+Version 1.0.2 (2007.03.24)
+--------------------------
+* A small bug fix. (Thanks to NANKI Haruo)
+* 'extern "C"' barrier has been added to qrencode.h.
+
+
+Version 1.0.1 (2006.12.27)
+--------------------------
+* Added "force 8-bit encoding mode".
+* Configure script finds libpng's header correctly.
+
+
+Version 1.0.0 (2006.12.12)
+--------------------------
+* The first public release.
diff --git a/genqrcode/README.md b/genqrcode/README.md
new file mode 100644
index 0000000000..34f557aa9f
--- /dev/null
+++ b/genqrcode/README.md
@@ -0,0 +1,235 @@
+# libqrencode - a fast and compact QR Code encoding library
+[![build](https://github.com/fukuchi/libqrencode/workflows/build/badge.svg)](https://github.com/fukuchi/libqrencode/actions)
+
+**Attention:** This repository contains the development version of libqrencode. See <https://fukuchi.org/works/qrencode/> for the official stable releases. At this moment, the latest stable release is version 4.1.1.
+
+GENERAL INFORMATION
+===================
+Libqrencode is a fast and compact library for encoding data in a QR Code,
+a 2D symbology that can be scanned by handy terminals such as a smartphone.
+The capacity of QR Code is up to 7000 digits or 4000 characters and has high
+robustness.
+
+Libqrencode accepts a string or a list of data chunks then encodes in a QR Code
+symbol as a bitmap array. While other QR Code applications generate an image
+file, using libqrencode allows applications to render QR Code symbols from raw
+bitmap data directly. This library also contains a command-line utility outputs
+QR Code images in various formats.
+
+
+SPECIFICATION
+=============
+Libqrencode supports QR Code model 2, described in JIS (Japanese Industrial
+Standards) X0510:2004 or ISO/IEC 18004. Most of features in the specification
+are implemented such as:
+
+- Numeric, alphabet, Japanese kanji (Shift-JIS) or any 8 bit code can be
+ embedded
+- Optimized encoding of a string
+- Structured-append of symbols
+- Micro QR Code (experimental)
+
+Currently the following features are not supported:
+
+- ECI and FNC1 mode
+- QR Code model 1 (deprecated)
+
+
+INSTALL
+=======
+
+Requirements
+------------
+While the command-line utility and some test programs use libpng or SDL 2.0,
+the libqrencode library itself has no dependencies. You can skip compiling
+tests and/or tools if you want not to install programs using SDL or PNG.
+
+Compile & install
+-----------------
+If there is no "configure" script in the source code directory, run
+"autogen.sh" at first to generate it - this is mandatory if you downloaded the
+source from GitHub. Some additional software is needed to complete this
+process. For example, in Ubuntu, the following packages are needed:
+
+- autoconf
+- automake
+- autotools-dev
+- libtool
+- pkg-config
+- libpng-dev
+
+You can skip this process if you have "configure" script already (typically
+when you downloaded the source tarball from fukuchi.org.)
+
+Now you are ready to compile the library and tool. Type the following commands:
+
+```
+./configure
+make
+sudo make install
+sudo ldconfig
+```
+
+This compiles and installs the library and header file to the appropriate
+directories: by default, /usr/local/lib and /usr/local/include. You can change
+the destination directory by passing some options to the configure script.
+Run "./configure --help" to see the list of options.
+
+It also installs a command line tool "qrencode" to /usr/local/bin. If you want
+not to build it, give "--without-tools" option to the configure script.
+
+If the configure script does not work well, try to use CMake.
+
+```
+cmake .
+make
+```
+
+When you want to build the test programs, give "--with-tests" option to
+configure, or "-DWITH\_TESTS=YES" to cmake.
+
+### Building libqrencode with vcpkg
+
+You can download and install libqrencode using the
+[vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
+
+```
+git clone https://github.com/Microsoft/vcpkg.git
+cd vcpkg
+./bootstrap-vcpkg.sh
+./vcpkg integrate install
+./vcpkg install libqrencode
+```
+
+The libqrencode port in vcpkg is kept up to date by Microsoft team members and
+community contributors. If the version is out of date, please
+[create an issue or pull request](https://github.com/Microsoft/vcpkg) on the
+vcpkg repository.
+
+
+USAGE
+=====
+Basic usages of this library are written in the header file (qrencode.h).
+You can generate a manual of the library by using Doxygen, or see
+
+https://fukuchi.org/works/qrencode/manual/index.html
+
+
+WARNINGS
+========
+The library is distributed WITHOUT ANY WARRANTY.
+
+Micro QR Code support is EXPERIMENTAL.
+
+Be careful to use the command line tool (qrencode) if it is used by a web
+application (e.g. CGI script). For example, giving "-s" option with a large
+number to qrencode may cause DoS. The parameters should be checked by the
+application.
+
+
+LICENSING INFORMATION
+=====================
+Copyright (C) 2006-2018, 2020 Kentaro Fukuchi
+
+This library is free software; you can redistribute it and/or modify it under
+the terms of the GNU Lesser General Public License as published by the Free
+Software Foundation; either version 2.1 of the License, or any later version.
+
+This library is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this library; if not, write to the Free Software Foundation, Inc., 51
+Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+CONTACT
+=======
+Visit the homepage at:
+
+https://fukuchi.org/works/qrencode/
+
+for new releases. The git repository is available at:
+
+https://github.com/fukuchi/libqrencode
+
+Please mail any bug reports, suggestions, comments, and questions to:
+
+Kentaro Fukuchi <kentaro@fukuchi.org>
+
+or submit issues to:
+
+https://github.com/fukuchi/libqrencode/issues
+
+
+ACKNOWLEDGMENTS
+===============
+QR Code is registered trademarks of DENSO WAVE INCORPORATED in JAPAN and other
+countries.
+
+Reed-Solomon encoder included in this library is originally taken from FEC
+library developed by Phil Karn (KA9Q) and distributed under the terms of the
+GNU LGPL, then rewritten by Kentaro Fukuchi.
+Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
+
+* NANKI Haruo - improved lower-case characters encoding
+* Katsumi Saito - SPEC file
+* Philippe Delcroix - improved mask evaluation
+* Yusuke Mihara - structured-append support
+* David Dahl - DPI and SVG support patch
+* Adam Shepherd - bug fix patch of the mask evaluation
+* Josef Eisl (@zapster) - EPS support patch
+* Colin (@moshen) - ANSI support patch
+* Ralf Ertzinger - ASCII support patch
+* Yutaka Niibe (@gniibe)- various bug fix patches
+* Dan Storm (@Repox) - SVG support patch
+* Lennart Poettering (@mezcalero)
+ - improved text art patch
+* Yann Droneaud - improved input validation patch
+* Viona - bug fix patch for string splitting
+* Daniel Dörrhöfer (@d4ndo)
+ - RLE option, some bug fixes, Travis configuration
+* Greg Hart - PNG32 support patch
+* @siggi-heltau - bug fix patch
+* Tobias Klauser (@tklauser)
+ - bug fix patch, XPM support patch
+* Robert Petersen (@ripetersen)
+ - added ability to read input data from a file
+* @Oblomov - improved SVG support patch
+* Michał Górny (@mgorny)
+ - reverse mappings of UTF8 and ANSIUTF8, build script
+ fixes
+* @EckoEdc - MinGW support patch
+* Sebastian Buchwald (@UniQP)
+ - Various code cleanups
+* André Klitzing (@misery)
+ - CMake support
+* Alexey Nikolaev (@aleksey-nikolaev)
+ - improved CMake support
+* Vilppu Vuorinen (@vilppuvuorinen)
+ - improved CMake support
+* @vanillahsu - bug fix patch
+* @Ation - bug fix patch
+* Jonathan Bennett - Added "--inline" option to qrencode
+* András Veres-Szentkirályi
+ - ANSI256UTF8 support
+* @sdf5 - improved CMake support
+* Lonnie Abelbeck (@abelbeck)
+ - bug fix patch
+* @4061N - performance improvement patch
+* Rosen Penev (@neheb) - CMake bug fix patch
+* Mika Lindqvist (@mtl1979)
+ - replacement for gettimeofday() for Windows.
+* Darsey Litzenberger (@dlitz) and Edward E. (@cbrt64)
+ - fixed invalid XPM output
+* Shigeyuki Hirai, Paul Janssens, wangsai, Gavan Fantom, Matthew Baker,
+ Rob Ryan, Fred Steinhaeuser, Terry Burton, @chisj, @vlad417, Petr,
+ Hassan Hajji, Emmanuel Blot, ßlúèÇhîp, Heiko Becker, Gavin Andresen,
+ David Binderman, @ralgozino, Sean McMurray, Vlad Bespalov (@win32asm),
+ Antenore Gatta, Yoshimichi Inoue, Sunil Maganally, Norman Gray,
+ Danomi Manchego, @minus7, Ian Sweet, @qianchenglenger, Ronald Michaels,
+ Yuji Ueno, Jakub Wilk, @KangLin, @c-273, @thebunnyrules, @NancyLi1013,
+ Frédéric Wang, Dan Jacobson, Jan Tojnar, @xiaoyur347, @charmander,
+ Yannick Schinko, @a6q
+ - bug report / suggestion / typo fixes
diff --git a/genqrcode/TODO b/genqrcode/TODO
new file mode 100644
index 0000000000..475abfa88f
--- /dev/null
+++ b/genqrcode/TODO
@@ -0,0 +1,5 @@
+Micro QR code encoding is not tested well.
+
+Documents (not only the README, but also the manual of the library) needs
+revision of grammar, spelling or to resolve ambiguity or incomplete descriptions.
+Feel really free to send us your revision.
diff --git a/genqrcode/acinclude.m4 b/genqrcode/acinclude.m4
new file mode 100644
index 0000000000..bfd896e613
--- /dev/null
+++ b/genqrcode/acinclude.m4
@@ -0,0 +1,1391 @@
+# iconv.m4 serial 19 (gettext-0.18.2)
+dnl Copyright (C) 2000-2002, 2007-2014 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_DEFUN([AM_ICONV_LINKFLAGS_BODY],
+[
+ dnl Prerequisites of AC_LIB_LINKFLAGS_BODY.
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+
+ dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+ dnl accordingly.
+ AC_LIB_LINKFLAGS_BODY([iconv])
+])
+
+AC_DEFUN([AM_ICONV_LINK],
+[
+ dnl Some systems have iconv in libc, some have it in libiconv (OSF/1 and
+ dnl those with the standalone portable GNU libiconv installed).
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+ dnl Search for libiconv and define LIBICONV, LTLIBICONV and INCICONV
+ dnl accordingly.
+ AC_REQUIRE([AM_ICONV_LINKFLAGS_BODY])
+
+ dnl Add $INCICONV to CPPFLAGS before performing the following checks,
+ dnl because if the user has installed libiconv and not disabled its use
+ dnl via --without-libiconv-prefix, he wants to use it. The first
+ dnl AC_LINK_IFELSE will then fail, the second AC_LINK_IFELSE will succeed.
+ am_save_CPPFLAGS="$CPPFLAGS"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INCICONV])
+
+ AC_CACHE_CHECK([for iconv], [am_cv_func_iconv], [
+ am_cv_func_iconv="no, consider installing GNU libiconv"
+ am_cv_lib_iconv=no
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+#include <stdlib.h>
+#include <iconv.h>
+ ]],
+ [[iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);]])],
+ [am_cv_func_iconv=yes])
+ if test "$am_cv_func_iconv" != yes; then
+ am_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBICONV"
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+#include <stdlib.h>
+#include <iconv.h>
+ ]],
+ [[iconv_t cd = iconv_open("","");
+ iconv(cd,NULL,NULL,NULL,NULL);
+ iconv_close(cd);]])],
+ [am_cv_lib_iconv=yes]
+ [am_cv_func_iconv=yes])
+ LIBS="$am_save_LIBS"
+ fi
+ ])
+ if test "$am_cv_func_iconv" = yes; then
+ AC_CACHE_CHECK([for working iconv], [am_cv_func_iconv_works], [
+ dnl This tests against bugs in AIX 5.1, AIX 6.1..7.1, HP-UX 11.11,
+ dnl Solaris 10.
+ am_save_LIBS="$LIBS"
+ if test $am_cv_lib_iconv = yes; then
+ LIBS="$LIBS $LIBICONV"
+ fi
+ am_cv_func_iconv_works=no
+ for ac_iconv_const in '' 'const'; do
+ AC_RUN_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+#include <iconv.h>
+#include <string.h>
+
+#ifndef ICONV_CONST
+# define ICONV_CONST $ac_iconv_const
+#endif
+ ]],
+ [[int result = 0;
+ /* Test against AIX 5.1 bug: Failures are not distinguishable from successful
+ returns. */
+ {
+ iconv_t cd_utf8_to_88591 = iconv_open ("ISO8859-1", "UTF-8");
+ if (cd_utf8_to_88591 != (iconv_t)(-1))
+ {
+ static ICONV_CONST char input[] = "\342\202\254"; /* EURO SIGN */
+ char buf[10];
+ ICONV_CONST char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_utf8_to_88591,
+ &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if (res == 0)
+ result |= 1;
+ iconv_close (cd_utf8_to_88591);
+ }
+ }
+ /* Test against Solaris 10 bug: Failures are not distinguishable from
+ successful returns. */
+ {
+ iconv_t cd_ascii_to_88591 = iconv_open ("ISO8859-1", "646");
+ if (cd_ascii_to_88591 != (iconv_t)(-1))
+ {
+ static ICONV_CONST char input[] = "\263";
+ char buf[10];
+ ICONV_CONST char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_ascii_to_88591,
+ &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if (res == 0)
+ result |= 2;
+ iconv_close (cd_ascii_to_88591);
+ }
+ }
+ /* Test against AIX 6.1..7.1 bug: Buffer overrun. */
+ {
+ iconv_t cd_88591_to_utf8 = iconv_open ("UTF-8", "ISO-8859-1");
+ if (cd_88591_to_utf8 != (iconv_t)(-1))
+ {
+ static ICONV_CONST char input[] = "\304";
+ static char buf[2] = { (char)0xDE, (char)0xAD };
+ ICONV_CONST char *inptr = input;
+ size_t inbytesleft = 1;
+ char *outptr = buf;
+ size_t outbytesleft = 1;
+ size_t res = iconv (cd_88591_to_utf8,
+ &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if (res != (size_t)(-1) || outptr - buf > 1 || buf[1] != (char)0xAD)
+ result |= 4;
+ iconv_close (cd_88591_to_utf8);
+ }
+ }
+#if 0 /* This bug could be worked around by the caller. */
+ /* Test against HP-UX 11.11 bug: Positive return value instead of 0. */
+ {
+ iconv_t cd_88591_to_utf8 = iconv_open ("utf8", "iso88591");
+ if (cd_88591_to_utf8 != (iconv_t)(-1))
+ {
+ static ICONV_CONST char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
+ char buf[50];
+ ICONV_CONST char *inptr = input;
+ size_t inbytesleft = strlen (input);
+ char *outptr = buf;
+ size_t outbytesleft = sizeof (buf);
+ size_t res = iconv (cd_88591_to_utf8,
+ &inptr, &inbytesleft,
+ &outptr, &outbytesleft);
+ if ((int)res > 0)
+ result |= 8;
+ iconv_close (cd_88591_to_utf8);
+ }
+ }
+#endif
+ /* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
+ provided. */
+ if (/* Try standardized names. */
+ iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+ /* Try IRIX, OSF/1 names. */
+ && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+ /* Try AIX names. */
+ && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+ /* Try HP-UX names. */
+ && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+ result |= 16;
+ return result;
+]])],
+ [am_cv_func_iconv_works=yes], ,
+ [case "$host_os" in
+ aix* | hpux*) am_cv_func_iconv_works="guessing no" ;;
+ *) am_cv_func_iconv_works="guessing yes" ;;
+ esac])
+ test "$am_cv_func_iconv_works" = no || break
+ done
+ LIBS="$am_save_LIBS"
+ ])
+ case "$am_cv_func_iconv_works" in
+ *no) am_func_iconv=no am_cv_lib_iconv=no ;;
+ *) am_func_iconv=yes ;;
+ esac
+ else
+ am_func_iconv=no am_cv_lib_iconv=no
+ fi
+ if test "$am_func_iconv" = yes; then
+ AC_DEFINE([HAVE_ICONV], [1],
+ [Define if you have the iconv() function and it works.])
+ fi
+ if test "$am_cv_lib_iconv" = yes; then
+ AC_MSG_CHECKING([how to link with libiconv])
+ AC_MSG_RESULT([$LIBICONV])
+ else
+ dnl If $LIBICONV didn't lead to a usable library, we don't need $INCICONV
+ dnl either.
+ CPPFLAGS="$am_save_CPPFLAGS"
+ LIBICONV=
+ LTLIBICONV=
+ fi
+ AC_SUBST([LIBICONV])
+ AC_SUBST([LTLIBICONV])
+])
+
+dnl Define AM_ICONV using AC_DEFUN_ONCE for Autoconf >= 2.64, in order to
+dnl avoid warnings like
+dnl "warning: AC_REQUIRE: `AM_ICONV' was expanded before it was required".
+dnl This is tricky because of the way 'aclocal' is implemented:
+dnl - It requires defining an auxiliary macro whose name ends in AC_DEFUN.
+dnl Otherwise aclocal's initial scan pass would miss the macro definition.
+dnl - It requires a line break inside the AC_DEFUN_ONCE and AC_DEFUN expansions.
+dnl Otherwise aclocal would emit many "Use of uninitialized value $1"
+dnl warnings.
+m4_define([gl_iconv_AC_DEFUN],
+ m4_version_prereq([2.64],
+ [[AC_DEFUN_ONCE(
+ [$1], [$2])]],
+ [m4_ifdef([gl_00GNULIB],
+ [[AC_DEFUN_ONCE(
+ [$1], [$2])]],
+ [[AC_DEFUN(
+ [$1], [$2])]])]))
+gl_iconv_AC_DEFUN([AM_ICONV],
+[
+ AM_ICONV_LINK
+ if test "$am_cv_func_iconv" = yes; then
+ AC_MSG_CHECKING([for iconv declaration])
+ AC_CACHE_VAL([am_cv_proto_iconv], [
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM(
+ [[
+#include <stdlib.h>
+#include <iconv.h>
+extern
+#ifdef __cplusplus
+"C"
+#endif
+#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus)
+size_t iconv (iconv_t cd, char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);
+#else
+size_t iconv();
+#endif
+ ]],
+ [[]])],
+ [am_cv_proto_iconv_arg1=""],
+ [am_cv_proto_iconv_arg1="const"])
+ am_cv_proto_iconv="extern size_t iconv (iconv_t cd, $am_cv_proto_iconv_arg1 char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft);"])
+ am_cv_proto_iconv=`echo "[$]am_cv_proto_iconv" | tr -s ' ' | sed -e 's/( /(/'`
+ AC_MSG_RESULT([
+ $am_cv_proto_iconv])
+ AC_DEFINE_UNQUOTED([ICONV_CONST], [$am_cv_proto_iconv_arg1],
+ [Define as const if the declaration of iconv() needs const.])
+ dnl Also substitute ICONV_CONST in the gnulib generated <iconv.h>.
+ m4_ifdef([gl_ICONV_H_DEFAULTS],
+ [AC_REQUIRE([gl_ICONV_H_DEFAULTS])
+ if test -n "$am_cv_proto_iconv_arg1"; then
+ ICONV_CONST="const"
+ fi
+ ])
+ fi
+])
+# lib-ld.m4 serial 6
+dnl Copyright (C) 1996-2003, 2009-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl Subroutines of libtool.m4,
+dnl with replacements s/_*LT_PATH/AC_LIB_PROG/ and s/lt_/acl_/ to avoid
+dnl collision with libtool.m4.
+
+dnl From libtool-2.4. Sets the variable with_gnu_ld to yes or no.
+AC_DEFUN([AC_LIB_PROG_LD_GNU],
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], [acl_cv_prog_gnu_ld],
+[# I'd rather use --version here, but apparently some GNU lds only accept -v.
+case `$LD -v 2>&1 </dev/null` in
+*GNU* | *'with BFD'*)
+ acl_cv_prog_gnu_ld=yes
+ ;;
+*)
+ acl_cv_prog_gnu_ld=no
+ ;;
+esac])
+with_gnu_ld=$acl_cv_prog_gnu_ld
+])
+
+dnl From libtool-2.4. Sets the variable LD.
+AC_DEFUN([AC_LIB_PROG_LD],
+[AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+AC_ARG_WITH([gnu-ld],
+ [AS_HELP_STRING([--with-gnu-ld],
+ [assume the C compiler uses GNU ld [default=no]])],
+ [test "$withval" = no || with_gnu_ld=yes],
+ [with_gnu_ld=no])dnl
+
+# Prepare PATH_SEPARATOR.
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ # Determine PATH_SEPARATOR by trying to find /bin/sh in a PATH which
+ # contains only /bin. Note that ksh looks also at the FPATH variable,
+ # so we have to set that as well for the test.
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
+ && { (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 \
+ || PATH_SEPARATOR=';'
+ }
+fi
+
+ac_prog=ld
+if test "$GCC" = yes; then
+ # Check if gcc -print-prog-name=ld gives a path.
+ AC_MSG_CHECKING([for ld used by $CC])
+ case $host in
+ *-*-mingw*)
+ # gcc leaves a trailing carriage return which upsets mingw
+ ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;;
+ *)
+ ac_prog=`($CC -print-prog-name=ld) 2>&5` ;;
+ esac
+ case $ac_prog in
+ # Accept absolute paths.
+ [[\\/]]* | ?:[[\\/]]*)
+ re_direlt='/[[^/]][[^/]]*/\.\./'
+ # Canonicalize the pathname of ld
+ ac_prog=`echo "$ac_prog"| sed 's%\\\\%/%g'`
+ while echo "$ac_prog" | grep "$re_direlt" > /dev/null 2>&1; do
+ ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+ done
+ test -z "$LD" && LD="$ac_prog"
+ ;;
+ "")
+ # If it fails, then pretend we aren't using GCC.
+ ac_prog=ld
+ ;;
+ *)
+ # If it is relative, then search for the first ld in PATH.
+ with_gnu_ld=unknown
+ ;;
+ esac
+elif test "$with_gnu_ld" = yes; then
+ AC_MSG_CHECKING([for GNU ld])
+else
+ AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL([acl_cv_path_LD],
+[if test -z "$LD"; then
+ acl_save_ifs="$IFS"; IFS=$PATH_SEPARATOR
+ for ac_dir in $PATH; do
+ IFS="$acl_save_ifs"
+ test -z "$ac_dir" && ac_dir=.
+ if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+ acl_cv_path_LD="$ac_dir/$ac_prog"
+ # Check to see if the program is GNU ld. I'd rather use --version,
+ # but apparently some variants of GNU ld only accept -v.
+ # Break only if it was the GNU/non-GNU ld that we prefer.
+ case `"$acl_cv_path_LD" -v 2>&1 </dev/null` in
+ *GNU* | *'with BFD'*)
+ test "$with_gnu_ld" != no && break
+ ;;
+ *)
+ test "$with_gnu_ld" != yes && break
+ ;;
+ esac
+ fi
+ done
+ IFS="$acl_save_ifs"
+else
+ acl_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$acl_cv_path_LD"
+if test -n "$LD"; then
+ AC_MSG_RESULT([$LD])
+else
+ AC_MSG_RESULT([no])
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_LIB_PROG_LD_GNU
+])
+# lib-link.m4 serial 26 (gettext-0.18.2)
+dnl Copyright (C) 2001-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+AC_PREREQ([2.54])
+
+dnl AC_LIB_LINKFLAGS(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets and AC_SUBSTs the LIB${NAME} and LTLIB${NAME} variables and
+dnl augments the CPPFLAGS variable.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ pushdef([Name],[m4_translit([$1],[./+-], [____])])
+ pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+ AC_CACHE_CHECK([how to link with lib[]$1], [ac_cv_lib[]Name[]_libs], [
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+ ac_cv_lib[]Name[]_libs="$LIB[]NAME"
+ ac_cv_lib[]Name[]_ltlibs="$LTLIB[]NAME"
+ ac_cv_lib[]Name[]_cppflags="$INC[]NAME"
+ ac_cv_lib[]Name[]_prefix="$LIB[]NAME[]_PREFIX"
+ ])
+ LIB[]NAME="$ac_cv_lib[]Name[]_libs"
+ LTLIB[]NAME="$ac_cv_lib[]Name[]_ltlibs"
+ INC[]NAME="$ac_cv_lib[]Name[]_cppflags"
+ LIB[]NAME[]_PREFIX="$ac_cv_lib[]Name[]_prefix"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ AC_SUBST([LIB]NAME[_PREFIX])
+ dnl Also set HAVE_LIB[]NAME so that AC_LIB_HAVE_LINKFLAGS can reuse the
+ dnl results of this search when this library appears as a dependency.
+ HAVE_LIB[]NAME=yes
+ popdef([NAME])
+ popdef([Name])
+])
+
+dnl AC_LIB_HAVE_LINKFLAGS(name, dependencies, includes, testcode, [missing-message])
+dnl searches for libname and the libraries corresponding to explicit and
+dnl implicit dependencies, together with the specified include files and
+dnl the ability to compile and link the specified testcode. The missing-message
+dnl defaults to 'no' and may contain additional hints for the user.
+dnl If found, it sets and AC_SUBSTs HAVE_LIB${NAME}=yes and the LIB${NAME}
+dnl and LTLIB${NAME} variables and augments the CPPFLAGS variable, and
+dnl #defines HAVE_LIB${NAME} to 1. Otherwise, it sets and AC_SUBSTs
+dnl HAVE_LIB${NAME}=no and LIB${NAME} and LTLIB${NAME} to empty.
+dnl Sets and AC_SUBSTs the LIB${NAME}_PREFIX variable to nonempty if libname
+dnl was found in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_HAVE_LINKFLAGS],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ AC_REQUIRE([AC_LIB_RPATH])
+ pushdef([Name],[m4_translit([$1],[./+-], [____])])
+ pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+
+ dnl Search for lib[]Name and define LIB[]NAME, LTLIB[]NAME and INC[]NAME
+ dnl accordingly.
+ AC_LIB_LINKFLAGS_BODY([$1], [$2])
+
+ dnl Add $INC[]NAME to CPPFLAGS before performing the following checks,
+ dnl because if the user has installed lib[]Name and not disabled its use
+ dnl via --without-lib[]Name-prefix, he wants to use it.
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ AC_LIB_APPENDTOVAR([CPPFLAGS], [$INC]NAME)
+
+ AC_CACHE_CHECK([for lib[]$1], [ac_cv_lib[]Name], [
+ ac_save_LIBS="$LIBS"
+ dnl If $LIB[]NAME contains some -l options, add it to the end of LIBS,
+ dnl because these -l options might require -L options that are present in
+ dnl LIBS. -l options benefit only from the -L options listed before it.
+ dnl Otherwise, add it to the front of LIBS, because it may be a static
+ dnl library that depends on another static library that is present in LIBS.
+ dnl Static libraries benefit only from the static libraries listed after
+ dnl it.
+ case " $LIB[]NAME" in
+ *" -l"*) LIBS="$LIBS $LIB[]NAME" ;;
+ *) LIBS="$LIB[]NAME $LIBS" ;;
+ esac
+ AC_LINK_IFELSE(
+ [AC_LANG_PROGRAM([[$3]], [[$4]])],
+ [ac_cv_lib[]Name=yes],
+ [ac_cv_lib[]Name='m4_if([$5], [], [no], [[$5]])'])
+ LIBS="$ac_save_LIBS"
+ ])
+ if test "$ac_cv_lib[]Name" = yes; then
+ HAVE_LIB[]NAME=yes
+ AC_DEFINE([HAVE_LIB]NAME, 1, [Define if you have the lib][$1 library.])
+ AC_MSG_CHECKING([how to link with lib[]$1])
+ AC_MSG_RESULT([$LIB[]NAME])
+ else
+ HAVE_LIB[]NAME=no
+ dnl If $LIB[]NAME didn't lead to a usable library, we don't need
+ dnl $INC[]NAME either.
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIB[]NAME=
+ LTLIB[]NAME=
+ LIB[]NAME[]_PREFIX=
+ fi
+ AC_SUBST([HAVE_LIB]NAME)
+ AC_SUBST([LIB]NAME)
+ AC_SUBST([LTLIB]NAME)
+ AC_SUBST([LIB]NAME[_PREFIX])
+ popdef([NAME])
+ popdef([Name])
+])
+
+dnl Determine the platform dependent parameters needed to use rpath:
+dnl acl_libext,
+dnl acl_shlibext,
+dnl acl_libname_spec,
+dnl acl_library_names_spec,
+dnl acl_hardcode_libdir_flag_spec,
+dnl acl_hardcode_libdir_separator,
+dnl acl_hardcode_direct,
+dnl acl_hardcode_minus_L.
+AC_DEFUN([AC_LIB_RPATH],
+[
+ dnl Tell automake >= 1.10 to complain if config.rpath is missing.
+ m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([config.rpath])])
+ AC_REQUIRE([AC_PROG_CC]) dnl we use $CC, $GCC, $LDFLAGS
+ AC_REQUIRE([AC_LIB_PROG_LD]) dnl we use $LD, $with_gnu_ld
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use $host
+ AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT]) dnl we use $ac_aux_dir
+ AC_CACHE_CHECK([for shared library run path origin], [acl_cv_rpath], [
+ CC="$CC" GCC="$GCC" LDFLAGS="$LDFLAGS" LD="$LD" with_gnu_ld="$with_gnu_ld" \
+ ${CONFIG_SHELL-/bin/sh} "$ac_aux_dir/config.rpath" "$host" > conftest.sh
+ . ./conftest.sh
+ rm -f ./conftest.sh
+ acl_cv_rpath=done
+ ])
+ wl="$acl_cv_wl"
+ acl_libext="$acl_cv_libext"
+ acl_shlibext="$acl_cv_shlibext"
+ acl_libname_spec="$acl_cv_libname_spec"
+ acl_library_names_spec="$acl_cv_library_names_spec"
+ acl_hardcode_libdir_flag_spec="$acl_cv_hardcode_libdir_flag_spec"
+ acl_hardcode_libdir_separator="$acl_cv_hardcode_libdir_separator"
+ acl_hardcode_direct="$acl_cv_hardcode_direct"
+ acl_hardcode_minus_L="$acl_cv_hardcode_minus_L"
+ dnl Determine whether the user wants rpath handling at all.
+ AC_ARG_ENABLE([rpath],
+ [ --disable-rpath do not hardcode runtime library paths],
+ :, enable_rpath=yes)
+])
+
+dnl AC_LIB_FROMPACKAGE(name, package)
+dnl declares that libname comes from the given package. The configure file
+dnl will then not have a --with-libname-prefix option but a
+dnl --with-package-prefix option. Several libraries can come from the same
+dnl package. This declaration must occur before an AC_LIB_LINKFLAGS or similar
+dnl macro call that searches for libname.
+AC_DEFUN([AC_LIB_FROMPACKAGE],
+[
+ pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+ define([acl_frompackage_]NAME, [$2])
+ popdef([NAME])
+ pushdef([PACK],[$2])
+ pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+ define([acl_libsinpackage_]PACKUP,
+ m4_ifdef([acl_libsinpackage_]PACKUP, [m4_defn([acl_libsinpackage_]PACKUP)[, ]],)[lib$1])
+ popdef([PACKUP])
+ popdef([PACK])
+])
+
+dnl AC_LIB_LINKFLAGS_BODY(name [, dependencies]) searches for libname and
+dnl the libraries corresponding to explicit and implicit dependencies.
+dnl Sets the LIB${NAME}, LTLIB${NAME} and INC${NAME} variables.
+dnl Also, sets the LIB${NAME}_PREFIX variable to nonempty if libname was found
+dnl in ${LIB${NAME}_PREFIX}/$acl_libdirstem.
+AC_DEFUN([AC_LIB_LINKFLAGS_BODY],
+[
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ pushdef([NAME],[m4_translit([$1],[abcdefghijklmnopqrstuvwxyz./+-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+ pushdef([PACK],[m4_ifdef([acl_frompackage_]NAME, [acl_frompackage_]NAME, lib[$1])])
+ pushdef([PACKUP],[m4_translit(PACK,[abcdefghijklmnopqrstuvwxyz./+-],
+ [ABCDEFGHIJKLMNOPQRSTUVWXYZ____])])
+ pushdef([PACKLIBS],[m4_ifdef([acl_frompackage_]NAME, [acl_libsinpackage_]PACKUP, lib[$1])])
+ dnl Autoconf >= 2.61 supports dots in --with options.
+ pushdef([P_A_C_K],[m4_if(m4_version_compare(m4_defn([m4_PACKAGE_VERSION]),[2.61]),[-1],[m4_translit(PACK,[.],[_])],PACK)])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_ARG_WITH(P_A_C_K[-prefix],
+[[ --with-]]P_A_C_K[[-prefix[=DIR] search for ]PACKLIBS[ in DIR/include and DIR/lib
+ --without-]]P_A_C_K[[-prefix don't search for ]PACKLIBS[ in includedir and libdir]],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ if test "$acl_libdirstem2" != "$acl_libdirstem" \
+ && ! test -d "$withval/$acl_libdirstem"; then
+ additional_libdir="$withval/$acl_libdirstem2"
+ fi
+ fi
+ fi
+])
+ dnl Search the library and its dependencies in $additional_libdir and
+ dnl $LDFLAGS. Using breadth-first-seach.
+ LIB[]NAME=
+ LTLIB[]NAME=
+ INC[]NAME=
+ LIB[]NAME[]_PREFIX=
+ dnl HAVE_LIB${NAME} is an indicator that LIB${NAME}, LTLIB${NAME} have been
+ dnl computed. So it has to be reset here.
+ HAVE_LIB[]NAME=
+ rpathdirs=
+ ltrpathdirs=
+ names_already_handled=
+ names_next_round='$1 $2'
+ while test -n "$names_next_round"; do
+ names_this_round="$names_next_round"
+ names_next_round=
+ for name in $names_this_round; do
+ already_handled=
+ for n in $names_already_handled; do
+ if test "$n" = "$name"; then
+ already_handled=yes
+ break
+ fi
+ done
+ if test -z "$already_handled"; then
+ names_already_handled="$names_already_handled $name"
+ dnl See if it was already located by an earlier AC_LIB_LINKFLAGS
+ dnl or AC_LIB_HAVE_LINKFLAGS call.
+ uppername=`echo "$name" | sed -e 'y|abcdefghijklmnopqrstuvwxyz./+-|ABCDEFGHIJKLMNOPQRSTUVWXYZ____|'`
+ eval value=\"\$HAVE_LIB$uppername\"
+ if test -n "$value"; then
+ if test "$value" = yes; then
+ eval value=\"\$LIB$uppername\"
+ test -z "$value" || LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$value"
+ eval value=\"\$LTLIB$uppername\"
+ test -z "$value" || LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$value"
+ else
+ dnl An earlier call to AC_LIB_HAVE_LINKFLAGS has determined
+ dnl that this library doesn't exist. So just drop it.
+ :
+ fi
+ else
+ dnl Search the library lib$name in $additional_libdir and $LDFLAGS
+ dnl and the already constructed $LIBNAME/$LTLIBNAME.
+ found_dir=
+ found_la=
+ found_so=
+ found_a=
+ eval libname=\"$acl_libname_spec\" # typically: libname=lib$name
+ if test -n "$acl_shlibext"; then
+ shrext=".$acl_shlibext" # typically: shrext=.so
+ else
+ shrext=
+ fi
+ if test $use_additional = yes; then
+ dir="$additional_libdir"
+ dnl The same code as in the loop below:
+ dnl First look for a shared library.
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ dnl Then look for a static library.
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ fi
+ if test "X$found_dir" = "X"; then
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ case "$x" in
+ -L*)
+ dir=`echo "X$x" | sed -e 's/^X-L//'`
+ dnl First look for a shared library.
+ if test -n "$acl_shlibext"; then
+ if test -f "$dir/$libname$shrext"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext"
+ else
+ if test "$acl_library_names_spec" = '$libname$shrext$versuffix'; then
+ ver=`(cd "$dir" && \
+ for f in "$libname$shrext".*; do echo "$f"; done \
+ | sed -e "s,^$libname$shrext\\\\.,," \
+ | sort -t '.' -n -r -k1,1 -k2,2 -k3,3 -k4,4 -k5,5 \
+ | sed 1q ) 2>/dev/null`
+ if test -n "$ver" && test -f "$dir/$libname$shrext.$ver"; then
+ found_dir="$dir"
+ found_so="$dir/$libname$shrext.$ver"
+ fi
+ else
+ eval library_names=\"$acl_library_names_spec\"
+ for f in $library_names; do
+ if test -f "$dir/$f"; then
+ found_dir="$dir"
+ found_so="$dir/$f"
+ break
+ fi
+ done
+ fi
+ fi
+ fi
+ dnl Then look for a static library.
+ if test "X$found_dir" = "X"; then
+ if test -f "$dir/$libname.$acl_libext"; then
+ found_dir="$dir"
+ found_a="$dir/$libname.$acl_libext"
+ fi
+ fi
+ if test "X$found_dir" != "X"; then
+ if test -f "$dir/$libname.la"; then
+ found_la="$dir/$libname.la"
+ fi
+ fi
+ ;;
+ esac
+ if test "X$found_dir" != "X"; then
+ break
+ fi
+ done
+ fi
+ if test "X$found_dir" != "X"; then
+ dnl Found the library.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$found_dir -l$name"
+ if test "X$found_so" != "X"; then
+ dnl Linking with a shared library. We attempt to hardcode its
+ dnl directory into the executable's runpath, unless it's the
+ dnl standard /usr/lib.
+ if test "$enable_rpath" = no \
+ || test "X$found_dir" = "X/usr/$acl_libdirstem" \
+ || test "X$found_dir" = "X/usr/$acl_libdirstem2"; then
+ dnl No hardcoding is needed.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $found_dir"
+ fi
+ dnl The hardcoding into $LIBNAME is system dependent.
+ if test "$acl_hardcode_direct" = yes; then
+ dnl Using DIR/libNAME.so during linking hardcodes DIR into the
+ dnl resulting binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ dnl Use an explicit option to hardcode DIR into the resulting
+ dnl binary.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $found_dir"
+ fi
+ else
+ dnl Rely on "-L$found_dir".
+ dnl But don't add it if it's already contained in the LDFLAGS
+ dnl or the already constructed $LIBNAME
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$found_dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir"
+ fi
+ if test "$acl_hardcode_minus_L" != no; then
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_so"
+ else
+ dnl We cannot use $acl_hardcode_runpath_var and LD_RUN_PATH
+ dnl here, because this doesn't fit in flags passed to the
+ dnl compiler. So give up. No hardcoding. This affects only
+ dnl very old systems.
+ dnl FIXME: Not sure whether we should use
+ dnl "-L$found_dir -l$name" or "-L$found_dir $found_so"
+ dnl here.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ fi
+ else
+ if test "X$found_a" != "X"; then
+ dnl Linking with a static library.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$found_a"
+ else
+ dnl We shouldn't come here, but anyway it's good to have a
+ dnl fallback.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$found_dir -l$name"
+ fi
+ fi
+ dnl Assume the include files are nearby.
+ additional_includedir=
+ case "$found_dir" in
+ */$acl_libdirstem | */$acl_libdirstem/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem/"'*$,,'`
+ if test "$name" = '$1'; then
+ LIB[]NAME[]_PREFIX="$basedir"
+ fi
+ additional_includedir="$basedir/include"
+ ;;
+ */$acl_libdirstem2 | */$acl_libdirstem2/)
+ basedir=`echo "X$found_dir" | sed -e 's,^X,,' -e "s,/$acl_libdirstem2/"'*$,,'`
+ if test "$name" = '$1'; then
+ LIB[]NAME[]_PREFIX="$basedir"
+ fi
+ additional_includedir="$basedir/include"
+ ;;
+ esac
+ if test "X$additional_includedir" != "X"; then
+ dnl Potentially add $additional_includedir to $INCNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 3. if it's already present in $CPPFLAGS or the already
+ dnl constructed $INCNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ for x in $CPPFLAGS $INC[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $INCNAME.
+ INC[]NAME="${INC[]NAME}${INC[]NAME:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ fi
+ dnl Look for dependencies.
+ if test -n "$found_la"; then
+ dnl Read the .la file. It defines the variables
+ dnl dlname, library_names, old_library, dependency_libs, current,
+ dnl age, revision, installed, dlopen, dlpreopen, libdir.
+ save_libdir="$libdir"
+ case "$found_la" in
+ */* | *\\*) . "$found_la" ;;
+ *) . "./$found_la" ;;
+ esac
+ libdir="$save_libdir"
+ dnl We use only dependency_libs.
+ for dep in $dependency_libs; do
+ case "$dep" in
+ -L*)
+ additional_libdir=`echo "X$dep" | sed -e 's/^X-L//'`
+ dnl Potentially add $additional_libdir to $LIBNAME and $LTLIBNAME.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 3. if it's already present in $LDFLAGS or the already
+ dnl constructed $LIBNAME,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem" \
+ && test "X$additional_libdir" != "X/usr/$acl_libdirstem2"; then
+ haveit=
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem" \
+ || test "X$additional_libdir" = "X/usr/local/$acl_libdirstem2"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ haveit=
+ for x in $LDFLAGS $LIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LIBNAME.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ haveit=
+ for x in $LDFLAGS $LTLIB[]NAME; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LTLIBNAME.
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ ;;
+ -R*)
+ dir=`echo "X$dep" | sed -e 's/^X-R//'`
+ if test "$enable_rpath" != no; then
+ dnl Potentially add DIR to rpathdirs.
+ dnl The rpathdirs will be appended to $LIBNAME at the end.
+ haveit=
+ for x in $rpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ dnl Potentially add DIR to ltrpathdirs.
+ dnl The ltrpathdirs will be appended to $LTLIBNAME at the end.
+ haveit=
+ for x in $ltrpathdirs; do
+ if test "X$x" = "X$dir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ ltrpathdirs="$ltrpathdirs $dir"
+ fi
+ fi
+ ;;
+ -l*)
+ dnl Handle this in the next round.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's/^X-l//'`
+ ;;
+ *.la)
+ dnl Handle this in the next round. Throw away the .la's
+ dnl directory; it is already contained in a preceding -L
+ dnl option.
+ names_next_round="$names_next_round "`echo "X$dep" | sed -e 's,^X.*/,,' -e 's,^lib,,' -e 's,\.la$,,'`
+ ;;
+ *)
+ dnl Most likely an immediate library name.
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$dep"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }$dep"
+ ;;
+ esac
+ done
+ fi
+ else
+ dnl Didn't find the library; assume it is in the system directories
+ dnl known to the linker and runtime loader. (All the system
+ dnl directories known to the linker should also be known to the
+ dnl runtime loader, otherwise the system is severely misconfigured.)
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }-l$name"
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-l$name"
+ fi
+ fi
+ fi
+ done
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n "$acl_hardcode_libdir_separator"; then
+ dnl Weird platform: only the last -rpath option counts, the user must
+ dnl pass all path elements in one option. We can arrange that for a
+ dnl single library, but not when more than one $LIBNAMEs are used.
+ alldirs=
+ for found_dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$found_dir"
+ done
+ dnl Note: acl_hardcode_libdir_flag_spec uses $libdir and $wl.
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ else
+ dnl The -rpath options are cumulative.
+ for found_dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$found_dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ LIB[]NAME="${LIB[]NAME}${LIB[]NAME:+ }$flag"
+ done
+ fi
+ fi
+ if test "X$ltrpathdirs" != "X"; then
+ dnl When using libtool, the option that works for both libraries and
+ dnl executables is -R. The -R options are cumulative.
+ for found_dir in $ltrpathdirs; do
+ LTLIB[]NAME="${LTLIB[]NAME}${LTLIB[]NAME:+ }-R$found_dir"
+ done
+ fi
+ popdef([P_A_C_K])
+ popdef([PACKLIBS])
+ popdef([PACKUP])
+ popdef([PACK])
+ popdef([NAME])
+])
+
+dnl AC_LIB_APPENDTOVAR(VAR, CONTENTS) appends the elements of CONTENTS to VAR,
+dnl unless already present in VAR.
+dnl Works only for CPPFLAGS, not for LIB* variables because that sometimes
+dnl contains two or three consecutive elements that belong together.
+AC_DEFUN([AC_LIB_APPENDTOVAR],
+[
+ for element in [$2]; do
+ haveit=
+ for x in $[$1]; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X$element"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ [$1]="${[$1]}${[$1]:+ }$element"
+ fi
+ done
+])
+
+dnl For those cases where a variable contains several -L and -l options
+dnl referring to unknown libraries and directories, this macro determines the
+dnl necessary additional linker options for the runtime path.
+dnl AC_LIB_LINKFLAGS_FROM_LIBS([LDADDVAR], [LIBSVALUE], [USE-LIBTOOL])
+dnl sets LDADDVAR to linker options needed together with LIBSVALUE.
+dnl If USE-LIBTOOL evaluates to non-empty, linking with libtool is assumed,
+dnl otherwise linking without libtool is assumed.
+AC_DEFUN([AC_LIB_LINKFLAGS_FROM_LIBS],
+[
+ AC_REQUIRE([AC_LIB_RPATH])
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ $1=
+ if test "$enable_rpath" != no; then
+ if test -n "$acl_hardcode_libdir_flag_spec" && test "$acl_hardcode_minus_L" = no; then
+ dnl Use an explicit option to hardcode directories into the resulting
+ dnl binary.
+ rpathdirs=
+ next=
+ for opt in $2; do
+ if test -n "$next"; then
+ dir="$next"
+ dnl No need to hardcode the standard /usr/lib.
+ if test "X$dir" != "X/usr/$acl_libdirstem" \
+ && test "X$dir" != "X/usr/$acl_libdirstem2"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ next=
+ else
+ case $opt in
+ -L) next=yes ;;
+ -L*) dir=`echo "X$opt" | sed -e 's,^X-L,,'`
+ dnl No need to hardcode the standard /usr/lib.
+ if test "X$dir" != "X/usr/$acl_libdirstem" \
+ && test "X$dir" != "X/usr/$acl_libdirstem2"; then
+ rpathdirs="$rpathdirs $dir"
+ fi
+ next= ;;
+ *) next= ;;
+ esac
+ fi
+ done
+ if test "X$rpathdirs" != "X"; then
+ if test -n ""$3""; then
+ dnl libtool is used for linking. Use -R options.
+ for dir in $rpathdirs; do
+ $1="${$1}${$1:+ }-R$dir"
+ done
+ else
+ dnl The linker is used for linking directly.
+ if test -n "$acl_hardcode_libdir_separator"; then
+ dnl Weird platform: only the last -rpath option counts, the user
+ dnl must pass all path elements in one option.
+ alldirs=
+ for dir in $rpathdirs; do
+ alldirs="${alldirs}${alldirs:+$acl_hardcode_libdir_separator}$dir"
+ done
+ acl_save_libdir="$libdir"
+ libdir="$alldirs"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ $1="$flag"
+ else
+ dnl The -rpath options are cumulative.
+ for dir in $rpathdirs; do
+ acl_save_libdir="$libdir"
+ libdir="$dir"
+ eval flag=\"$acl_hardcode_libdir_flag_spec\"
+ libdir="$acl_save_libdir"
+ $1="${$1}${$1:+ }$flag"
+ done
+ fi
+ fi
+ fi
+ fi
+ fi
+ AC_SUBST([$1])
+])
+# lib-prefix.m4 serial 7 (gettext-0.18)
+dnl Copyright (C) 2001-2005, 2008-2013 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+
+dnl AC_LIB_ARG_WITH is synonymous to AC_ARG_WITH in autoconf-2.13, and
+dnl similar to AC_ARG_WITH in autoconf 2.52...2.57 except that is doesn't
+dnl require excessive bracketing.
+ifdef([AC_HELP_STRING],
+[AC_DEFUN([AC_LIB_ARG_WITH], [AC_ARG_WITH([$1],[[$2]],[$3],[$4])])],
+[AC_DEFUN([AC_][LIB_ARG_WITH], [AC_ARG_WITH([$1],[$2],[$3],[$4])])])
+
+dnl AC_LIB_PREFIX adds to the CPPFLAGS and LDFLAGS the flags that are needed
+dnl to access previously installed libraries. The basic assumption is that
+dnl a user will want packages to use other packages he previously installed
+dnl with the same --prefix option.
+dnl This macro is not needed if only AC_LIB_LINKFLAGS is used to locate
+dnl libraries, but is otherwise very convenient.
+AC_DEFUN([AC_LIB_PREFIX],
+[
+ AC_BEFORE([$0], [AC_LIB_LINKFLAGS])
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_REQUIRE([AC_LIB_PREPARE_MULTILIB])
+ AC_REQUIRE([AC_LIB_PREPARE_PREFIX])
+ dnl By default, look in $includedir and $libdir.
+ use_additional=yes
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ AC_LIB_ARG_WITH([lib-prefix],
+[ --with-lib-prefix[=DIR] search for libraries in DIR/include and DIR/lib
+ --without-lib-prefix don't search for libraries in includedir and libdir],
+[
+ if test "X$withval" = "Xno"; then
+ use_additional=no
+ else
+ if test "X$withval" = "X"; then
+ AC_LIB_WITH_FINAL_PREFIX([
+ eval additional_includedir=\"$includedir\"
+ eval additional_libdir=\"$libdir\"
+ ])
+ else
+ additional_includedir="$withval/include"
+ additional_libdir="$withval/$acl_libdirstem"
+ fi
+ fi
+])
+ if test $use_additional = yes; then
+ dnl Potentially add $additional_includedir to $CPPFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/include,
+ dnl 2. if it's already present in $CPPFLAGS,
+ dnl 3. if it's /usr/local/include and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_includedir" != "X/usr/include"; then
+ haveit=
+ for x in $CPPFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-I$additional_includedir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_includedir" = "X/usr/local/include"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux* | gnu* | k*bsd*-gnu) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_includedir"; then
+ dnl Really add $additional_includedir to $CPPFLAGS.
+ CPPFLAGS="${CPPFLAGS}${CPPFLAGS:+ }-I$additional_includedir"
+ fi
+ fi
+ fi
+ fi
+ dnl Potentially add $additional_libdir to $LDFLAGS.
+ dnl But don't add it
+ dnl 1. if it's the standard /usr/lib,
+ dnl 2. if it's already present in $LDFLAGS,
+ dnl 3. if it's /usr/local/lib and we are using GCC on Linux,
+ dnl 4. if it doesn't exist as a directory.
+ if test "X$additional_libdir" != "X/usr/$acl_libdirstem"; then
+ haveit=
+ for x in $LDFLAGS; do
+ AC_LIB_WITH_FINAL_PREFIX([eval x=\"$x\"])
+ if test "X$x" = "X-L$additional_libdir"; then
+ haveit=yes
+ break
+ fi
+ done
+ if test -z "$haveit"; then
+ if test "X$additional_libdir" = "X/usr/local/$acl_libdirstem"; then
+ if test -n "$GCC"; then
+ case $host_os in
+ linux*) haveit=yes;;
+ esac
+ fi
+ fi
+ if test -z "$haveit"; then
+ if test -d "$additional_libdir"; then
+ dnl Really add $additional_libdir to $LDFLAGS.
+ LDFLAGS="${LDFLAGS}${LDFLAGS:+ }-L$additional_libdir"
+ fi
+ fi
+ fi
+ fi
+ fi
+])
+
+dnl AC_LIB_PREPARE_PREFIX creates variables acl_final_prefix,
+dnl acl_final_exec_prefix, containing the values to which $prefix and
+dnl $exec_prefix will expand at the end of the configure script.
+AC_DEFUN([AC_LIB_PREPARE_PREFIX],
+[
+ dnl Unfortunately, prefix and exec_prefix get only finally determined
+ dnl at the end of configure.
+ if test "X$prefix" = "XNONE"; then
+ acl_final_prefix="$ac_default_prefix"
+ else
+ acl_final_prefix="$prefix"
+ fi
+ if test "X$exec_prefix" = "XNONE"; then
+ acl_final_exec_prefix='${prefix}'
+ else
+ acl_final_exec_prefix="$exec_prefix"
+ fi
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ eval acl_final_exec_prefix=\"$acl_final_exec_prefix\"
+ prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_WITH_FINAL_PREFIX([statement]) evaluates statement, with the
+dnl variables prefix and exec_prefix bound to the values they will have
+dnl at the end of the configure script.
+AC_DEFUN([AC_LIB_WITH_FINAL_PREFIX],
+[
+ acl_save_prefix="$prefix"
+ prefix="$acl_final_prefix"
+ acl_save_exec_prefix="$exec_prefix"
+ exec_prefix="$acl_final_exec_prefix"
+ $1
+ exec_prefix="$acl_save_exec_prefix"
+ prefix="$acl_save_prefix"
+])
+
+dnl AC_LIB_PREPARE_MULTILIB creates
+dnl - a variable acl_libdirstem, containing the basename of the libdir, either
+dnl "lib" or "lib64" or "lib/64",
+dnl - a variable acl_libdirstem2, as a secondary possible value for
+dnl acl_libdirstem, either the same as acl_libdirstem or "lib/sparcv9" or
+dnl "lib/amd64".
+AC_DEFUN([AC_LIB_PREPARE_MULTILIB],
+[
+ dnl There is no formal standard regarding lib and lib64.
+ dnl On glibc systems, the current practice is that on a system supporting
+ dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
+ dnl $prefix/lib64 and 32-bit libraries go under $prefix/lib. We determine
+ dnl the compiler's default mode by looking at the compiler's library search
+ dnl path. If at least one of its elements ends in /lib64 or points to a
+ dnl directory whose absolute pathname ends in /lib64, we assume a 64-bit ABI.
+ dnl Otherwise we use the default, namely "lib".
+ dnl On Solaris systems, the current practice is that on a system supporting
+ dnl 32-bit and 64-bit instruction sets or ABIs, 64-bit libraries go under
+ dnl $prefix/lib/64 (which is a symlink to either $prefix/lib/sparcv9 or
+ dnl $prefix/lib/amd64) and 32-bit libraries go under $prefix/lib.
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ acl_libdirstem=lib
+ acl_libdirstem2=
+ case "$host_os" in
+ solaris*)
+ dnl See Solaris 10 Software Developer Collection > Solaris 64-bit Developer's Guide > The Development Environment
+ dnl <http://docs.sun.com/app/docs/doc/816-5138/dev-env?l=en&a=view>.
+ dnl "Portable Makefiles should refer to any library directories using the 64 symbolic link."
+ dnl But we want to recognize the sparcv9 or amd64 subdirectory also if the
+ dnl symlink is missing, so we set acl_libdirstem2 too.
+ AC_CACHE_CHECK([for 64-bit host], [gl_cv_solaris_64bit],
+ [AC_EGREP_CPP([sixtyfour bits], [
+#ifdef _LP64
+sixtyfour bits
+#endif
+ ], [gl_cv_solaris_64bit=yes], [gl_cv_solaris_64bit=no])
+ ])
+ if test $gl_cv_solaris_64bit = yes; then
+ acl_libdirstem=lib/64
+ case "$host_cpu" in
+ sparc*) acl_libdirstem2=lib/sparcv9 ;;
+ i*86 | x86_64) acl_libdirstem2=lib/amd64 ;;
+ esac
+ fi
+ ;;
+ *)
+ searchpath=`(LC_ALL=C $CC -print-search-dirs) 2>/dev/null | sed -n -e 's,^libraries: ,,p' | sed -e 's,^=,,'`
+ if test -n "$searchpath"; then
+ acl_save_IFS="${IFS= }"; IFS=":"
+ for searchdir in $searchpath; do
+ if test -d "$searchdir"; then
+ case "$searchdir" in
+ */lib64/ | */lib64 ) acl_libdirstem=lib64 ;;
+ */../ | */.. )
+ # Better ignore directories of this form. They are misleading.
+ ;;
+ *) searchdir=`cd "$searchdir" && pwd`
+ case "$searchdir" in
+ */lib64 ) acl_libdirstem=lib64 ;;
+ esac ;;
+ esac
+ fi
+ done
+ IFS="$acl_save_IFS"
+ fi
+ ;;
+ esac
+ test -n "$acl_libdirstem2" || acl_libdirstem2="$acl_libdirstem"
+])
diff --git a/genqrcode/autogen.sh b/genqrcode/autogen.sh
new file mode 100755
index 0000000000..ab14d6c040
--- /dev/null
+++ b/genqrcode/autogen.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+set -e
+
+if [ `uname -s` = Darwin ]; then
+ LIBTOOLIZE=glibtoolize
+else
+ LIBTOOLIZE=libtoolize
+fi
+
+ACLOCAL_OPT=""
+if [ -d /usr/local/share/aclocal ]; then
+ ACLOCAL_OPT="-I /usr/local/share/aclocal"
+elif [ -d /opt/local/share/aclocal ]; then
+ ACLOCAL_OPT="-I /opt/local/share/aclocal"
+elif [ -d /usr/share/aclocal ]; then
+ ACLOCAL_OPT="-I /usr/share/aclocal"
+fi
+
+if [ ! -d use ]; then
+ mkdir use
+fi
+
+if [ ! -d m4 ]; then
+ mkdir m4
+fi
+
+autoheader
+
+aclocal $ACLOCAL_OPT
+
+$LIBTOOLIZE --automake --copy
+automake --add-missing --copy
+
+autoconf
diff --git a/genqrcode/bitstream.c b/genqrcode/bitstream.c
new file mode 100644
index 0000000000..f620050dc6
--- /dev/null
+++ b/genqrcode/bitstream.c
@@ -0,0 +1,231 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Binary sequence class.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "bitstream.h"
+
+#define DEFAULT_BUFSIZE (128)
+
+BitStream *BitStream_new(void)
+{
+ BitStream *bstream;
+
+ bstream = (BitStream *)malloc(sizeof(BitStream));
+ if(bstream == NULL) return NULL;
+
+ bstream->length = 0;
+ bstream->data = (unsigned char *)malloc(DEFAULT_BUFSIZE);
+ if(bstream->data == NULL) {
+ free(bstream);
+ return NULL;
+ }
+ bstream->datasize = DEFAULT_BUFSIZE;
+
+ return bstream;
+}
+
+#ifdef WITH_TESTS
+BitStream *BitStream_newWithBits(size_t size, unsigned char *bits)
+{
+ BitStream *bstream;
+
+ if(size == 0) return BitStream_new();
+
+ bstream = (BitStream *)malloc(sizeof(BitStream));
+ if(bstream == NULL) return NULL;
+
+ bstream->data = (unsigned char *)malloc(size);
+ if(bstream->data == NULL) {
+ free(bstream);
+ return NULL;
+ }
+
+ bstream->length = size;
+ bstream->datasize = size;
+ memcpy(bstream->data, bits, size);
+
+ return bstream;
+}
+#endif
+
+static int BitStream_expand(BitStream *bstream)
+{
+ unsigned char *data;
+
+ data = (unsigned char *)realloc(bstream->data, bstream->datasize * 2);
+ if(data == NULL) {
+ return -1;
+ }
+
+ bstream->data = data;
+ bstream->datasize *= 2;
+
+ return 0;
+}
+
+static void BitStream_writeNum(unsigned char *dest, size_t bits, unsigned int num)
+{
+ unsigned int mask;
+ size_t i;
+ unsigned char *p;
+
+ p = dest;
+ mask = 1U << (bits - 1);
+ for(i = 0; i < bits; i++) {
+ if(num & mask) {
+ *p = 1;
+ } else {
+ *p = 0;
+ }
+ p++;
+ mask = mask >> 1;
+ }
+}
+
+static void BitStream_writeBytes(unsigned char *dest, size_t size, unsigned char *data)
+{
+ unsigned char mask;
+ size_t i, j;
+ unsigned char *p;
+
+ p = dest;
+ for(i = 0; i < size; i++) {
+ mask = 0x80;
+ for(j = 0; j < 8; j++) {
+ if(data[i] & mask) {
+ *p = 1;
+ } else {
+ *p = 0;
+ }
+ p++;
+ mask = mask >> 1;
+ }
+ }
+}
+
+int BitStream_append(BitStream *bstream, BitStream *arg)
+{
+ int ret;
+
+ if(arg == NULL) {
+ return -1;
+ }
+ if(arg->length == 0) {
+ return 0;
+ }
+
+ while(bstream->length + arg->length > bstream->datasize) {
+ ret = BitStream_expand(bstream);
+ if(ret < 0) return ret;
+ }
+
+ memcpy(bstream->data + bstream->length, arg->data, arg->length);
+ bstream->length += arg->length;
+
+ return 0;
+}
+
+int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num)
+{
+ int ret;
+
+ if(bits == 0) return 0;
+
+ while(bstream->datasize - bstream->length < bits) {
+ ret = BitStream_expand(bstream);
+ if(ret < 0) return ret;
+ }
+ BitStream_writeNum(bstream->data + bstream->length, bits, num);
+ bstream->length += bits;
+
+ return 0;
+}
+
+int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data)
+{
+ int ret;
+
+ if(size == 0) return 0;
+
+ while(bstream->datasize - bstream->length < size * 8) {
+ ret = BitStream_expand(bstream);
+ if(ret < 0) return ret;
+ }
+ BitStream_writeBytes(bstream->data + bstream->length, size, data);
+ bstream->length += size * 8;
+
+ return 0;
+}
+
+unsigned char *BitStream_toByte(BitStream *bstream)
+{
+ size_t i, j, size, bytes, oddbits;
+ unsigned char *data, v;
+ unsigned char *p;
+
+ size = BitStream_size(bstream);
+ if(size == 0) {
+ return NULL;
+ }
+ data = (unsigned char *)malloc((size + 7) / 8);
+ if(data == NULL) {
+ return NULL;
+ }
+
+ bytes = size / 8;
+
+ p = bstream->data;
+ for(i = 0; i < bytes; i++) {
+ v = 0;
+ for(j = 0; j < 8; j++) {
+ v = (unsigned char)(v << 1);
+ v |= *p;
+ p++;
+ }
+ data[i] = v;
+ }
+ oddbits = size & 7;
+ if(oddbits > 0) {
+ v = 0;
+ for(j = 0; j < oddbits; j++) {
+ v = (unsigned char)(v << 1);
+ v |= *p;
+ p++;
+ }
+ data[bytes] = (unsigned char)(v << (8 - oddbits));
+ }
+
+ return data;
+}
+
+void BitStream_free(BitStream *bstream)
+{
+ if(bstream != NULL) {
+ free(bstream->data);
+ free(bstream);
+ }
+}
diff --git a/genqrcode/bitstream.h b/genqrcode/bitstream.h
new file mode 100644
index 0000000000..70f3e1dfc5
--- /dev/null
+++ b/genqrcode/bitstream.h
@@ -0,0 +1,43 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Binary sequence class.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef BITSTREAM_H
+#define BITSTREAM_H
+
+typedef struct {
+ size_t length;
+ size_t datasize;
+ unsigned char *data;
+} BitStream;
+
+extern BitStream *BitStream_new(void);
+#ifdef WITH_TESTS
+extern BitStream *BitStream_newWithBits(size_t size, unsigned char *bits);
+#endif
+extern int BitStream_append(BitStream *bstream, BitStream *arg);
+extern int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num);
+extern int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data);
+#define BitStream_size(__bstream__) (__bstream__->length)
+#define BitStream_reset(__bstream__) (__bstream__->length = 0)
+extern unsigned char *BitStream_toByte(BitStream *bstream);
+extern void BitStream_free(BitStream *bstream);
+
+#endif /* BITSTREAM_H */
diff --git a/genqrcode/cmake/FindIconv.cmake b/genqrcode/cmake/FindIconv.cmake
new file mode 100644
index 0000000000..fede82a093
--- /dev/null
+++ b/genqrcode/cmake/FindIconv.cmake
@@ -0,0 +1,115 @@
+include(CheckFunctionExists)
+
+set(_ICONV_SEARCHES)
+
+# Search ICONV_DIR first if it is set.
+if(NOT ICONV_DIR AND ENV{ICONV_DIR})
+ set(ICONV_DIR $ENV{ICONV_DIR})
+endif()
+
+if(ICONV_DIR)
+ set(_ICONV_DIR_SEARCH PATHS ${ICONV_DIR} NO_DEFAULT_PATH)
+ list(APPEND _ICONV_SEARCHES _ICONV_DIR_SEARCH)
+endif()
+
+# Normal search.
+set(_ICONV_SEARCH_NORMAL
+ PATHS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\GnuWin32\\Iconv;InstallPath]"
+ "$ENV{PROGRAMFILES}/iconv"
+ ENV CPATH
+ ENV C_INCLUDE_PATH
+ ENV CPLUS_INCLUDE_PATH
+ ENV LIBRARY_PATH)
+list(APPEND _ICONV_SEARCHES _ICONV_SEARCH_NORMAL)
+
+set(ICONV_NAMES iconv iconv2 libiconv iconv64)
+set(ICONV_NAMES_DEBUG iconvd iconv64d)
+
+# Try each search configuration.
+foreach(search ${_ICONV_SEARCHES})
+ find_path(ICONV_INCLUDE_DIR NAMES iconv.h ${${search}} PATH_SUFFIXES include)
+endforeach()
+
+# Allow ICONV_LIBRARY to be set manually, as the location of the iconv library
+if(NOT ICONV_LIBRARY)
+ foreach(search ${_ICONV_SEARCHES})
+ find_library(ICONV_LIBRARY_RELEASE NAMES ${ICONV_NAMES} ${${search}} PATH_SUFFIXES lib)
+ find_library(ICONV_LIBRARY_DEBUG NAMES ${ICONV_NAMES_DEBUG} ${${search}} PATH_SUFFIXES lib)
+ endforeach()
+
+ include(SelectLibraryConfigurations)
+ select_library_configurations(ICONV)
+endif()
+
+unset(ICONV_NAMES)
+unset(ICONV_NAMES_DEBUG)
+
+if(ICONV_INCLUDE_DIR AND EXISTS "${ICONV_INCLUDE_DIR}/iconv.h")
+ file(STRINGS "${ICONV_INCLUDE_DIR}/iconv.h" ICONV_H REGEX "^#define _LIBICONV_VERSION 0x([0-9]+)")
+ string(REGEX MATCH "q#define _LIBICONV_VERSION 0x([0-9][0-9])([0-9][0-9])?([0-9][0-9])?.*" temp_match "${ICONV_H}")
+ unset(temp_match)
+ if(CMAKE_MATCH_0)
+ set(ICONV_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(ICONV_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(ICONV_VERSION_PATCH "${CMAKE_MATCH_3}")
+ string(REGEX REPLACE "0*([1-9][0-9]*).*" "\\1" ICONV_VERSION_MAJOR "${ICONV_VERSION_MAJOR}")
+ string(REGEX REPLACE "0*([1-9][0-9]*).*" "\\1" ICONV_VERSION_MINOR "${ICONV_VERSION_MINOR}")
+ string(REGEX REPLACE "0*([1-9][0-9]*).*" "\\1" ICONV_VERSION_PATCH "${ICONV_VERSION_PATCH}")
+
+ set(ICONV_VERSION_STRING "${ICONV_VERSION_MAJOR}.${ICONV_VERSION_MINOR}")
+ if(ICONV_VERSION_PATCH)
+ set(ICONV_VERSION_STRING "${ICONV_VERSION_STRING}.${ICONV_VERSION_PATCH}")
+ endif()
+ endif()
+endif()
+
+check_function_exists(iconv_open ICONV_IN_GLIBC)
+
+set(ICONV_FOUND_ANY FALSE)
+if(ICONV_IN_GLIBC OR ICONV_LIBRARY)
+ set(ICONV_FOUND_ANY TRUE)
+endif()
+
+# handle the QUIETLY and REQUIRED arguments and set ICONV_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(ICONV
+ REQUIRED_VARS ICONV_FOUND_ANY ICONV_INCLUDE_DIR
+ VERSION_VAR ICONV_VERSION_STRING)
+
+mark_as_advanced(ICONV_LIBRARY ICONV_INCLUDE_DIR)
+
+if(NOT ICONV_FOUND)
+ return()
+endif()
+
+set(ICONV_INCLUDE_DIRS ${ICONV_INCLUDE_DIR})
+
+if(NOT ICONV_LIBRARIES)
+ set(ICONV_LIBRARIES ${ICONV_LIBRARY})
+endif()
+
+if(ICONV_LIBRARY AND NOT TARGET ICONV::ICONV)
+ add_library(ICONV::ICONV UNKNOWN IMPORTED)
+ set_target_properties(ICONV::ICONV PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${ICONV_INCLUDE_DIRS}"
+ IMPORTED_LOCATION "${ICONV_LIBRARY}")
+
+ if(ICONV_LIBRARY_RELEASE)
+ set_property(TARGET ICONV::ICONV APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS RELEASE)
+ set_target_properties(ICONV::ICONV PROPERTIES
+ IMPORTED_LOCATION_RELEASE "${ICONV_LIBRARY_RELEASE}")
+ endif()
+
+ if(ICONV_LIBRARY_DEBUG)
+ set_property(TARGET ICONV::ICONV APPEND PROPERTY
+ IMPORTED_CONFIGURATIONS DEBUG)
+ set_target_properties(ICONV::ICONV PROPERTIES
+ IMPORTED_LOCATION_DEBUG "${ICONV_LIBRARY_DEBUG}")
+ endif()
+elseif(NOT TARGET ICONV::ICONV)
+ add_library(ICONV::ICONV INTERFACE IMPORTED)
+ set_target_properties(ICONV::ICONV PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${ICONV_INCLUDE_DIRS}")
+endif()
diff --git a/genqrcode/configure.ac b/genqrcode/configure.ac
new file mode 100644
index 0000000000..bc1d024d9b
--- /dev/null
+++ b/genqrcode/configure.ac
@@ -0,0 +1,153 @@
+m4_define([__MAJOR_VERSION], [4])dnl
+m4_define([__MINOR_VERSION], [1])dnl
+m4_define([__MICRO_VERSION], [1])dnl
+m4_define([__VERSION], [__MAJOR_VERSION.__MINOR_VERSION.__MICRO_VERSION])dnl
+AC_INIT(QRencode, __VERSION)
+
+MAJOR_VERSION=__MAJOR_VERSION
+MINOR_VERSION=__MINOR_VERSION
+MICRO_VERSION=__MICRO_VERSION
+AC_SUBST(MAJOR_VERSION)
+AC_SUBST(MINOR_VERSION)
+AC_SUBST(MICRO_VERSION)
+AC_DEFINE_UNQUOTED([MAJOR_VERSION], [$MAJOR_VERSION], [Major version number])
+AC_DEFINE_UNQUOTED([MINOR_VERSION], [$MINOR_VERSION], [Minor version number])
+AC_DEFINE_UNQUOTED([MICRO_VERSION], [$MICRO_VERSION], [Micro version number])
+
+AC_CONFIG_SRCDIR([qrencode.c])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_AUX_DIR(use)
+AC_CONFIG_MACRO_DIR([m4])
+AC_CANONICAL_HOST
+AC_CANONICAL_TARGET
+
+AM_INIT_AUTOMAKE
+
+AC_DISABLE_STATIC
+AC_C_CONST
+AC_C_INLINE
+AC_HEADER_STDC
+AC_CHECK_HEADERS(sys/time.h)
+
+LT_INIT
+AC_PROG_CC
+AM_PROG_CC_C_O
+AC_PROG_INSTALL
+AC_PROG_LIBTOOL
+PKG_PROG_PKG_CONFIG
+
+case "${target}" in
+*-*-mingw*)
+ mingw=yes
+esac
+AM_CONDITIONAL(MINGW, [test "x$mingw" = "xyes" ])
+
+AC_CONFIG_FILES([Makefile libqrencode.pc tests/Makefile qrencode.1])
+
+AC_CHECK_FUNCS([strdup])
+
+dnl --enable-thread-safety
+AC_ARG_ENABLE([thread-safety], [AS_HELP_STRING([--enable-thread-safety], [make the library thread-safe. [default=yes]])],
+ [], [enable_thread_safety=yes])
+
+if test x$enable_thread_safety = xyes; then
+ AC_CHECK_LIB([pthread], [pthread_mutex_init], [AC_SUBST([LIBPTHREAD], [-lpthread])])
+fi
+AM_CONDITIONAL([HAVE_LIBPTHREAD], [test "x$ac_cv_lib_pthread_pthread_mutex_init" = "xyes" ])
+# FIXME: isn't it able to integrate the followings to AC_CHECK_LIB?
+if test x$ac_cv_lib_pthread_pthread_mutex_init = xyes ; then
+ AC_DEFINE([HAVE_LIBPTHREAD], [1], [Define to 1 if using pthread is enabled.])
+ CFLAGS="$CFLAGS -pthread"
+fi
+
+AC_ARG_WITH(png,
+ [AC_HELP_STRING([--without-png],
+ [disable PNG support])],
+ [with_png=$withval], [with_png=yes])
+
+dnl --with-tools
+AC_ARG_WITH([tools], [AS_HELP_STRING([--with-tools], [build utility tools [default=yes]])],
+ [build_tools=$withval], [build_tools=yes])
+
+AM_CONDITIONAL(BUILD_TOOLS, [test "x$build_tools" = "xyes" ])
+if test x$build_tools = xyes && test x$with_png = xyes ; then
+ PKG_CHECK_MODULES(png, "libpng", [AC_DEFINE([HAVE_PNG], [1], [Define to 1 if using libpng is enabled.])], [AC_DEFINE([HAVE_PNG], [0])])
+ if test "x$png_CFLAGS" = "x" && test x$with_png = xyes ; then
+ echo "
+!!!!!!!!!!
+LIBPNG is required to build the utility tools. Temporarily disabled.
+!!!!!!!!!!
+"
+ fi
+fi
+AM_CONDITIONAL(HAVE_PNG, [test "x$png_CFLAGS" != "x" ])
+
+dnl --with-tests
+AC_ARG_WITH([tests], [AS_HELP_STRING([--with-tests], [build tests [default=no]])],
+ [build_tests=$withval], [build_tests=no])
+
+AM_CONDITIONAL(BUILD_TESTS, [test "x$build_tests" = "xyes" ])
+AH_VERBATIM([tests],
+[/* Define to 'static' if no test programs will be compiled. */
+#define STATIC_IN_RELEASE static
+#undef WITH_TESTS
+ ])
+if test x$build_tests = xyes ; then
+echo "#define STATIC_IN_RELEASE" >>confdefs.h
+echo "#define WITH_TESTS 1" >>confdefs.h
+else
+echo "#define STATIC_IN_RELEASE static" >>confdefs.h
+echo "/* #undef WITH_TESTS */" >>confdefs.h
+fi
+
+if test x$build_tests = xyes ; then
+ SDL_REQUIRED_VERSION=2.0.0
+ PKG_CHECK_MODULES(SDL, [sdl2 >= $SDL_REQUIRED_VERSION], [AC_DEFINE([HAVE_SDL], [1], [Define to 1 if using SDL is enabled.])], [AC_DEFINE([HAVE_SDL], [0])])
+ AM_ICONV_LINK
+fi
+AM_CONDITIONAL(HAVE_SDL, [test "x$SDL_CFLAGS" != "x" ])
+
+
+dnl --enable-gprof
+AC_ARG_ENABLE([gprof], [AS_HELP_STRING([--enable-gprof], [generate extra code to write profile information suitable for gprof [default=no]])],
+ [], [enable_gprof=no])
+
+if test x$enable_gprof = xyes; then
+ CFLAGS="$CFLAGS -g -pg"
+fi
+
+
+dnl --enable-gcov
+AC_ARG_ENABLE([gcov], [AS_HELP_STRING([--enable-gcov], [generate extra code to write coverage information suitable for gcov [default=no]])],
+ [], [enable_gcov=no])
+
+if test x$enable_gcov = xyes; then
+ CFLAGS="$CFLAGS --coverage"
+fi
+
+
+dnl --enable-asan
+AC_ARG_ENABLE([asan], [AS_HELP_STRING([--enable-asan], [use AddressSanitizer [default=no]])],
+ [], [enable_asan=no])
+
+if test x$enable_asan = xyes; then
+ CFLAGS="$CFLAGS -fsanitize=address -fno-omit-frame-pointer"
+ LDFLAGS="$LDFLAGS -fsanitize=address"
+fi
+
+
+dnl set CFLAGS
+CFLAGS="-Wall $CFLAGS"
+
+
+AC_OUTPUT
+
+echo ""
+echo "Options used to compile and link:"
+echo " CC = $CC"
+echo " CFLAGS = $CFLAGS"
+echo " CPPFLAGS = $CPPFLAGS"
+echo " CXX = $CXX"
+echo " CXXFLAGS = $CXXFLAGS"
+echo " LDFLAGS = $LDFLAGS"
+echo ""
diff --git a/genqrcode/libqrencode.pc.in b/genqrcode/libqrencode.pc.in
new file mode 100644
index 0000000000..ef6afbdf21
--- /dev/null
+++ b/genqrcode/libqrencode.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libqrencode
+Description: A QR Code encoding library
+Version: @VERSION@
+Libs: -L${libdir} -lqrencode
+Libs.private: @LIBPTHREAD@
+Cflags: -I${includedir}
diff --git a/genqrcode/makeREADME.sh b/genqrcode/makeREADME.sh
new file mode 100755
index 0000000000..d42e152d27
--- /dev/null
+++ b/genqrcode/makeREADME.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+sed '/^```$/d
+/badge\.svg/{N;d;}
+/^\*\*Attention/d
+s/DWITH\\_TESTS/DWITH_TESTS/
+1 {
+ s/^# //
+}
+' README.md > README
diff --git a/genqrcode/mask.c b/genqrcode/mask.c
new file mode 100644
index 0000000000..f812132033
--- /dev/null
+++ b/genqrcode/mask.c
@@ -0,0 +1,356 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Masking.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
+#include "qrencode.h"
+#include "qrspec.h"
+#include "mask.h"
+
+STATIC_IN_RELEASE int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level)
+{
+ unsigned int format;
+ unsigned char v;
+ int i;
+ int blacks = 0;
+
+ format = QRspec_getFormatInfo(mask, level);
+
+ for(i = 0; i < 8; i++) {
+ if(format & 1) {
+ blacks += 2;
+ v = 0x85;
+ } else {
+ v = 0x84;
+ }
+ frame[width * 8 + width - 1 - i] = v;
+ if(i < 6) {
+ frame[width * i + 8] = v;
+ } else {
+ frame[width * (i + 1) + 8] = v;
+ }
+ format= format >> 1;
+ }
+ for(i = 0; i < 7; i++) {
+ if(format & 1) {
+ blacks += 2;
+ v = 0x85;
+ } else {
+ v = 0x84;
+ }
+ frame[width * (width - 7 + i) + 8] = v;
+ if(i == 0) {
+ frame[width * 8 + 7] = v;
+ } else {
+ frame[width * 8 + 6 - i] = v;
+ }
+ format= format >> 1;
+ }
+
+ return blacks;
+}
+
+/**
+ * Penalty coefficients.
+ * See Section 8.8.2, p.45, JIS X0510:2004.
+ */
+#define N1 (3)
+#define N2 (3)
+#define N3 (40)
+#define N4 (10)
+
+#define MASKMAKER(__exp__) \
+ int x, y;\
+ int b = 0;\
+\
+ for(y = 0; y < width; y++) {\
+ for(x = 0; x < width; x++) {\
+ if(*s & 0x80) {\
+ *d = *s;\
+ } else {\
+ *d = *s ^ ((__exp__) == 0);\
+ }\
+ b += (int)(*d & 1);\
+ s++; d++;\
+ }\
+ }\
+ return b;
+
+static int Mask_mask0(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER((x+y)&1)
+}
+
+static int Mask_mask1(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER(y&1)
+}
+
+static int Mask_mask2(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER(x%3)
+}
+
+static int Mask_mask3(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER((x+y)%3)
+}
+
+static int Mask_mask4(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER(((y/2)+(x/3))&1)
+}
+
+static int Mask_mask5(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER(((x*y)&1)+(x*y)%3)
+}
+
+static int Mask_mask6(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER((((x*y)&1)+(x*y)%3)&1)
+}
+
+static int Mask_mask7(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER((((x*y)%3)+((x+y)&1))&1)
+}
+
+#define maskNum (8)
+typedef int MaskMaker(int, const unsigned char *, unsigned char *);
+static MaskMaker *maskMakers[maskNum] = {
+ Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3,
+ Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7
+};
+
+#ifdef WITH_TESTS
+unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask)
+{
+ unsigned char *masked;
+
+ masked = (unsigned char *)malloc((size_t)(width * width));
+ if(masked == NULL) return NULL;
+
+ maskMakers[mask](width, frame, masked);
+
+ return masked;
+}
+#endif
+
+unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level)
+{
+ unsigned char *masked;
+
+ if(mask < 0 || mask >= maskNum) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ masked = (unsigned char *)malloc((size_t)(width * width));
+ if(masked == NULL) return NULL;
+
+ maskMakers[mask](width, frame, masked);
+ Mask_writeFormatInformation(width, masked, mask, level);
+
+ return masked;
+}
+
+
+//static int n1;
+//static int n2;
+//static int n3;
+//static int n4;
+
+STATIC_IN_RELEASE int Mask_calcN1N3(int length, int *runLength)
+{
+ int i;
+ int penalty = 0;
+ int fact;
+
+ for(i = 0; i < length; i++) {
+ if(runLength[i] >= 5) {
+ penalty += N1 + (runLength[i] - 5);
+ //n1 += N1 + (runLength[i] - 5);
+ }
+ if(i & 1) {
+ if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) {
+ fact = runLength[i] / 3;
+ if(runLength[i-2] == fact &&
+ runLength[i-1] == fact &&
+ runLength[i+1] == fact &&
+ runLength[i+2] == fact) {
+ if(i == 3 || runLength[i-3] >= 4 * fact) {
+ penalty += N3;
+ //n3 += N3;
+ } else if(i+4 >= length || runLength[i+3] >= 4 * fact) {
+ penalty += N3;
+ //n3 += N3;
+ }
+ }
+ }
+ }
+ }
+
+ return penalty;
+}
+
+STATIC_IN_RELEASE int Mask_calcN2(int width, unsigned char *frame)
+{
+ int x, y;
+ unsigned char *p;
+ unsigned char b22, w22;
+ int penalty = 0;
+
+ p = frame;
+ for(y = 1; y < width; y++) {
+ for(x = 1; x < width; x++) {
+ b22 = (p[0] & p[1] & p[width] & p[width+1]) & 1;
+ w22 = (p[0] | p[1] | p[width] | p[width+1]) & 1;
+ if(b22 != 0 || w22 == 0) {
+ penalty += N2;
+ }
+ p++;
+ }
+ p++;
+ }
+
+ return penalty;
+}
+
+STATIC_IN_RELEASE int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength)
+{
+ int head;
+ int i;
+ unsigned char prev;
+
+ prev = frame[0];
+ head = prev & 1;
+ if(head) {
+ runLength[0] = -1;
+ }
+ runLength[head] = 1;
+
+ for(i = 1; i < width; i++) {
+ if((frame[i] ^ prev) & 1) {
+ head++;
+ runLength[head] = 1;
+ prev = frame[i];
+ } else {
+ runLength[head]++;
+ }
+ }
+
+ return head + 1;
+}
+
+STATIC_IN_RELEASE int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength)
+{
+ int head;
+ int i;
+ unsigned char prev;
+
+ prev = frame[0];
+ head = prev & 1;
+ if(head) {
+ runLength[0] = -1;
+ } else {
+ }
+ runLength[head] = 1;
+ frame += width;
+
+ for(i = 1; i < width; i++) {
+ if((*frame ^ prev) & 1) {
+ head++;
+ runLength[head] = 1;
+ prev = *frame;
+ } else {
+ runLength[head]++;
+ }
+ frame += width;
+ }
+
+ return head + 1;
+}
+
+STATIC_IN_RELEASE int Mask_evaluateSymbol(int width, unsigned char *frame)
+{
+ int x, y;
+ int penalty = 0;
+ int runLength[QRSPEC_WIDTH_MAX + 1];
+ int length;
+
+ penalty += Mask_calcN2(width, frame);
+
+ for(y = 0; y < width; y++) {
+ length = Mask_calcRunLengthH(width, frame + y * width, runLength);
+ penalty += Mask_calcN1N3(length, runLength);
+ }
+
+ for(x = 0; x < width; x++) {
+ length = Mask_calcRunLengthV(width, frame + x, runLength);
+ penalty += Mask_calcN1N3(length, runLength);
+ }
+
+ return penalty;
+}
+
+unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level)
+{
+ int i;
+ unsigned char *mask, *bestMask;
+ int minPenalty = INT_MAX;
+ int blacks;
+ int bratio;
+ int penalty;
+ int w2 = width * width;
+
+ mask = (unsigned char *)malloc((size_t)w2);
+ if(mask == NULL) return NULL;
+ bestMask = (unsigned char *)malloc((size_t)w2);
+ if(bestMask == NULL) {
+ free(mask);
+ return NULL;
+ }
+
+ for(i = 0; i < maskNum; i++) {
+// n1 = n2 = n3 = n4 = 0;
+ penalty = 0;
+ blacks = maskMakers[i](width, frame, mask);
+ blacks += Mask_writeFormatInformation(width, mask, i, level);
+ bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */
+ penalty = (abs(bratio - 50) / 5) * N4;
+// n4 = penalty;
+ penalty += Mask_evaluateSymbol(width, mask);
+// printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, penalty);
+ if(penalty < minPenalty) {
+ minPenalty = penalty;
+ memcpy(bestMask, mask, (size_t)w2);
+ }
+ }
+ free(mask);
+ return bestMask;
+}
diff --git a/genqrcode/mask.h b/genqrcode/mask.h
new file mode 100644
index 0000000000..169e64b2bb
--- /dev/null
+++ b/genqrcode/mask.h
@@ -0,0 +1,38 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Masking.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MASK_H
+#define MASK_H
+
+extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level);
+extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level);
+
+#ifdef WITH_TESTS
+extern int Mask_calcN2(int width, unsigned char *frame);
+extern int Mask_calcN1N3(int length, int *runLength);
+extern int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength);
+extern int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength);
+extern int Mask_evaluateSymbol(int width, unsigned char *frame);
+extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level);
+extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask);
+#endif
+
+#endif /* MASK_H */
diff --git a/genqrcode/mmask.c b/genqrcode/mmask.c
new file mode 100644
index 0000000000..5f09a1e981
--- /dev/null
+++ b/genqrcode/mmask.c
@@ -0,0 +1,177 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Masking for Micro QR Code.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <errno.h>
+
+#include "qrencode.h"
+#include "mqrspec.h"
+#include "mmask.h"
+
+STATIC_IN_RELEASE void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level)
+{
+ unsigned int format;
+ unsigned char v;
+ int i;
+
+ format = MQRspec_getFormatInfo(mask, version, level);
+
+ for(i = 0; i < 8; i++) {
+ v = 0x84 | (format & 1);
+ frame[width * (i + 1) + 8] = v;
+ format = format >> 1;
+ }
+ for(i = 0; i < 7; i++) {
+ v = 0x84 | (format & 1);
+ frame[width * 8 + 7 - i] = v;
+ format = format >> 1;
+ }
+}
+
+#define MASKMAKER(__exp__) \
+ int x, y;\
+\
+ for(y = 0; y < width; y++) {\
+ for(x = 0; x < width; x++) {\
+ if(*s & 0x80) {\
+ *d = *s;\
+ } else {\
+ *d = *s ^ ((__exp__) == 0);\
+ }\
+ s++; d++;\
+ }\
+ }
+
+static void Mask_mask0(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER(y&1)
+}
+
+static void Mask_mask1(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER(((y/2)+(x/3))&1)
+}
+
+static void Mask_mask2(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER((((x*y)&1)+(x*y)%3)&1)
+}
+
+static void Mask_mask3(int width, const unsigned char *s, unsigned char *d)
+{
+ MASKMAKER((((x+y)&1)+((x*y)%3))&1)
+}
+
+#define maskNum (4)
+typedef void MaskMaker(int, const unsigned char *, unsigned char *);
+static MaskMaker *maskMakers[maskNum] = {
+ Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3
+};
+
+#ifdef WITH_TESTS
+unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask)
+{
+ unsigned char *masked;
+
+ masked = (unsigned char *)malloc((size_t)(width * width));
+ if(masked == NULL) return NULL;
+
+ maskMakers[mask](width, frame, masked);
+
+ return masked;
+}
+#endif
+
+unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level)
+{
+ unsigned char *masked;
+ int width;
+
+ if(mask < 0 || mask >= maskNum) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ width = MQRspec_getWidth(version);
+ masked = (unsigned char *)malloc((size_t)(width * width));
+ if(masked == NULL) return NULL;
+
+ maskMakers[mask](width, frame, masked);
+ MMask_writeFormatInformation(version, width, masked, mask, level);
+
+ return masked;
+}
+
+STATIC_IN_RELEASE int MMask_evaluateSymbol(int width, unsigned char *frame)
+{
+ int x, y;
+ unsigned char *p;
+ int sum1 = 0, sum2 = 0;
+
+ p = frame + width * (width - 1);
+ for(x = 1; x < width; x++) {
+ sum1 += (p[x] & 1);
+ }
+
+ p = frame + width * 2 - 1;
+ for(y = 1; y < width; y++) {
+ sum2 += (*p & 1);
+ p += width;
+ }
+
+ return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1);
+}
+
+unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level)
+{
+ int i;
+ unsigned char *mask, *bestMask;
+ int maxScore = 0;
+ int score;
+ int width;
+
+ width = MQRspec_getWidth(version);
+
+ mask = (unsigned char *)malloc((size_t)(width * width));
+ if(mask == NULL) return NULL;
+ bestMask = NULL;
+
+ for(i = 0; i < maskNum; i++) {
+ score = 0;
+ maskMakers[i](width, frame, mask);
+ MMask_writeFormatInformation(version, width, mask, i, level);
+ score = MMask_evaluateSymbol(width, mask);
+ if(score > maxScore) {
+ maxScore = score;
+ free(bestMask);
+ bestMask = mask;
+ mask = (unsigned char *)malloc((size_t)(width * width));
+ if(mask == NULL) break;
+ }
+ }
+ free(mask);
+ return bestMask;
+}
diff --git a/genqrcode/mmask.h b/genqrcode/mmask.h
new file mode 100644
index 0000000000..56a58cd2d7
--- /dev/null
+++ b/genqrcode/mmask.h
@@ -0,0 +1,34 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Masking for Micro QR Code.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MMASK_H
+#define MMASK_H
+
+extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level);
+extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level);
+
+#ifdef WITH_TESTS
+extern int MMask_evaluateSymbol(int width, unsigned char *frame);
+extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level);
+extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask);
+#endif
+
+#endif /* MMASK_H */
diff --git a/genqrcode/mqrspec.c b/genqrcode/mqrspec.c
new file mode 100644
index 0000000000..6dbc9e11a2
--- /dev/null
+++ b/genqrcode/mqrspec.c
@@ -0,0 +1,232 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Micro QR Code specification in convenient format.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ * or
+ * "Automatic identification and data capture techniques --
+ * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "mqrspec.h"
+
+/******************************************************************************
+ * Version and capacity
+ *****************************************************************************/
+
+typedef struct {
+ int width; ///< Edge length of the symbol
+ int ec[4]; ///< Number of ECC code (bytes)
+} MQRspec_Capacity;
+
+/**
+ * Table of the capacity of symbols
+ * See Table 1 (p.106) and Table 8 (p.113) of Appendix 1, JIS X0510:2004.
+ */
+static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = {
+ { 0, {0, 0, 0, 0}},
+ { 11, {2, 0, 0, 0}},
+ { 13, {5, 6, 0, 0}},
+ { 15, {6, 8, 0, 0}},
+ { 17, {8, 10, 14, 0}}
+};
+
+int MQRspec_getDataLengthBit(int version, QRecLevel level)
+{
+ int w;
+ int ecc;
+
+ w = mqrspecCapacity[version].width - 1;
+ ecc = mqrspecCapacity[version].ec[level];
+ if(ecc == 0) return 0;
+ return w * w - 64 - ecc * 8;
+}
+
+int MQRspec_getDataLength(int version, QRecLevel level)
+{
+ return (MQRspec_getDataLengthBit(version, level) + 4) / 8;
+}
+
+int MQRspec_getECCLength(int version, QRecLevel level)
+{
+ return mqrspecCapacity[version].ec[level];
+}
+
+int MQRspec_getWidth(int version)
+{
+ return mqrspecCapacity[version].width;
+}
+
+/******************************************************************************
+ * Length indicator
+ *****************************************************************************/
+
+/**
+ * See Table 3 (p.107) of Appendix 1, JIS X0510:2004.
+ */
+static const int lengthTableBits[4][4] = {
+ { 3, 4, 5, 6},
+ { 0, 3, 4, 5},
+ { 0, 0, 4, 5},
+ { 0, 0, 3, 4}
+};
+
+int MQRspec_lengthIndicator(QRencodeMode mode, int version)
+{
+ return lengthTableBits[mode][version - 1];
+}
+
+int MQRspec_maximumWords(QRencodeMode mode, int version)
+{
+ int bits;
+ int words;
+
+ bits = lengthTableBits[mode][version - 1];
+ words = (1 << bits) - 1;
+ if(mode == QR_MODE_KANJI) {
+ words *= 2; // the number of bytes is required
+ }
+
+ return words;
+}
+
+/******************************************************************************
+ * Format information
+ *****************************************************************************/
+
+/* See calcFormatInfo in tests/test_mqrspec.c */
+static const unsigned int formatInfo[4][8] = {
+ {0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3},
+ {0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4},
+ {0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d},
+ {0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba}
+};
+
+/* See Table 10 of Appendix 1. (p.115) */
+static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = {
+ {-1, -1, -1},
+ { 0, -1, -1},
+ { 1, 2, -1},
+ { 3, 4, -1},
+ { 5, 6, 7}
+};
+
+unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level)
+{
+ int type;
+
+ if(mask < 0 || mask > 3) return 0;
+ if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0;
+ if(level == QR_ECLEVEL_H) return 0;
+ type = typeTable[version][level];
+ if(type < 0) return 0;
+
+ return formatInfo[mask][type];
+}
+
+/******************************************************************************
+ * Frame
+ *****************************************************************************/
+
+/**
+ * Put a finder pattern.
+ * @param frame destination frame data
+ * @param width frame width
+ * @param ox,oy upper-left coordinate of the pattern
+ */
+static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
+{
+ static const unsigned char finder[] = {
+ 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+ 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+ 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+ 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+ 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+ 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+ 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+ };
+ int x, y;
+ const unsigned char *s;
+
+ frame += oy * width + ox;
+ s = finder;
+ for(y = 0; y < 7; y++) {
+ for(x = 0; x < 7; x++) {
+ frame[x] = s[x];
+ }
+ frame += width;
+ s += 7;
+ }
+}
+
+static unsigned char *MQRspec_createFrame(int version)
+{
+ unsigned char *frame, *p, *q;
+ int width;
+ int x, y;
+
+ width = mqrspecCapacity[version].width;
+ frame = (unsigned char *)malloc((size_t)(width * width));
+ if(frame == NULL) return NULL;
+
+ memset(frame, 0, (size_t)(width * width));
+ /* Finder pattern */
+ putFinderPattern(frame, width, 0, 0);
+ /* Separator */
+ p = frame;
+ for(y = 0; y < 7; y++) {
+ p[7] = 0xc0;
+ p += width;
+ }
+ memset(frame + width * 7, 0xc0, 8);
+ /* Mask format information area */
+ memset(frame + width * 8 + 1, 0x84, 8);
+ p = frame + width + 8;
+ for(y = 0; y < 7; y++) {
+ *p = 0x84;
+ p += width;
+ }
+ /* Timing pattern */
+ p = frame + 8;
+ q = frame + width * 8;
+ for(x = 1; x < width-7; x++) {
+ *p = 0x90 | (x & 1);
+ *q = 0x90 | (x & 1);
+ p++;
+ q += width;
+ }
+
+ return frame;
+}
+
+unsigned char *MQRspec_newFrame(int version)
+{
+ if(version < 1 || version > MQRSPEC_VERSION_MAX) return NULL;
+
+ return MQRspec_createFrame(version);
+}
diff --git a/genqrcode/mqrspec.h b/genqrcode/mqrspec.h
new file mode 100644
index 0000000000..c8ab425080
--- /dev/null
+++ b/genqrcode/mqrspec.h
@@ -0,0 +1,150 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Micro QR Code specification in convenient format.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef MQRSPEC_H
+#define MQRSPEC_H
+
+#include "qrencode.h"
+
+/******************************************************************************
+ * Version and capacity
+ *****************************************************************************/
+
+/**
+ * Maximum width of a symbol
+ */
+#define MQRSPEC_WIDTH_MAX 17
+
+/**
+ * Return maximum data code length (bits) for the version.
+ * @param version version of the symbol
+ * @param level error correction level
+ * @return maximum size (bits)
+ */
+extern int MQRspec_getDataLengthBit(int version, QRecLevel level);
+
+/**
+ * Return maximum data code length (bytes) for the version.
+ * @param version version of the symbol
+ * @param level error correction level
+ * @return maximum size (bytes)
+ */
+extern int MQRspec_getDataLength(int version, QRecLevel level);
+
+/**
+ * Return maximum error correction code length (bytes) for the version.
+ * @param version version of the symbol
+ * @param level error correction level
+ * @return ECC size (bytes)
+ */
+extern int MQRspec_getECCLength(int version, QRecLevel level);
+
+/**
+ * Return a version number that satisfies the input code length.
+ * @param size input code length (byte)
+ * @param level error correction level
+ * @return version number
+ */
+extern int MQRspec_getMinimumVersion(int size, QRecLevel level);
+
+/**
+ * Return the width of the symbol for the version.
+ * @param version version of the symbol
+ * @return width
+ */
+extern int MQRspec_getWidth(int version);
+
+/**
+ * Return the numer of remainder bits.
+ * @param version version of the symbol
+ * @return number of remainder bits
+ */
+extern int MQRspec_getRemainder(int version);
+
+/******************************************************************************
+ * Length indicator
+ *****************************************************************************/
+
+/**
+ * Return the size of length indicator for the mode and version.
+ * @param mode encode mode
+ * @param version vesion of the symbol
+ * @return the size of the appropriate length indicator (bits).
+ */
+extern int MQRspec_lengthIndicator(QRencodeMode mode, int version);
+
+/**
+ * Return the maximum length for the mode and version.
+ * @param mode encode mode
+ * @param version vesion of the symbol
+ * @return the maximum length (bytes)
+ */
+extern int MQRspec_maximumWords(QRencodeMode mode, int version);
+
+/******************************************************************************
+ * Version information pattern
+ *****************************************************************************/
+
+/**
+ * Return BCH encoded version information pattern that is used for the symbol
+ * of version 7 or greater. Use lower 18 bits.
+ * @param version vesion of the symbol
+ * @return BCH encoded version information pattern
+ */
+extern unsigned int MQRspec_getVersionPattern(int version);
+
+/******************************************************************************
+ * Format information
+ *****************************************************************************/
+
+/**
+ * Return BCH encoded format information pattern.
+ * @param mask mask number
+ * @param version version of the symbol
+ * @param level error correction level
+ * @return BCH encoded format information pattern
+ */
+extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level);
+
+/******************************************************************************
+ * Frame
+ *****************************************************************************/
+
+/**
+ * Return a copy of initialized frame.
+ * @param version version of the symbol
+ * @return Array of unsigned char. You can free it by free().
+ */
+extern unsigned char *MQRspec_newFrame(int version);
+
+/******************************************************************************
+ * Mode indicator
+ *****************************************************************************/
+
+/**
+ * Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, p.107.
+ */
+#define MQRSPEC_MODEID_NUM 0
+#define MQRSPEC_MODEID_AN 1
+#define MQRSPEC_MODEID_8 2
+#define MQRSPEC_MODEID_KANJI 3
+
+#endif /* MQRSPEC_H */
diff --git a/genqrcode/qrenc.c b/genqrcode/qrenc.c
new file mode 100644
index 0000000000..1ce8c989b0
--- /dev/null
+++ b/genqrcode/qrenc.c
@@ -0,0 +1,1451 @@
+/**
+ * qrencode - QR Code encoder
+ *
+ * QR Code encoding tool
+ * Copyright (C) 2006-2018, 2020 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#if HAVE_PNG
+#include <png.h>
+#endif
+
+#include "qrencode.h"
+
+#define INCHES_PER_METER (100.0/2.54)
+
+static int casesensitive = 1;
+static int eightbit = 0;
+static int version = 0;
+static int size = 3;
+static int margin = -1;
+static int dpi = 72;
+static int structured = 0;
+static int rle = 0;
+static int svg_path = 0;
+static int micro = 0;
+static int inline_svg = 0;
+static int strict_versioning = 0;
+static QRecLevel level = QR_ECLEVEL_L;
+static QRencodeMode hint = QR_MODE_8;
+static unsigned char fg_color[4] = {0, 0, 0, 255};
+static unsigned char bg_color[4] = {255, 255, 255, 255};
+
+static int verbose = 0;
+
+enum imageType {
+ PNG_TYPE,
+ PNG32_TYPE,
+ EPS_TYPE,
+ SVG_TYPE,
+ XPM_TYPE,
+ ANSI_TYPE,
+ ANSI256_TYPE,
+ ASCII_TYPE,
+ ASCIIi_TYPE,
+ UTF8_TYPE,
+ ANSIUTF8_TYPE,
+ ANSI256UTF8_TYPE,
+ UTF8i_TYPE,
+ ANSIUTF8i_TYPE
+};
+
+static enum imageType image_type = PNG_TYPE;
+
+static const struct option options[] = {
+ {"help" , no_argument , NULL, 'h'},
+ {"output" , required_argument, NULL, 'o'},
+ {"read-from" , required_argument, NULL, 'r'},
+ {"level" , required_argument, NULL, 'l'},
+ {"size" , required_argument, NULL, 's'},
+ {"symversion" , required_argument, NULL, 'v'},
+ {"margin" , required_argument, NULL, 'm'},
+ {"dpi" , required_argument, NULL, 'd'},
+ {"type" , required_argument, NULL, 't'},
+ {"structured" , no_argument , NULL, 'S'},
+ {"kanji" , no_argument , NULL, 'k'},
+ {"casesensitive" , no_argument , NULL, 'c'},
+ {"ignorecase" , no_argument , NULL, 'i'},
+ {"8bit" , no_argument , NULL, '8'},
+ {"micro" , no_argument , NULL, 'M'},
+ {"rle" , no_argument , &rle, 1},
+ {"svg-path" , no_argument , &svg_path, 1},
+ {"inline" , no_argument , &inline_svg, 1},
+ {"strict-version", no_argument , &strict_versioning, 1},
+ {"foreground" , required_argument, NULL, 'f'},
+ {"background" , required_argument, NULL, 'b'},
+ {"version" , no_argument , NULL, 'V'},
+ {"verbose" , no_argument , &verbose, 1},
+ {NULL, 0, NULL, 0}
+};
+
+static char *optstring = "ho:r:l:s:v:m:d:t:Skci8MV";
+
+static void usage(int help, int longopt, int status)
+{
+ FILE *out = status ? stderr : stdout;
+ fprintf(out,
+"qrencode version %s\n"
+"Copyright (C) 2006-2018, 2020 Kentaro Fukuchi\n", QRcode_APIVersionString());
+ if(help) {
+ if(longopt) {
+ fprintf(out,
+"Usage: qrencode [-o FILENAME] [OPTION]... [STRING]\n"
+"Encode input data in a QR Code and save as a PNG or EPS image.\n\n"
+" -h, --help display the help message. -h displays only the help of short\n"
+" options.\n\n"
+" -o FILENAME, --output=FILENAME\n"
+" write image to FILENAME. If '-' is specified, the result\n"
+" will be output to standard output. If -S is given, structured\n"
+" symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n"
+" (suffix is removed from FILENAME, if specified)\n\n"
+" -r FILENAME, --read-from=FILENAME\n"
+" read input data from FILENAME.\n\n"
+" -s NUMBER, --size=NUMBER\n"
+" specify module size in dots (pixels). (default=3)\n\n"
+" -l {LMQH}, --level={LMQH}\n"
+" specify error correction level from L (lowest) to H (highest).\n"
+" (default=L)\n\n"
+" -v NUMBER, --symversion=NUMBER\n"
+" specify the minimum version of the symbol. See SYMBOL VERSIONS\n"
+" for more information. (default=auto)\n\n"
+" -m NUMBER, --margin=NUMBER\n"
+" specify the width of the margins. (default=4 (2 for Micro QR)))\n\n"
+" -d NUMBER, --dpi=NUMBER\n"
+" specify the DPI of the generated PNG. (default=72)\n\n"
+" -t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8},\n"
+" --type={PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}\n"
+" specify the type of the generated image. (default=PNG)\n"
+" If ASCII*, UTF8*, or ANSI* is specified, the image will be disp-\n"
+" layed in the terminal by using text characters instead of gene-\n"
+" rating an image file. If the name of the type is followed by\n"
+" 'i', the light/dark character will be reversed.\n"
+" -S, --structured\n"
+" make structured symbols. Version must be specified with '-v'.\n\n"
+" -k, --kanji assume that the input text contains kanji (shift-jis).\n\n"
+" -c, --casesensitive\n"
+" encode lower-case alphabet characters in 8-bit mode. (default)\n\n"
+" -i, --ignorecase\n"
+" ignore case distinctions and use only upper-case characters.\n\n"
+" -8, --8bit encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n\n"
+" -M, --micro encode in a Micro QR Code.\n\n"
+" --rle enable run-length encoding for SVG.\n\n"
+" --svg-path\n"
+" use single path to draw modules for SVG.\n\n"
+" --inline only useful for SVG output, generates an SVG without the XML tag.\n\n"
+" --foreground=RRGGBB[AA]\n"
+" --background=RRGGBB[AA]\n"
+" specify foreground/background color in hexadecimal notation.\n"
+" 6-digit (RGB) or 8-digit (RGBA) form are supported.\n"
+" Color output support available only in PNG, EPS and SVG.\n\n"
+" --strict-version\n"
+" disable automatic version number adjustment. If the input data is\n"
+" too large for the specified version, the program exits with the\n"
+" code of 1.\n\n"
+" -V, --version\n"
+" display the version number and copyrights of the qrencode.\n\n"
+" --verbose\n"
+" display verbose information to stderr.\n\n"
+" [STRING] input data. If it is not specified, data will be taken from\n"
+" standard input.\n\n"
+"SYMBOL VERSIONS\n"
+" The symbol versions of QR Code range from Version 1 to Version\n"
+" 40. Each version has a different module configuration or number\n"
+" of modules, ranging from Version 1 (21 x 21 modules) up to\n"
+" Version 40 (177 x 177 modules). Each higher version number\n"
+" comprises 4 additional modules per side by default. See\n"
+" https://www.qrcode.com/en/about/version.html for a detailed\n"
+" version list.\n"
+
+ );
+ } else {
+ fprintf(out,
+"Usage: qrencode [-o FILENAME] [OPTION]... [STRING]\n"
+"Encode input data in a QR Code and save as a PNG or EPS image.\n\n"
+" -h display this message.\n"
+" --help display the usage of long options.\n"
+" -o FILENAME write image to FILENAME. If '-' is specified, the result\n"
+" will be output to standard output. If -S is given, structured\n"
+" symbols are written to FILENAME-01.png, FILENAME-02.png, ...\n"
+" (suffix is removed from FILENAME, if specified)\n"
+" -r FILENAME read input data from FILENAME.\n"
+" -s NUMBER specify module size in dots (pixels). (default=3)\n"
+" -l {LMQH} specify error correction level from L (lowest) to H (highest).\n"
+" (default=L)\n"
+" -v NUMBER specify the minimum version of the symbol. (default=auto)\n"
+" -m NUMBER specify the width of the margins. (default=4 (2 for Micro))\n"
+" -d NUMBER specify the DPI of the generated PNG. (default=72)\n"
+" -t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}\n"
+" specify the type of the generated image. (default=PNG)\n"
+" -S make structured symbols. Version number must be specified with '-v'.\n"
+" -k assume that the input text contains kanji (shift-jis).\n"
+" -c encode lower-case alphabet characters in 8-bit mode. (default)\n"
+" -i ignore case distinctions and use only upper-case characters.\n"
+" -8 encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n"
+" -M encode in a Micro QR Code.\n"
+" -V display the version number and copyrights of the qrencode.\n"
+" [STRING] input data. If it is not specified, data will be taken from\n"
+" standard input.\n\n"
+" Try \"qrencode --help\" for more options.\n"
+ );
+ }
+ }
+}
+
+static int color_set(unsigned char color[4], const char *value)
+{
+ int len = (int)strlen(value);
+ int i, count;
+ unsigned int col[4];
+ if(len == 6) {
+ count = sscanf(value, "%02x%02x%02x%n", &col[0], &col[1], &col[2], &len);
+ if(count < 3 || len != 6) {
+ return -1;
+ }
+ for(i = 0; i < 3; i++) {
+ color[i] = (unsigned char)col[i];
+ }
+ color[3] = 255;
+ } else if(len == 8) {
+ count = sscanf(value, "%02x%02x%02x%02x%n", &col[0], &col[1], &col[2], &col[3], &len);
+ if(count < 4 || len != 8) {
+ return -1;
+ }
+ for(i = 0; i < 4; i++) {
+ color[i] = (unsigned char)col[i];
+ }
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+#define MAX_DATA_SIZE (7090 * 2) /* timed by the safty factor 2 */
+static unsigned char data_buffer[MAX_DATA_SIZE];
+static unsigned char *readFile(FILE *fp, int *length)
+{
+ int ret;
+
+ ret = (int)fread(data_buffer, 1, MAX_DATA_SIZE, fp);
+ if(ret == 0) {
+ fprintf(stderr, "No input data.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(feof(fp) == 0) {
+ fprintf(stderr, "Input data is too large.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ data_buffer[ret] = '\0';
+ *length = ret;
+
+ return data_buffer;
+}
+
+static FILE *openFile(const char *outfile)
+{
+ FILE *fp;
+
+ if(outfile == NULL || (outfile[0] == '-' && outfile[1] == '\0')) {
+ fp = stdout;
+ } else {
+ fp = fopen(outfile, "wb");
+ if(fp == NULL) {
+ fprintf(stderr, "Failed to create file: %s\n", outfile);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ return fp;
+}
+
+#if HAVE_PNG
+static void fillRow(unsigned char *row, int num, const unsigned char color[])
+{
+ int i;
+
+ for(i = 0; i < num; i++) {
+ memcpy(row, color, 4);
+ row += 4;
+ }
+}
+#endif
+
+static int writePNG(const QRcode *qrcode, const char *outfile, enum imageType type)
+{
+#if HAVE_PNG
+ static FILE *fp; // avoid clobbering by setjmp.
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_colorp palette = NULL;
+ png_byte alpha_values[2];
+ unsigned char *row, *p, *q;
+ int x, y, xx, yy, bit;
+ int realwidth;
+
+ realwidth = (qrcode->width + margin * 2) * size;
+ if(type == PNG_TYPE) {
+ row = (unsigned char *)malloc((size_t)((realwidth + 7) / 8));
+ } else if(type == PNG32_TYPE) {
+ row = (unsigned char *)malloc((size_t)realwidth * 4);
+ } else {
+ fprintf(stderr, "Internal error.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(row == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(outfile[0] == '-' && outfile[1] == '\0') {
+ fp = stdout;
+ } else {
+ fp = fopen(outfile, "wb");
+ if(fp == NULL) {
+ fprintf(stderr, "Failed to create file: %s\n", outfile);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if(png_ptr == NULL) {
+ fprintf(stderr, "Failed to initialize PNG writer.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if(info_ptr == NULL) {
+ fprintf(stderr, "Failed to initialize PNG write.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ fprintf(stderr, "Failed to write PNG image.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(type == PNG_TYPE) {
+ palette = (png_colorp) malloc(sizeof(png_color) * 2);
+ if(palette == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+ palette[0].red = fg_color[0];
+ palette[0].green = fg_color[1];
+ palette[0].blue = fg_color[2];
+ palette[1].red = bg_color[0];
+ palette[1].green = bg_color[1];
+ palette[1].blue = bg_color[2];
+ alpha_values[0] = fg_color[3];
+ alpha_values[1] = bg_color[3];
+ png_set_PLTE(png_ptr, info_ptr, palette, 2);
+ png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, NULL);
+ }
+
+ png_init_io(png_ptr, fp);
+ if(type == PNG_TYPE) {
+ png_set_IHDR(png_ptr, info_ptr,
+ (unsigned int)realwidth, (unsigned int)realwidth,
+ 1,
+ PNG_COLOR_TYPE_PALETTE,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+ } else {
+ png_set_IHDR(png_ptr, info_ptr,
+ (unsigned int)realwidth, (unsigned int)realwidth,
+ 8,
+ PNG_COLOR_TYPE_RGB_ALPHA,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+ }
+ png_set_pHYs(png_ptr, info_ptr,
+ (png_uint_32)(dpi * INCHES_PER_METER),
+ (png_uint_32)(dpi * INCHES_PER_METER),
+ PNG_RESOLUTION_METER);
+ png_write_info(png_ptr, info_ptr);
+
+ if(type == PNG_TYPE) {
+ /* top margin */
+ memset(row, 0xff, (size_t)((realwidth + 7) / 8));
+ for(y = 0; y < margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+
+ /* data */
+ p = qrcode->data;
+ for(y = 0; y < qrcode->width; y++) {
+ memset(row, 0xff, (size_t)((realwidth + 7) / 8));
+ q = row;
+ q += margin * size / 8;
+ bit = 7 - (margin * size % 8);
+ for(x = 0; x < qrcode->width; x++) {
+ for(xx = 0; xx < size; xx++) {
+ *q ^= (*p & 1) << bit;
+ bit--;
+ if(bit < 0) {
+ q++;
+ bit = 7;
+ }
+ }
+ p++;
+ }
+ for(yy = 0; yy < size; yy++) {
+ png_write_row(png_ptr, row);
+ }
+ }
+ /* bottom margin */
+ memset(row, 0xff, (size_t)((realwidth + 7) / 8));
+ for(y = 0; y < margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+ } else {
+ /* top margin */
+ fillRow(row, realwidth, bg_color);
+ for(y = 0; y < margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+
+ /* data */
+ p = qrcode->data;
+ for(y = 0; y < qrcode->width; y++) {
+ fillRow(row, realwidth, bg_color);
+ for(x = 0; x < qrcode->width; x++) {
+ for(xx = 0; xx < size; xx++) {
+ if(*p & 1) {
+ memcpy(&row[((margin + x) * size + xx) * 4], fg_color, 4);
+ }
+ }
+ p++;
+ }
+ for(yy = 0; yy < size; yy++) {
+ png_write_row(png_ptr, row);
+ }
+ }
+ /* bottom margin */
+ fillRow(row, realwidth, bg_color);
+ for(y = 0; y < margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ fclose(fp);
+ free(row);
+ free(palette);
+
+ return 0;
+#else
+ fputs("PNG output is disabled at compile time. No output generated.\n", stderr);
+ return 0;
+#endif
+}
+
+static int writeEPS(const QRcode *qrcode, const char *outfile)
+{
+ FILE *fp;
+ unsigned char *row, *p;
+ int x, y, yy;
+ int realwidth;
+
+ fp = openFile(outfile);
+
+ realwidth = (qrcode->width + margin * 2) * size;
+ /* EPS file header */
+ fprintf(fp, "%%!PS-Adobe-2.0 EPSF-1.2\n"
+ "%%%%BoundingBox: 0 0 %d %d\n"
+ "%%%%Pages: 1 1\n"
+ "%%%%EndComments\n", realwidth, realwidth);
+ /* draw point */
+ fprintf(fp, "/p { "
+ "moveto "
+ "0 1 rlineto "
+ "1 0 rlineto "
+ "0 -1 rlineto "
+ "fill "
+ "} bind def\n");
+ /* set color */
+ fprintf(fp, "gsave\n");
+ fprintf(fp, "%f %f %f setrgbcolor\n",
+ (double)bg_color[0] / 255,
+ (double)bg_color[1] / 255,
+ (double)bg_color[2] / 255);
+ fprintf(fp, "%d %d scale\n", realwidth, realwidth);
+ fprintf(fp, "0 0 p\ngrestore\n");
+ fprintf(fp, "%f %f %f setrgbcolor\n",
+ (double)fg_color[0] / 255,
+ (double)fg_color[1] / 255,
+ (double)fg_color[2] / 255);
+ fprintf(fp, "%d %d scale\n", size, size);
+
+ /* data */
+ p = qrcode->data;
+ for(y = 0; y < qrcode->width; y++) {
+ row = (p+(y*qrcode->width));
+ yy = (margin + qrcode->width - y - 1);
+
+ for(x = 0; x < qrcode->width; x++) {
+ if(*(row+x)&0x1) {
+ fprintf(fp, "%d %d p ", margin + x, yy);
+ }
+ }
+ }
+
+ fprintf(fp, "\n%%%%EOF\n");
+ fclose(fp);
+
+ return 0;
+}
+
+static void writeSVG_drawModules(FILE *fp, int x, int y, int width, const char* col, double opacity)
+{
+ if(svg_path) {
+ fprintf(fp, "M%d,%dh%d", x, y, width);
+ } else {
+ if(fg_color[3] != 255) {
+ fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\
+ "fill=\"#%s\" fill-opacity=\"%f\"/>\n",
+ x, y, width, col, opacity );
+ } else {
+ fprintf(fp, "\t\t\t<rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"1\" "\
+ "fill=\"#%s\"/>\n",
+ x, y, width, col );
+ }
+ }
+}
+
+static int writeSVG(const QRcode *qrcode, const char *outfile)
+{
+ FILE *fp;
+ unsigned char *row, *p;
+ int x, y, x0, pen;
+ int symwidth, realwidth;
+ double scale;
+ char fg[7], bg[7];
+ double fg_opacity;
+ double bg_opacity;
+
+ fp = openFile(outfile);
+
+ scale = dpi * INCHES_PER_METER / 100.0;
+
+ symwidth = qrcode->width + margin * 2;
+ realwidth = symwidth * size;
+
+ snprintf(fg, 7, "%02x%02x%02x", fg_color[0], fg_color[1], fg_color[2]);
+ snprintf(bg, 7, "%02x%02x%02x", bg_color[0], bg_color[1], bg_color[2]);
+ fg_opacity = (double)fg_color[3] / 255;
+ bg_opacity = (double)bg_color[3] / 255;
+
+ /* XML declaration */
+ if (!inline_svg)
+ fputs( "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n", fp );
+
+ /* DTD
+ No document type specified because "while a DTD is provided in [the SVG]
+ specification, the use of DTDs for validating XML documents is known to
+ be problematic. In particular, DTDs do not handle namespaces gracefully.
+ It is *not* recommended that a DOCTYPE declaration be included in SVG
+ documents."
+ https://www.w3.org/TR/2003/REC-SVG11-20030114/intro.html#Namespace
+ */
+
+ /* Vanity remark */
+ fprintf(fp, "<!-- Created with qrencode %s (https://fukuchi.org/works/qrencode/index.html) -->\n", QRcode_APIVersionString());
+
+ /* SVG code start */
+ fprintf(fp,
+ "<svg width=\"%.2fcm\" height=\"%.2fcm\" viewBox=\"0 0 %d %d\""\
+ " preserveAspectRatio=\"none\" version=\"1.1\""\
+ " xmlns=\"http://www.w3.org/2000/svg\">\n",
+ (double)realwidth / scale, (double)realwidth / scale, symwidth, symwidth
+ );
+
+ /* Make named group */
+ fputs("\t<g id=\"QRcode\">\n", fp);
+
+ /* Make solid background */
+ if(bg_color[3] != 255) {
+ fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\" fill-opacity=\"%f\"/>\n", symwidth, symwidth, bg, bg_opacity);
+ } else {
+ fprintf(fp, "\t\t<rect x=\"0\" y=\"0\" width=\"%d\" height=\"%d\" fill=\"#%s\"/>\n", symwidth, symwidth, bg);
+ }
+
+ if(svg_path) {
+ if(fg_color[3] != 255) {
+ fprintf(fp, "\t\t<path style=\"stroke:#%s;stroke-opacity:%f\" transform=\"translate(%d,%d.5)\" d=\"", fg, fg_opacity, margin, margin);
+ } else {
+ fprintf(fp, "\t\t<path style=\"stroke:#%s\" transform=\"translate(%d,%d.5)\" d=\"", fg, margin, margin);
+ }
+ } else {
+ /* Create new viewbox for QR data */
+ fprintf(fp, "\t\t<g id=\"Pattern\" transform=\"translate(%d,%d)\">\n", margin, margin);
+ }
+
+ /* Write data */
+ p = qrcode->data;
+ for(y = 0; y < qrcode->width; y++) {
+ row = (p+(y*qrcode->width));
+
+ if( !rle ) {
+ /* no RLE */
+ for(x = 0; x < qrcode->width; x++) {
+ if(*(row+x)&0x1) {
+ writeSVG_drawModules(fp, x, y, 1, fg, fg_opacity);
+ }
+ }
+ } else {
+ /* simple RLE */
+ pen = 0;
+ x0 = 0;
+ for(x = 0; x < qrcode->width; x++) {
+ if( !pen ) {
+ pen = *(row+x)&0x1;
+ x0 = x;
+ } else if(!(*(row+x)&0x1)) {
+ writeSVG_drawModules(fp, x0, y, x-x0, fg, fg_opacity);
+ pen = 0;
+ }
+ }
+ if( pen ) {
+ writeSVG_drawModules(fp, x0, y, qrcode->width - x0, fg, fg_opacity);
+ }
+ }
+ }
+
+ if(svg_path) {
+ fputs("\"/>\n", fp);
+ } else {
+ /* Close QR data viewbox */
+ fputs("\t\t</g>\n", fp);
+ }
+
+ /* Close group */
+ fputs("\t</g>\n", fp);
+
+ /* Close SVG code */
+ fputs("</svg>\n", fp);
+ fclose(fp);
+
+ return 0;
+}
+
+static int writeXPM(const QRcode *qrcode, const char *outfile)
+{
+ FILE *fp;
+ int x, xx, y, yy, realwidth, realmargin;
+ char *row;
+ char fg[7], bg[7];
+ unsigned char *p;
+
+ fp = openFile(outfile);
+
+ realwidth = (qrcode->width + margin * 2) * size;
+ realmargin = margin * size;
+
+ row = malloc((size_t)realwidth + 1);
+ if (!row ) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ snprintf(fg, 7, "%02x%02x%02x", fg_color[0], fg_color[1], fg_color[2]);
+ snprintf(bg, 7, "%02x%02x%02x", bg_color[0], bg_color[1], bg_color[2]);
+
+ fputs("/* XPM */\n", fp);
+ fputs("static const char *const qrcode_xpm[] = {\n", fp);
+ fputs("/* width height ncolors chars_per_pixel */\n", fp);
+ fprintf(fp, "\"%d %d 2 1\",\n", realwidth, realwidth);
+
+ fputs("/* colors */\n", fp);
+ fprintf(fp, "\"F c #%s\",\n", fg);
+ fprintf(fp, "\"B c #%s\",\n", bg);
+
+ fputs("/* pixels */\n", fp);
+ memset(row, 'B', (size_t)realwidth);
+ row[realwidth] = '\0';
+
+ for (y = 0; y < realmargin; y++) {
+ fprintf(fp, "\"%s\",\n", row);
+ }
+
+ p = qrcode->data;
+ for (y = 0; y < qrcode->width; y++) {
+ for (yy = 0; yy < size; yy++) {
+ fputs("\"", fp);
+
+ for (x = 0; x < margin; x++) {
+ for (xx = 0; xx < size; xx++) {
+ fputs("B", fp);
+ }
+ }
+
+ for (x = 0; x < qrcode->width; x++) {
+ for (xx = 0; xx < size; xx++) {
+ if (p[(y * qrcode->width) + x] & 0x1) {
+ fputs("F", fp);
+ } else {
+ fputs("B", fp);
+ }
+ }
+ }
+
+ for (x = 0; x < margin; x++) {
+ for (xx = 0; xx < size; xx++) {
+ fputs("B", fp);
+ }
+ }
+
+ fputs("\",\n", fp);
+ }
+ }
+
+ for (y = 0; y < realmargin; y++) {
+ fprintf(fp, "\"%s\",\n", row);
+ }
+ fputs("};\n", fp);
+
+ free(row);
+ fclose(fp);
+
+ return 0;
+}
+
+static void writeANSI_margin(FILE* fp, int realwidth,
+ char* buffer, const char* white, int white_s )
+{
+ int y;
+
+ strncpy(buffer, white, (size_t)white_s);
+ memset(buffer + white_s, ' ', (size_t)realwidth * 2);
+ strcpy(buffer + white_s + realwidth * 2, "\033[0m\n"); // reset to default colors
+ for(y = 0; y < margin; y++ ){
+ fputs(buffer, fp);
+ }
+}
+
+static int writeANSI(const QRcode *qrcode, const char *outfile)
+{
+ FILE *fp;
+ unsigned char *row, *p;
+ int x, y;
+ int realwidth;
+ int last;
+
+ const char *white, *black;
+ char *buffer;
+ int white_s, black_s, buffer_s;
+
+ if(image_type == ANSI256_TYPE){
+ /* codes for 256 color compatible terminals */
+ white = "\033[48;5;231m";
+ white_s = 11;
+ black = "\033[48;5;16m";
+ black_s = 10;
+ } else {
+ white = "\033[47m";
+ white_s = 5;
+ black = "\033[40m";
+ black_s = 5;
+ }
+
+ size = 1;
+
+ fp = openFile(outfile);
+
+ realwidth = (qrcode->width + margin * 2) * size;
+ buffer_s = (realwidth * white_s) * 2;
+ buffer = (char *)malloc((size_t)buffer_s);
+ if(buffer == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* top margin */
+ writeANSI_margin(fp, realwidth, buffer, white, white_s);
+
+ /* data */
+ p = qrcode->data;
+ for(y = 0; y < qrcode->width; y++) {
+ row = (p+(y*qrcode->width));
+
+ memset(buffer, 0, (size_t)buffer_s);
+ strncpy(buffer, white, (size_t)white_s);
+ for(x = 0; x < margin; x++ ){
+ strncat(buffer, " ", 2);
+ }
+ last = 0;
+
+ for(x = 0; x < qrcode->width; x++) {
+ if(*(row+x)&0x1) {
+ if( last != 1 ){
+ strncat(buffer, black, (size_t)black_s);
+ last = 1;
+ }
+ } else if( last != 0 ){
+ strncat(buffer, white, (size_t)white_s);
+ last = 0;
+ }
+ strncat(buffer, " ", 2);
+ }
+
+ if( last != 0 ){
+ strncat(buffer, white, (size_t)white_s);
+ }
+ for(x = 0; x < margin; x++ ){
+ strncat(buffer, " ", 2);
+ }
+ strncat(buffer, "\033[0m\n", 5);
+ fputs(buffer, fp);
+ }
+
+ /* bottom margin */
+ writeANSI_margin(fp, realwidth, buffer, white, white_s);
+
+ fclose(fp);
+ free(buffer);
+
+ return 0;
+}
+
+static void writeUTF8_margin(FILE* fp, int realwidth, const char* white,
+ const char *reset, const char* full)
+{
+ int x, y;
+
+ for (y = 0; y < margin/2; y++) {
+ fputs(white, fp);
+ for (x = 0; x < realwidth; x++)
+ fputs(full, fp);
+ fputs(reset, fp);
+ fputc('\n', fp);
+ }
+}
+
+static int writeUTF8(const QRcode *qrcode, const char *outfile, int use_ansi, int invert)
+{
+ FILE *fp;
+ int x, y;
+ int realwidth;
+ const char *white, *reset;
+ const char *empty, *lowhalf, *uphalf, *full;
+
+ empty = " ";
+ lowhalf = "\342\226\204";
+ uphalf = "\342\226\200";
+ full = "\342\226\210";
+
+ if (invert) {
+ const char *tmp;
+
+ tmp = empty;
+ empty = full;
+ full = tmp;
+
+ tmp = lowhalf;
+ lowhalf = uphalf;
+ uphalf = tmp;
+ }
+
+ if (use_ansi){
+ if (use_ansi == 2) {
+ white = "\033[38;5;231m\033[48;5;16m";
+ } else {
+ white = "\033[40;37;1m";
+ }
+ reset = "\033[0m";
+ } else {
+ white = "";
+ reset = "";
+ }
+
+ fp = openFile(outfile);
+
+ realwidth = (qrcode->width + margin * 2);
+
+ /* top margin */
+ writeUTF8_margin(fp, realwidth, white, reset, full);
+
+ /* data */
+ for(y = 0; y < qrcode->width; y += 2) {
+ unsigned char *row1, *row2;
+ row1 = qrcode->data + y*qrcode->width;
+ row2 = row1 + qrcode->width;
+
+ fputs(white, fp);
+
+ for (x = 0; x < margin; x++) {
+ fputs(full, fp);
+ }
+
+ for (x = 0; x < qrcode->width; x++) {
+ if(row1[x] & 1) {
+ if(y < qrcode->width - 1 && row2[x] & 1) {
+ fputs(empty, fp);
+ } else {
+ fputs(lowhalf, fp);
+ }
+ } else if(y < qrcode->width - 1 && row2[x] & 1) {
+ fputs(uphalf, fp);
+ } else {
+ fputs(full, fp);
+ }
+ }
+
+ for (x = 0; x < margin; x++)
+ fputs(full, fp);
+
+ fputs(reset, fp);
+ fputc('\n', fp);
+ }
+
+ /* bottom margin */
+ writeUTF8_margin(fp, realwidth, white, reset, full);
+
+ fclose(fp);
+
+ return 0;
+}
+
+static void writeASCII_margin(FILE* fp, int realwidth, char* buffer, int invert)
+{
+ int y, h;
+
+ h = margin;
+
+ memset(buffer, (invert?'#':' '), (size_t)realwidth);
+ buffer[realwidth] = '\n';
+ buffer[realwidth + 1] = '\0';
+ for(y = 0; y < h; y++ ){
+ fputs(buffer, fp);
+ }
+}
+
+static int writeASCII(const QRcode *qrcode, const char *outfile, int invert)
+{
+ FILE *fp;
+ unsigned char *row;
+ int x, y;
+ int realwidth;
+ char *buffer, *p;
+ int buffer_s;
+ char black = '#';
+ char white = ' ';
+
+ if(invert) {
+ black = ' ';
+ white = '#';
+ }
+
+ size = 1;
+
+ fp = openFile(outfile);
+
+ realwidth = (qrcode->width + margin * 2) * 2;
+ buffer_s = realwidth + 2;
+ buffer = (char *)malloc((size_t)buffer_s);
+ if(buffer == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ /* top margin */
+ writeASCII_margin(fp, realwidth, buffer, invert);
+
+ /* data */
+ for(y = 0; y < qrcode->width; y++) {
+ row = qrcode->data+(y*qrcode->width);
+ p = buffer;
+
+ memset(p, white, (size_t)margin * 2);
+ p += margin * 2;
+
+ for(x = 0; x < qrcode->width; x++) {
+ if(row[x]&0x1) {
+ *p++ = black;
+ *p++ = black;
+ } else {
+ *p++ = white;
+ *p++ = white;
+ }
+ }
+
+ memset(p, white, (size_t)margin * 2);
+ p += margin * 2;
+ *p++ = '\n';
+ *p++ = '\0';
+ fputs( buffer, fp );
+ }
+
+ /* bottom margin */
+ writeASCII_margin(fp, realwidth, buffer, invert);
+
+ fclose(fp);
+ free(buffer);
+
+ return 0;
+}
+
+static QRcode *encode(const unsigned char *intext, int length)
+{
+ QRcode *code;
+
+ if(micro) {
+ if(eightbit) {
+ code = QRcode_encodeDataMQR(length, intext, version, level);
+ } else {
+ code = QRcode_encodeStringMQR((const char *)intext, version, level, hint, casesensitive);
+ }
+ } else if(eightbit) {
+ code = QRcode_encodeData(length, intext, version, level);
+ } else {
+ code = QRcode_encodeString((const char *)intext, version, level, hint, casesensitive);
+ }
+
+ return code;
+}
+
+static void qrencode(const unsigned char *intext, int length, const char *outfile)
+{
+ QRcode *qrcode;
+
+ qrcode = encode(intext, length);
+ if(qrcode == NULL) {
+ if(errno == ERANGE) {
+ fprintf(stderr, "Failed to encode the input data: Input data too large\n");
+ } else {
+ perror("Failed to encode the input data");
+ }
+ exit(EXIT_FAILURE);
+ }
+ if(strict_versioning && version > 0 && qrcode->version != version) {
+ fprintf(stderr, "Failed to encode the input data: Input data too large\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(verbose) {
+ fprintf(stderr, "File: %s, Version: %d\n", (outfile!=NULL)?outfile:"(stdout)", qrcode->version);
+ }
+
+ switch(image_type) {
+ case PNG_TYPE:
+ case PNG32_TYPE:
+ writePNG(qrcode, outfile, image_type);
+ break;
+ case EPS_TYPE:
+ writeEPS(qrcode, outfile);
+ break;
+ case SVG_TYPE:
+ writeSVG(qrcode, outfile);
+ break;
+ case XPM_TYPE:
+ writeXPM(qrcode, outfile);
+ break;
+ case ANSI_TYPE:
+ case ANSI256_TYPE:
+ writeANSI(qrcode, outfile);
+ break;
+ case ASCII_TYPE:
+ writeASCII(qrcode, outfile, 1);
+ break;
+ case ASCIIi_TYPE:
+ writeASCII(qrcode, outfile, 0);
+ break;
+ case UTF8_TYPE:
+ writeUTF8(qrcode, outfile, 0, 0);
+ break;
+ case ANSIUTF8_TYPE:
+ writeUTF8(qrcode, outfile, 1, 0);
+ break;
+ case ANSI256UTF8_TYPE:
+ writeUTF8(qrcode, outfile, 2, 0);
+ break;
+ case UTF8i_TYPE:
+ writeUTF8(qrcode, outfile, 0, 1);
+ break;
+ case ANSIUTF8i_TYPE:
+ writeUTF8(qrcode, outfile, 1, 1);
+ break;
+ }
+
+ QRcode_free(qrcode);
+}
+
+static QRcode_List *encodeStructured(const unsigned char *intext, int length)
+{
+ QRcode_List *list;
+
+ if(eightbit) {
+ list = QRcode_encodeDataStructured(length, intext, version, level);
+ } else {
+ list = QRcode_encodeStringStructured((const char *)intext, version, level, hint, casesensitive);
+ }
+
+ return list;
+}
+
+static void qrencodeStructured(const unsigned char *intext, int length, const char *outfile)
+{
+ QRcode_List *qrlist, *p;
+ char filename[FILENAME_MAX];
+ char *base, *q, *suffix = NULL;
+ const char *type_suffix;
+ int i = 1;
+ size_t suffix_size;
+
+ switch(image_type) {
+ case PNG_TYPE:
+ case PNG32_TYPE:
+ type_suffix = ".png";
+ break;
+ case EPS_TYPE:
+ type_suffix = ".eps";
+ break;
+ case SVG_TYPE:
+ type_suffix = ".svg";
+ break;
+ case XPM_TYPE:
+ type_suffix = ".xpm";
+ break;
+ case ANSI_TYPE:
+ case ANSI256_TYPE:
+ case ANSI256UTF8_TYPE:
+ case ASCII_TYPE:
+ case ASCIIi_TYPE:
+ case UTF8_TYPE:
+ case ANSIUTF8_TYPE:
+ case UTF8i_TYPE:
+ case ANSIUTF8i_TYPE:
+ type_suffix = ".txt";
+ break;
+ }
+
+ if(outfile == NULL) {
+ fprintf(stderr, "An output filename must be specified to store the structured images.\n");
+ exit(EXIT_FAILURE);
+ }
+ base = strdup(outfile);
+ if(base == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+ suffix_size = strlen(type_suffix);
+ if(strlen(base) > suffix_size) {
+ q = base + strlen(base) - suffix_size;
+ if(strcasecmp(type_suffix, q) == 0) {
+ suffix = strdup(q);
+ *q = '\0';
+ }
+ }
+
+ qrlist = encodeStructured(intext, length);
+ if(qrlist == NULL) {
+ if(errno == ERANGE) {
+ fprintf(stderr, "Failed to encode the input data: Input data too large\n");
+ } else {
+ perror("Failed to encode the input data");
+ }
+ exit(EXIT_FAILURE);
+ }
+
+ for(p = qrlist; p != NULL; p = p->next) {
+ if(p->code == NULL) {
+ fprintf(stderr, "Failed to encode the input data.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(suffix) {
+ snprintf(filename, FILENAME_MAX, "%s-%02d%s", base, i, suffix);
+ } else {
+ snprintf(filename, FILENAME_MAX, "%s-%02d", base, i);
+ }
+
+ if(verbose) {
+ fprintf(stderr, "File: %s, Version: %d\n", filename, p->code->version);
+ }
+
+ switch(image_type) {
+ case PNG_TYPE:
+ case PNG32_TYPE:
+ writePNG(p->code, filename, image_type);
+ break;
+ case EPS_TYPE:
+ writeEPS(p->code, filename);
+ break;
+ case SVG_TYPE:
+ writeSVG(p->code, filename);
+ break;
+ case XPM_TYPE:
+ writeXPM(p->code, filename);
+ break;
+ case ANSI_TYPE:
+ case ANSI256_TYPE:
+ writeANSI(p->code, filename);
+ break;
+ case ASCII_TYPE:
+ writeASCII(p->code, filename, 1);
+ break;
+ case ASCIIi_TYPE:
+ writeASCII(p->code, filename, 0);
+ break;
+ case UTF8_TYPE:
+ writeUTF8(p->code, filename, 0, 0);
+ break;
+ case ANSIUTF8_TYPE:
+ writeUTF8(p->code, filename, 1, 0);
+ break;
+ case ANSI256UTF8_TYPE:
+ writeUTF8(p->code, filename, 2, 0);
+ break;
+ case UTF8i_TYPE:
+ writeUTF8(p->code, filename, 0, 1);
+ break;
+ case ANSIUTF8i_TYPE:
+ writeUTF8(p->code, filename, 1, 1);
+ break;
+ }
+ i++;
+ }
+
+ free(base);
+ if(suffix) {
+ free(suffix);
+ }
+
+ QRcode_List_free(qrlist);
+}
+
+int main(int argc, char **argv)
+{
+ int opt, lindex = -1;
+ char *outfile = NULL, *infile = NULL;
+ unsigned char *intext = NULL;
+ int length = 0;
+ FILE *fp;
+
+ while((opt = getopt_long(argc, argv, optstring, options, &lindex)) != -1) {
+ switch(opt) {
+ case 'h':
+ if(lindex == 0) {
+ usage(1, 1, EXIT_SUCCESS);
+ } else {
+ usage(1, 0, EXIT_SUCCESS);
+ }
+ exit(EXIT_SUCCESS);
+ case 'o':
+ outfile = optarg;
+ break;
+ case 'r':
+ infile = optarg;
+ break;
+ case 's':
+ size = atoi(optarg);
+ if(size <= 0) {
+ fprintf(stderr, "Invalid size: %d\n", size);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'v':
+ version = atoi(optarg);
+ if(version < 0) {
+ fprintf(stderr, "Invalid version: %d\n", version);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'l':
+ switch(*optarg) {
+ case 'l':
+ case 'L':
+ level = QR_ECLEVEL_L;
+ break;
+ case 'm':
+ case 'M':
+ level = QR_ECLEVEL_M;
+ break;
+ case 'q':
+ case 'Q':
+ level = QR_ECLEVEL_Q;
+ break;
+ case 'h':
+ case 'H':
+ level = QR_ECLEVEL_H;
+ break;
+ default:
+ fprintf(stderr, "Invalid level: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'm':
+ margin = atoi(optarg);
+ if(margin < 0) {
+ fprintf(stderr, "Invalid margin: %d\n", margin);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'd':
+ dpi = atoi(optarg);
+ if( dpi < 0 ) {
+ fprintf(stderr, "Invalid DPI: %d\n", dpi);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 't':
+ if(strcasecmp(optarg, "png32") == 0) {
+ image_type = PNG32_TYPE;
+ } else if(strcasecmp(optarg, "png") == 0) {
+ image_type = PNG_TYPE;
+ } else if(strcasecmp(optarg, "eps") == 0) {
+ image_type = EPS_TYPE;
+ } else if(strcasecmp(optarg, "svg") == 0) {
+ image_type = SVG_TYPE;
+ } else if(strcasecmp(optarg, "xpm") == 0) {
+ image_type = XPM_TYPE;
+ } else if(strcasecmp(optarg, "ansi") == 0) {
+ image_type = ANSI_TYPE;
+ } else if(strcasecmp(optarg, "ansi256") == 0) {
+ image_type = ANSI256_TYPE;
+ } else if(strcasecmp(optarg, "asciii") == 0) {
+ image_type = ASCIIi_TYPE;
+ } else if(strcasecmp(optarg, "ascii") == 0) {
+ image_type = ASCII_TYPE;
+ } else if(strcasecmp(optarg, "utf8") == 0) {
+ image_type = UTF8_TYPE;
+ } else if(strcasecmp(optarg, "ansiutf8") == 0) {
+ image_type = ANSIUTF8_TYPE;
+ } else if(strcasecmp(optarg, "ansi256utf8") == 0) {
+ image_type = ANSI256UTF8_TYPE;
+ } else if(strcasecmp(optarg, "utf8i") == 0) {
+ image_type = UTF8i_TYPE;
+ } else if(strcasecmp(optarg, "ansiutf8i") == 0) {
+ image_type = ANSIUTF8i_TYPE;
+ } else {
+ fprintf(stderr, "Invalid image type: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'S':
+ structured = 1;
+ break;
+ case 'k':
+ hint = QR_MODE_KANJI;
+ break;
+ case 'c':
+ casesensitive = 1;
+ break;
+ case 'i':
+ casesensitive = 0;
+ break;
+ case '8':
+ eightbit = 1;
+ break;
+ case 'M':
+ micro = 1;
+ break;
+ case 'f':
+ if(color_set(fg_color, optarg)) {
+ fprintf(stderr, "Invalid foreground color value.\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'b':
+ if(color_set(bg_color, optarg)) {
+ fprintf(stderr, "Invalid background color value.\n");
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'V':
+ usage(0, 0, EXIT_SUCCESS);
+ exit(EXIT_SUCCESS);
+ case 0:
+ break;
+ default:
+ fprintf(stderr, "Try \"qrencode --help\" for more information.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if(argc == 1) {
+ usage(1, 0, EXIT_FAILURE);
+ exit(EXIT_FAILURE);
+ }
+
+ if(outfile == NULL && image_type == PNG_TYPE) {
+ fprintf(stderr, "No output filename is given.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(optind < argc) {
+ intext = (unsigned char *)argv[optind];
+ length = (int)strlen((char *)intext);
+ }
+ if(intext == NULL) {
+ fp = infile == NULL ? stdin : fopen(infile, "r");
+ if(fp == 0) {
+ fprintf(stderr, "Cannot read input file %s.\n", infile);
+ exit(EXIT_FAILURE);
+ }
+ intext = readFile(fp, &length);
+
+ }
+
+ if(micro && version > MQRSPEC_VERSION_MAX) {
+ fprintf(stderr, "Version number should be less or equal to %d.\n", MQRSPEC_VERSION_MAX);
+ exit(EXIT_FAILURE);
+ } else if(!micro && version > QRSPEC_VERSION_MAX) {
+ fprintf(stderr, "Version number should be less or equal to %d.\n", QRSPEC_VERSION_MAX);
+ exit(EXIT_FAILURE);
+ }
+
+ if(margin < 0) {
+ if(micro) {
+ margin = 2;
+ } else {
+ margin = 4;
+ }
+ }
+
+ if(micro) {
+ if(structured) {
+ fprintf(stderr, "Micro QR Code does not support structured symbols.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if(structured) {
+ if(version == 0) {
+ fprintf(stderr, "Version number must be specified to encode structured symbols.\n");
+ exit(EXIT_FAILURE);
+ }
+ qrencodeStructured(intext, length, outfile);
+ } else {
+ qrencode(intext, length, outfile);
+ }
+
+ return 0;
+}
diff --git a/genqrcode/qrencode.1.in b/genqrcode/qrencode.1.in
new file mode 100644
index 0000000000..c61e0b1ad9
--- /dev/null
+++ b/genqrcode/qrencode.1.in
@@ -0,0 +1,140 @@
+.TH QRENCODE 1 "Aug. 28, 2020" "qrencode @VERSION@"
+.SH NAME
+qrencode \- Encode input data in a QR Code and save as a PNG or EPS image.
+.SH SYNOPSIS
+.B "qrencode"
+[-o FILENAME]
+[OPTION]...
+[STRING]
+
+.SH DESCRIPTION
+Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
+symbology that can be scanned by handy terminals such as a mobile phone with
+CCD. The capacity of QR Code is up to 7000 digits or 4000 characters, and has
+high robustness.
+
+Qrencode is a utility software using libqrencode to encode string data in
+a QR Code and save as a PNG or EPS image.
+
+.SH OPTIONS
+.TP
+.B \-h, \-\-help
+display help message.
+.TP
+.B \-o FILENAME, \-\-output=FILENAME
+write image to FILENAME. If '\-' is specified, the result will be output to standard output. If \-S is given, structured symbols are written to FILENAME-01.png, FILENAME-02.png, ... (suffix is removed from FILENAME, if specified)
+.TP
+.B \-r FILENAME, \-\-read\-from=FILENAME
+read input data from FILENAME.
+.TP
+.B \-s NUMBER, \-\-size=NUMBER
+specify the size of dot (pixel). (default=3)
+.TP
+.B \-l {LMQH}, \-\-level={LMQH}
+specify error correction level from L (lowest) to H (highest). (default=L)
+.TP
+.B \-v NUMBER, \-\-symversion=NUMBER
+specify the minimum version of the symbol. See SYMBOL VERSIONS for more information. (default=auto)
+.TP
+.B \-m NUMBER, \-\-margin=NUMBER
+specify the width of margin. (default=4)
+.TP
+.B \-d NUMBER, \-\-dpi=NUMBER
+specify the DPI of the generated PNG. (default=72)
+.TP
+.PD 0
+.B \-t {PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}
+.TP
+.PD
+.B \-\-type={PNG,PNG32,EPS,SVG,XPM,ANSI,ANSI256,ASCII,ASCIIi,UTF8,UTF8i,ANSIUTF8,ANSIUTF8i,ANSI256UTF8}
+specify the type of the generated image. (default=PNG)
+.br
+If ASCII*, UTF8*, or ANSI* is specified, the image will be displayed in the terminal by using
+text characters instead of generating an image file. If the name of the type is followed by 'i',
+the light/dark character will be reversed.
+.TP
+.B \-S, \-\-structured
+make structured symbols. Version number must be specified with '-v'.
+.TP
+.B \-k, \-\-kanji
+assume that the input text contains kanji (shift-jis).
+.TP
+.B \-c, \-\-casesensitive
+encode lower-case alphabet characters in 8-bit mode. (default)
+.TP
+.B \-i, \-\-ignorecase
+ignore case distinctions and use only upper-case characters.
+.TP
+.B \-8, \-\-8bit
+encode entire data in 8-bit mode. \-k, \-c and \-i will be ignored.
+.TP
+.B \-M, \-\-micro
+encode in a Micro QR Code. See MICRO QR CODE for more information.
+.TP
+.B \-\-rle
+enable run-length encoding for SVG.
+.TP
+.B \-\-svg-path
+use single path to draw modules for SVG.
+.TP
+.B \-\-inline
+only useful for SVG output, generates an SVG without the XML tag.
+.TP
+.PD 0
+.B \-\-foreground=RRGGBB[AA]
+.TP
+.PD
+.B \-\-background=RRGGBB[AA]
+specify foreground/background color in hexadecimal notation.
+6-digit (RGB) or 8-digit (RGBA) form are supported.
+Color output support available only in PNG, EPS and SVG.
+.TP
+.B \-\-strict\-version
+disable automatic version number adjustment. If the input data is
+too large for the specified version, the program exits with the
+code of 1.
+.TP
+.B \-V, \-\-version
+display the version number and copyrights of the qrencode.
+.TP
+.B \-\-verbose
+display verbose information to stderr.
+.TP
+.B [STRING]
+input data. If it is not specified, data will be taken from standard input.
+
+.SH SYMBOL VERSIONS
+The symbol versions of QR Code range from Version 1 to Version 40.
+Each version has a different module configuration or number of modules,
+ranging from Version 1 (21 x 21 modules) up to Version 40 (177 x 177 modules).
+Each higher version number comprises 4 additional modules per side by default.
+See http://www.qrcode.com/en/about/version.html for a detailed version list.
+
+.SH MICRO QR CODE
+With Micro QR Code, You can embed data in a smaller area than with QR Code,
+but the data capacity is strongly limited. The symbol versions range from
+Version 1 to 4.
+
+.SH EXAMPLES
+.TP
+.B qrencode \-l L \-v 1 \-o output.png 'Hello, world!'
+encode into a symbol version 1, level L.
+.TP
+.B qrencode \-iSv 1 \-\-output=output.png
+read standard input and encode it into a structured-appended symbols in
+case-insensitive mode.
+.TP
+.B qrencode \-S \-v 40 \-l L \-r bigfile.txt \-o output.png
+read input data from bigfile.txt and encode into a symbol version 40, level L.
+
+.SH AUTHOR
+Written by Kentaro Fukuchi.
+
+.SH RESOURCES
+.TP
+Main Web Site: https://fukuchi.org/works/qrencode/
+.TP
+Source code repository: https://github.com/fukuchi/libqrencode/
+
+.SH COPYRIGHT
+Copyright (C) 2006-2018, 2020 Kentaro Fukuchi.
diff --git a/genqrcode/qrencode.c b/genqrcode/qrencode.c
new file mode 100644
index 0000000000..948d1626ce
--- /dev/null
+++ b/genqrcode/qrencode.c
@@ -0,0 +1,921 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Copyright (C) 2006-2018, 2020 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "qrencode.h"
+#include "qrspec.h"
+#include "mqrspec.h"
+#include "bitstream.h"
+#include "qrinput.h"
+#include "rsecc.h"
+#include "split.h"
+#include "mask.h"
+#include "mmask.h"
+
+/******************************************************************************
+ * Raw code
+ *****************************************************************************/
+
+typedef struct {
+ int dataLength;
+ int eccLength;
+ unsigned char *data;
+ unsigned char *ecc;
+} RSblock;
+
+typedef struct {
+ int version;
+ int dataLength;
+ int eccLength;
+ unsigned char *datacode;
+ unsigned char *ecccode;
+ int b1;
+ int blocks;
+ RSblock *rsblock;
+ int count;
+} QRRawCode;
+
+static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc)
+{
+ block->dataLength = dl;
+ block->data = data;
+ block->eccLength = el;
+ block->ecc = ecc;
+
+ RSECC_encode((size_t)dl, (size_t)el, data, ecc);
+}
+
+static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc)
+{
+ int i;
+ RSblock *block;
+ unsigned char *dp, *ep;
+ int el, dl;
+
+ dl = QRspec_rsDataCodes1(spec);
+ el = QRspec_rsEccCodes1(spec);
+
+ block = blocks;
+ dp = data;
+ ep = ecc;
+ for(i = 0; i < QRspec_rsBlockNum1(spec); i++) {
+ RSblock_initBlock(block, dl, dp, el, ep);
+ dp += dl;
+ ep += el;
+ block++;
+ }
+
+ if(QRspec_rsBlockNum2(spec) == 0) return 0;
+
+ dl = QRspec_rsDataCodes2(spec);
+ el = QRspec_rsEccCodes2(spec);
+ for(i = 0; i < QRspec_rsBlockNum2(spec); i++) {
+ RSblock_initBlock(block, dl, dp, el, ep);
+ dp += dl;
+ ep += el;
+ block++;
+ }
+
+ return 0;
+}
+
+STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw);
+STATIC_IN_RELEASE QRRawCode *QRraw_new(QRinput *input)
+{
+ QRRawCode *raw;
+ int spec[5], ret;
+
+ raw = (QRRawCode *)malloc(sizeof(QRRawCode));
+ if(raw == NULL) return NULL;
+
+ raw->datacode = QRinput_getByteStream(input);
+ if(raw->datacode == NULL) {
+ free(raw);
+ return NULL;
+ }
+
+ QRspec_getEccSpec(input->version, input->level, spec);
+
+ raw->version = input->version;
+ raw->b1 = QRspec_rsBlockNum1(spec);
+ raw->dataLength = QRspec_rsDataLength(spec);
+ raw->eccLength = QRspec_rsEccLength(spec);
+ raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
+ if(raw->ecccode == NULL) {
+ free(raw->datacode);
+ free(raw);
+ return NULL;
+ }
+
+ raw->blocks = QRspec_rsBlockNum(spec);
+ raw->rsblock = (RSblock *)calloc((size_t)(raw->blocks), sizeof(RSblock));
+ if(raw->rsblock == NULL) {
+ QRraw_free(raw);
+ return NULL;
+ }
+ ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode);
+ if(ret < 0) {
+ QRraw_free(raw);
+ return NULL;
+ }
+
+ raw->count = 0;
+
+ return raw;
+}
+
+/**
+ * Return a code (byte).
+ * This function can be called iteratively.
+ * @param raw raw code.
+ * @return code
+ */
+STATIC_IN_RELEASE unsigned char QRraw_getCode(QRRawCode *raw)
+{
+ int col, row;
+ unsigned char ret;
+
+ if(raw->count < raw->dataLength) {
+ row = raw->count % raw->blocks;
+ col = raw->count / raw->blocks;
+ if(col >= raw->rsblock[0].dataLength) {
+ row += raw->b1;
+ }
+ ret = raw->rsblock[row].data[col];
+ } else if(raw->count < raw->dataLength + raw->eccLength) {
+ row = (raw->count - raw->dataLength) % raw->blocks;
+ col = (raw->count - raw->dataLength) / raw->blocks;
+ ret = raw->rsblock[row].ecc[col];
+ } else {
+ return 0;
+ }
+ raw->count++;
+ return ret;
+}
+
+STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw)
+{
+ if(raw != NULL) {
+ free(raw->datacode);
+ free(raw->ecccode);
+ free(raw->rsblock);
+ free(raw);
+ }
+}
+
+/******************************************************************************
+ * Raw code for Micro QR Code
+ *****************************************************************************/
+
+typedef struct {
+ int version;
+ int dataLength;
+ int eccLength;
+ unsigned char *datacode;
+ unsigned char *ecccode;
+ RSblock *rsblock;
+ int oddbits;
+ int count;
+} MQRRawCode;
+
+STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw);
+STATIC_IN_RELEASE MQRRawCode *MQRraw_new(QRinput *input)
+{
+ MQRRawCode *raw;
+
+ raw = (MQRRawCode *)malloc(sizeof(MQRRawCode));
+ if(raw == NULL) return NULL;
+
+ raw->version = input->version;
+ raw->dataLength = MQRspec_getDataLength(input->version, input->level);
+ raw->eccLength = MQRspec_getECCLength(input->version, input->level);
+ raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level);
+ raw->datacode = QRinput_getByteStream(input);
+ if(raw->datacode == NULL) {
+ free(raw);
+ return NULL;
+ }
+ raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength);
+ if(raw->ecccode == NULL) {
+ free(raw->datacode);
+ free(raw);
+ return NULL;
+ }
+
+ raw->rsblock = (RSblock *)calloc(1, sizeof(RSblock));
+ if(raw->rsblock == NULL) {
+ MQRraw_free(raw);
+ return NULL;
+ }
+
+ RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode);
+
+ raw->count = 0;
+
+ return raw;
+}
+
+/**
+ * Return a code (byte).
+ * This function can be called iteratively.
+ * @param raw raw code.
+ * @return code
+ */
+STATIC_IN_RELEASE unsigned char MQRraw_getCode(MQRRawCode *raw)
+{
+ unsigned char ret;
+
+ if(raw->count < raw->dataLength) {
+ ret = raw->datacode[raw->count];
+ } else if(raw->count < raw->dataLength + raw->eccLength) {
+ ret = raw->ecccode[raw->count - raw->dataLength];
+ } else {
+ return 0;
+ }
+ raw->count++;
+ return ret;
+}
+
+STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw)
+{
+ if(raw != NULL) {
+ free(raw->datacode);
+ free(raw->ecccode);
+ free(raw->rsblock);
+ free(raw);
+ }
+}
+
+
+/******************************************************************************
+ * Frame filling
+ *****************************************************************************/
+
+typedef struct {
+ int width;
+ unsigned char *frame;
+ int x, y;
+ int dir;
+ int bit;
+ int mqr;
+} FrameFiller;
+
+static void FrameFiller_set(FrameFiller *filler, int width, unsigned char *frame, int mqr)
+{
+ filler->width = width;
+ filler->frame = frame;
+ filler->x = width - 1;
+ filler->y = width - 1;
+ filler->dir = -1;
+ filler->bit = -1;
+ filler->mqr = mqr;
+}
+
+static unsigned char *FrameFiller_next(FrameFiller *filler)
+{
+ int x, y, w;
+
+ x = filler->x;
+ y = filler->y;
+ w = filler->width;
+ for(;;) {
+ if(filler->bit == -1) {
+ filler->bit = 0;
+ break;
+ }
+
+ if(filler->bit == 0) {
+ x--;
+ filler->bit++;
+ } else {
+ x++;
+ y += filler->dir;
+ filler->bit--;
+ }
+
+ if(filler->dir < 0) {
+ if(y < 0) {
+ y = 0;
+ x -= 2;
+ filler->dir = 1;
+ if(!filler->mqr && x == 6) {
+ x--;
+ y = 9;
+ }
+ }
+ } else if(y == w) {
+ y = w - 1;
+ x -= 2;
+ filler->dir = -1;
+ if(!filler->mqr && x == 6) {
+ x--;
+ y -= 8;
+ }
+ }
+ if(x < 0 || y < 0) return NULL;
+
+ if(!(filler->frame[y * w + x] & 0x80)) {
+ break;
+ }
+ }
+ filler->x = x;
+ filler->y = y;
+ return &filler->frame[filler->y * w + filler->x];
+}
+
+#ifdef WITH_TESTS
+unsigned char *FrameFiller_test(int version)
+{
+ int width;
+ unsigned char *frame, *p;
+ int i, length;
+ FrameFiller filler;
+
+ width = QRspec_getWidth(version);
+ frame = QRspec_newFrame(version);
+ if(frame == NULL) return NULL;
+ FrameFiller_set(&filler, width, frame, 0);
+ length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8
+ + QRspec_getECCLength(version, QR_ECLEVEL_L) * 8
+ + QRspec_getRemainder(version);
+ for(i = 0; i < length; i++) {
+ p = FrameFiller_next(&filler);
+ if(p == NULL) {
+ free(frame);
+ return NULL;
+ }
+ *p = (unsigned char)(i & 0x7f) | 0x80;
+ }
+ return frame;
+}
+
+unsigned char *FrameFiller_testMQR(int version)
+{
+ int width;
+ unsigned char *frame, *p;
+ int i, length;
+ FrameFiller filler;
+
+ width = MQRspec_getWidth(version);
+ frame = MQRspec_newFrame(version);
+ if(frame == NULL) return NULL;
+ FrameFiller_set(&filler, width, frame, 1);
+ length = MQRspec_getDataLengthBit(version, QR_ECLEVEL_L)
+ + MQRspec_getECCLength(version, QR_ECLEVEL_L) * 8;
+ for(i = 0; i < length; i++) {
+ p = FrameFiller_next(&filler);
+ if(p == NULL) {
+ fprintf(stderr, "Frame filler run over the frame!\n");
+ return frame;
+ }
+ *p = (unsigned char)(i & 0x7f) | 0x80;
+ }
+ return frame;
+}
+#endif
+
+
+/******************************************************************************
+ * QR-code encoding
+ *****************************************************************************/
+
+STATIC_IN_RELEASE QRcode *QRcode_new(int version, int width, unsigned char *data)
+{
+ QRcode *qrcode;
+
+ qrcode = (QRcode *)malloc(sizeof(QRcode));
+ if(qrcode == NULL) return NULL;
+
+ qrcode->version = version;
+ qrcode->width = width;
+ qrcode->data = data;
+
+ return qrcode;
+}
+
+void QRcode_free(QRcode *qrcode)
+{
+ if(qrcode != NULL) {
+ free(qrcode->data);
+ free(qrcode);
+ }
+}
+
+STATIC_IN_RELEASE QRcode *QRcode_encodeMask(QRinput *input, int mask)
+{
+ int width, version;
+ QRRawCode *raw;
+ unsigned char *frame, *masked, *p, code, bit;
+ int i, j;
+ QRcode *qrcode = NULL;
+ FrameFiller filler;
+
+ if(input->mqr) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_H)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ raw = QRraw_new(input);
+ if(raw == NULL) return NULL;
+
+ version = raw->version;
+ width = QRspec_getWidth(version);
+ frame = QRspec_newFrame(version);
+ if(frame == NULL) {
+ QRraw_free(raw);
+ return NULL;
+ }
+ FrameFiller_set(&filler, width, frame, 0);
+
+ /* interleaved data and ecc codes */
+ for(i = 0; i < raw->dataLength; i++) {
+ code = QRraw_getCode(raw);
+ bit = 0x80;
+ for(j = 0; j < 8; j++) {
+ p = FrameFiller_next(&filler);
+ if(p == NULL) goto EXIT;
+ *p = ((bit & code) != 0);
+ bit = bit >> 1;
+ }
+ }
+ for(i = 0; i < raw->eccLength; i++) {
+ code = QRraw_getCode(raw);
+ bit = 0x80;
+ for(j = 0; j < 8; j++) {
+ p = FrameFiller_next(&filler);
+ if(p == NULL) goto EXIT;
+ *p = 0x02 | ((bit & code) != 0);
+ bit = bit >> 1;
+ }
+ }
+ QRraw_free(raw);
+ raw = NULL;
+ /* remainder bits */
+ j = QRspec_getRemainder(version);
+ for(i = 0; i < j; i++) {
+ p = FrameFiller_next(&filler);
+ if(p == NULL) goto EXIT;
+ *p = 0x02;
+ }
+
+ /* masking */
+ if(mask == -2) { // just for debug purpose
+ masked = (unsigned char *)malloc((size_t)(width * width));
+ memcpy(masked, frame, (size_t)(width * width));
+ } else if(mask < 0) {
+ masked = Mask_mask(width, frame, input->level);
+ } else {
+ masked = Mask_makeMask(width, frame, mask, input->level);
+ }
+ if(masked == NULL) {
+ goto EXIT;
+ }
+ qrcode = QRcode_new(version, width, masked);
+ if(qrcode == NULL) {
+ free(masked);
+ }
+
+EXIT:
+ QRraw_free(raw);
+ free(frame);
+ return qrcode;
+}
+
+STATIC_IN_RELEASE QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask)
+{
+ int width, version;
+ MQRRawCode *raw;
+ unsigned char *frame, *masked, *p, code, bit;
+ int i, j, length;
+ QRcode *qrcode = NULL;
+ FrameFiller filler;
+
+ if(!input->mqr) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_Q)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ raw = MQRraw_new(input);
+ if(raw == NULL) return NULL;
+
+ version = raw->version;
+ width = MQRspec_getWidth(version);
+ frame = MQRspec_newFrame(version);
+ if(frame == NULL) {
+ MQRraw_free(raw);
+ return NULL;
+ }
+ FrameFiller_set(&filler, width, frame, 1);
+
+ /* interleaved data and ecc codes */
+ for(i = 0; i < raw->dataLength; i++) {
+ code = MQRraw_getCode(raw);
+ bit = 0x80;
+ if(raw->oddbits && i == raw->dataLength - 1) {
+ length = raw->oddbits;
+ } else {
+ length = 8;
+ }
+ for(j = 0; j < length; j++) {
+ p = FrameFiller_next(&filler);
+ if(p == NULL) goto EXIT;
+ *p = ((bit & code) != 0);
+ bit = bit >> 1;
+ }
+ }
+ for(i = 0; i < raw->eccLength; i++) {
+ code = MQRraw_getCode(raw);
+ bit = 0x80;
+ length = 8;
+ for(j = 0; j < length; j++) {
+ p = FrameFiller_next(&filler);
+ if(p == NULL) goto EXIT;
+ *p = 0x02 | ((bit & code) != 0);
+ bit = bit >> 1;
+ }
+ }
+ MQRraw_free(raw);
+ raw = NULL;
+
+ /* masking */
+ if(mask == -2) { // just for debug purpose
+ masked = (unsigned char *)malloc((size_t)(width * width));
+ memcpy(masked, frame, (size_t)(width * width));
+ } else if(mask < 0) {
+ masked = MMask_mask(version, frame, input->level);
+ } else {
+ masked = MMask_makeMask(version, frame, mask, input->level);
+ }
+ if(masked == NULL) {
+ goto EXIT;
+ }
+
+ qrcode = QRcode_new(version, width, masked);
+ if(qrcode == NULL) {
+ free(masked);
+ }
+
+EXIT:
+ MQRraw_free(raw);
+ free(frame);
+ return qrcode;
+}
+
+QRcode *QRcode_encodeInput(QRinput *input)
+{
+ if(input->mqr) {
+ return QRcode_encodeMaskMQR(input, -1);
+ } else {
+ return QRcode_encodeMask(input, -1);
+ }
+}
+
+static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive)
+{
+ QRinput *input;
+ QRcode *code;
+ int ret;
+
+ if(string == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if(mqr) {
+ input = QRinput_newMQR(version, level);
+ } else {
+ input = QRinput_new2(version, level);
+ }
+ if(input == NULL) return NULL;
+
+ ret = Split_splitStringToQRinput(string, input, hint, casesensitive);
+ if(ret < 0) {
+ QRinput_free(input);
+ return NULL;
+ }
+ code = QRcode_encodeInput(input);
+ QRinput_free(input);
+
+ return code;
+}
+
+QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
+{
+ return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive);
+}
+
+QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
+{
+ int i;
+
+ if(version == 0) {
+ version = 1;
+ }
+ for(i = version; i <= MQRSPEC_VERSION_MAX ; i++) {
+ QRcode *code = QRcode_encodeStringReal(string, i, level, 1, hint, casesensitive);
+ if(code != NULL) return code;
+ }
+
+ return NULL;
+}
+
+static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr)
+{
+ QRinput *input;
+ QRcode *code;
+ int ret;
+
+ if(data == NULL || length == 0) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ if(mqr) {
+ input = QRinput_newMQR(version, level);
+ } else {
+ input = QRinput_new2(version, level);
+ }
+ if(input == NULL) return NULL;
+
+ ret = QRinput_append(input, QR_MODE_8, length, data);
+ if(ret < 0) {
+ QRinput_free(input);
+ return NULL;
+ }
+ code = QRcode_encodeInput(input);
+ QRinput_free(input);
+
+ return code;
+}
+
+QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level)
+{
+ return QRcode_encodeDataReal(data, size, version, level, 0);
+}
+
+QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level)
+{
+ if(string == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return QRcode_encodeDataReal((const unsigned char *)string, (int)strlen(string), version, level, 0);
+}
+
+QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level)
+{
+ int i;
+
+ if(version == 0) {
+ version = 1;
+ }
+ for(i = version; i <= MQRSPEC_VERSION_MAX; i++) {
+ QRcode *code = QRcode_encodeDataReal(data, size, i, level, 1);
+ if(code != NULL) return code;
+ }
+
+ return NULL;
+}
+
+QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level)
+{
+ int i;
+
+ if(string == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if(version == 0) {
+ version = 1;
+ }
+ for(i = version; i <= MQRSPEC_VERSION_MAX; i++) {
+ QRcode *code = QRcode_encodeDataReal((const unsigned char *)string, (int)strlen(string), i, level, 1);
+ if(code != NULL) return code;
+ }
+
+ return NULL;
+}
+
+
+/******************************************************************************
+ * Structured QR-code encoding
+ *****************************************************************************/
+
+static QRcode_List *QRcode_List_newEntry(void)
+{
+ QRcode_List *entry;
+
+ entry = (QRcode_List *)malloc(sizeof(QRcode_List));
+ if(entry == NULL) return NULL;
+
+ entry->next = NULL;
+ entry->code = NULL;
+
+ return entry;
+}
+
+static void QRcode_List_freeEntry(QRcode_List *entry)
+{
+ if(entry != NULL) {
+ QRcode_free(entry->code);
+ free(entry);
+ }
+}
+
+void QRcode_List_free(QRcode_List *qrlist)
+{
+ QRcode_List *list = qrlist, *next;
+
+ while(list != NULL) {
+ next = list->next;
+ QRcode_List_freeEntry(list);
+ list = next;
+ }
+}
+
+int QRcode_List_size(QRcode_List *qrlist)
+{
+ QRcode_List *list = qrlist;
+ int size = 0;
+
+ while(list != NULL) {
+ size++;
+ list = list->next;
+ }
+
+ return size;
+}
+
+QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s)
+{
+ QRcode_List *head = NULL;
+ QRcode_List *tail = NULL;
+ QRcode_List *entry;
+ QRinput_InputList *list = s->head;
+
+ while(list != NULL) {
+ if(head == NULL) {
+ entry = QRcode_List_newEntry();
+ if(entry == NULL) goto ABORT;
+ head = entry;
+ tail = head;
+ } else {
+ entry = QRcode_List_newEntry();
+ if(entry == NULL) goto ABORT;
+ tail->next = entry;
+ tail = tail->next;
+ }
+ tail->code = QRcode_encodeInput(list->input);
+ if(tail->code == NULL) {
+ goto ABORT;
+ }
+ list = list->next;
+ }
+
+ return head;
+ABORT:
+ QRcode_List_free(head);
+ return NULL;
+}
+
+static QRcode_List *QRcode_encodeInputToStructured(QRinput *input)
+{
+ QRinput_Struct *s;
+ QRcode_List *codes;
+
+ s = QRinput_splitQRinputToStruct(input);
+ if(s == NULL) return NULL;
+
+ codes = QRcode_encodeInputStructured(s);
+ QRinput_Struct_free(s);
+
+ return codes;
+}
+
+static QRcode_List *QRcode_encodeDataStructuredReal(
+ int size, const unsigned char *data,
+ int version, QRecLevel level,
+ int eightbit, QRencodeMode hint, int casesensitive)
+{
+ QRinput *input;
+ QRcode_List *codes;
+ int ret;
+
+ if(version <= 0) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ input = QRinput_new2(version, level);
+ if(input == NULL) return NULL;
+
+ if(eightbit) {
+ ret = QRinput_append(input, QR_MODE_8, size, data);
+ } else {
+ ret = Split_splitStringToQRinput((const char *)data, input, hint, casesensitive);
+ }
+ if(ret < 0) {
+ QRinput_free(input);
+ return NULL;
+ }
+ codes = QRcode_encodeInputToStructured(input);
+ QRinput_free(input);
+
+ return codes;
+}
+
+QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) {
+ return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0);
+}
+
+QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) {
+ if(string == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return QRcode_encodeDataStructured((int)strlen(string), (const unsigned char *)string, version, level);
+}
+
+QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive)
+{
+ if(string == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return QRcode_encodeDataStructuredReal((int)strlen(string), (const unsigned char *)string, version, level, 0, hint, casesensitive);
+}
+
+/******************************************************************************
+ * System utilities
+ *****************************************************************************/
+
+void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version)
+{
+ if(major_version != NULL) {
+ *major_version = MAJOR_VERSION;
+ }
+ if(minor_version != NULL) {
+ *minor_version = MINOR_VERSION;
+ }
+ if(micro_version != NULL) {
+ *micro_version = MICRO_VERSION;
+ }
+}
+
+char *QRcode_APIVersionString(void)
+{
+ return VERSION;
+}
+
+void QRcode_clearCache(void)
+{
+ return;
+}
diff --git a/genqrcode/qrencode.h b/genqrcode/qrencode.h
new file mode 100644
index 0000000000..3460866321
--- /dev/null
+++ b/genqrcode/qrencode.h
@@ -0,0 +1,593 @@
+/**
+ * qrencode - QR Code encoder
+ *
+ * Copyright (C) 2006-2018, 2020 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/** \mainpage
+ * Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D
+ * symbology.
+ *
+ * \section encoding Encoding
+ *
+ * There are two methods to encode data: <b>encoding a string/data</b> or
+ * <b>encoding a structured data</b>.
+ *
+ * \subsection encoding-string Encoding a string/data
+ * You can encode a string by calling QRcode_encodeString().
+ * The given string is parsed automatically and encoded. If you want to encode
+ * data that can be represented as a C string style (NUL terminated), you can
+ * simply use this way.
+ *
+ * If the input data contains Kanji (Shift-JIS) characters and you want to
+ * encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint.
+ * Otherwise, all of non-alphanumeric characters are encoded as 8-bit data.
+ * If you want to encode a whole string in 8-bit mode, you can use
+ * QRcode_encodeString8bit() instead.
+ *
+ * Please note that a C string can not contain NUL characters. If your data
+ * contains NUL, you must use QRcode_encodeData().
+ *
+ * \subsection encoding-input Encoding a structured data
+ * You can construct a structured input data manually. If the structure of the
+ * input data is known, you can use this method.
+ * At first, create a ::QRinput object by QRinput_new(). Then add input data
+ * to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput()
+ * to encode the QRinput data.
+ * You can reuse the QRinput object again to encode it in other symbols with
+ * different parameters.
+ *
+ * \section result Result
+ * The encoded symbol is generated as a ::QRcode object. It will contain its
+ * version number, the width of the symbol, and an array represents the symbol.
+ * See ::QRcode for the details. You can free the object by QRcode_free().
+ *
+ * Please note that the version of the result may be larger than specified.
+ * In such cases, the input data would be too large to be encoded in a
+ * symbol of the specified version.
+ *
+ * The following code snippet demonstrates how to use the obtained object:
+ *
+ * \code
+ * QRcode *qrcode;
+ *
+ * qrcode = QRcode_encodeString("TEST", 0, QR_ECLEVEL_M, QR_MODE_8, 1);
+ * if(qrcode == NULL) abort();
+ *
+ * for(int y = 0; y < qrcode->width; y++) {
+ * for(int x = 0; x < qrcode->width; x++) {
+ * if(qrcode->data[y * qrcode->width + x] & 1) {
+ * draw_black_dot(x, y);
+ * } else {
+ * draw_white_dot(x, y);
+ * }
+ * }
+ * }
+ *
+ * QRcode_free(qrcode);
+ * \endcode
+ *
+ * \section structured Structured append
+ * Libqrencode can generate "Structured-appended" symbols that enable to split
+ * a large data set into multiple QR codes. A QR code reader concatenates
+ * multiple QR code symbols into a string.
+ * Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured()
+ * to generate structured-appended symbols. This function returns an instance
+ * of ::QRcode_List. The returned list is a singly-linked list of QRcode: you
+ * can retrieve each QR code in this way:
+ *
+ * \code
+ * QRcode_List *qrcodes;
+ * QRcode_List *entry;
+ * QRcode *qrcode;
+ *
+ * qrcodes = QRcode_encodeStringStructured(...);
+ * entry = qrcodes;
+ * while(entry != NULL) {
+ * qrcode = entry->code;
+ * // do something
+ * entry = entry->next;
+ * }
+ * QRcode_List_free(entry);
+ * \endcode
+ *
+ * Instead of using auto-parsing functions, you can construct your own
+ * structured input. At first, instantiate an object of ::QRinput_Struct
+ * by calling QRinput_Struct_new(). This object can hold multiple ::QRinput,
+ * and one QR code is generated for a ::QRinput.
+ * QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct
+ * object. In order to generate structured-appended symbols, it is required to
+ * embed headers to each symbol. You can use
+ * QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate
+ * headers to each symbol. You should call this function just once before
+ * encoding symbols.
+ */
+
+#ifndef QRENCODE_H
+#define QRENCODE_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/**
+ * Encoding mode.
+ */
+typedef enum {
+ QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only
+ QR_MODE_NUM = 0, ///< Numeric mode
+ QR_MODE_AN, ///< Alphabet-numeric mode
+ QR_MODE_8, ///< 8-bit data mode
+ QR_MODE_KANJI, ///< Kanji (shift-jis) mode
+ QR_MODE_STRUCTURE, ///< Internal use only
+ QR_MODE_ECI, ///< ECI mode
+ QR_MODE_FNC1FIRST, ///< FNC1, first position
+ QR_MODE_FNC1SECOND, ///< FNC1, second position
+} QRencodeMode;
+
+/**
+ * Level of error correction.
+ */
+typedef enum {
+ QR_ECLEVEL_L = 0, ///< lowest
+ QR_ECLEVEL_M,
+ QR_ECLEVEL_Q,
+ QR_ECLEVEL_H ///< highest
+} QRecLevel;
+
+/**
+ * Maximum version (size) of QR-code symbol.
+ */
+#define QRSPEC_VERSION_MAX 40
+
+/**
+ * Maximum version (size) of QR-code symbol.
+ */
+#define MQRSPEC_VERSION_MAX 4
+
+
+/******************************************************************************
+ * Input data (qrinput.c)
+ *****************************************************************************/
+
+/**
+ * Singly linked list to contain input strings. An instance of this class
+ * contains its version and error correction level too. It is required to
+ * set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(),
+ * or use QRinput_new2() to instantiate an object.
+ */
+typedef struct _QRinput QRinput;
+
+/**
+ * Instantiate an input data object. The version is set to 0 (auto-select)
+ * and the error correction level is set to QR_ECLEVEL_L.
+ * @return an input object (initialized). On error, NULL is returned and errno
+ * is set to indicate the error.
+ * @throw ENOMEM unable to allocate memory.
+ */
+extern QRinput *QRinput_new(void);
+
+/**
+ * Instantiate an input data object.
+ * @param version version number.
+ * @param level Error correction level.
+ * @return an input object (initialized). On error, NULL is returned and errno
+ * is set to indicate the error.
+ * @throw ENOMEM unable to allocate memory for input objects.
+ * @throw EINVAL invalid arguments.
+ */
+extern QRinput *QRinput_new2(int version, QRecLevel level);
+
+/**
+ * Instantiate an input data object. Object's Micro QR Code flag is set.
+ * Unlike with full-sized QR Code, version number must be specified (>0).
+ * @param version version number (1--4).
+ * @param level Error correction level.
+ * @return an input object (initialized). On error, NULL is returned and errno
+ * is set to indicate the error.
+ * @throw ENOMEM unable to allocate memory for input objects.
+ * @throw EINVAL invalid arguments.
+ */
+extern QRinput *QRinput_newMQR(int version, QRecLevel level);
+
+/**
+ * Append data to an input object.
+ * The data is copied and appended to the input object.
+ * @param input input object.
+ * @param mode encoding mode.
+ * @param size size of data (byte).
+ * @param data a pointer to the memory area of the input data.
+ * @retval 0 success.
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ * @throw EINVAL input data is invalid.
+ *
+ */
+extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data);
+
+/**
+ * Append ECI header.
+ * @param input input object.
+ * @param ecinum ECI indicator number (0 - 999999)
+ * @retval 0 success.
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ * @throw EINVAL input data is invalid.
+ *
+ */
+extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum);
+
+/**
+ * Get current version.
+ * @param input input object.
+ * @return current version.
+ */
+extern int QRinput_getVersion(QRinput *input);
+
+/**
+ * Set version of the QR code that is to be encoded.
+ * This function cannot be applied to Micro QR Code.
+ * @param input input object.
+ * @param version version number (0 = auto)
+ * @retval 0 success.
+ * @retval -1 invalid argument.
+ */
+extern int QRinput_setVersion(QRinput *input, int version);
+
+/**
+ * Get current error correction level.
+ * @param input input object.
+ * @return Current error correcntion level.
+ */
+extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input);
+
+/**
+ * Set error correction level of the QR code that is to be encoded.
+ * This function cannot be applied to Micro QR Code.
+ * @param input input object.
+ * @param level Error correction level.
+ * @retval 0 success.
+ * @retval -1 invalid argument.
+ */
+extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level);
+
+/**
+ * Set version and error correction level of the QR code at once.
+ * This function is recommened for Micro QR Code.
+ * @param input input object.
+ * @param version version number (0 = auto)
+ * @param level Error correction level.
+ * @retval 0 success.
+ * @retval -1 invalid argument.
+ */
+extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level);
+
+/**
+ * Free the input object.
+ * All of data chunks in the input object are freed too.
+ * @param input input object.
+ */
+extern void QRinput_free(QRinput *input);
+
+/**
+ * Validate the input data.
+ * @param mode encoding mode.
+ * @param size size of data (byte).
+ * @param data a pointer to the memory area of the input data.
+ * @retval 0 success.
+ * @retval -1 invalid arguments.
+ */
+extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data);
+
+/**
+ * Set of QRinput for structured symbols.
+ */
+typedef struct _QRinput_Struct QRinput_Struct;
+
+/**
+ * Instantiate a set of input data object.
+ * @return an instance of QRinput_Struct. On error, NULL is returned and errno
+ * is set to indicate the error.
+ * @throw ENOMEM unable to allocate memory.
+ */
+extern QRinput_Struct *QRinput_Struct_new(void);
+
+/**
+ * Set parity of structured symbols.
+ * @param s structured input object.
+ * @param parity parity of s.
+ */
+extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity);
+
+/**
+ * Append a QRinput object to the set. QRinput created by QRinput_newMQR()
+ * will be rejected.
+ * @warning never append the same QRinput object twice or more.
+ * @param s structured input object.
+ * @param input an input object.
+ * @retval >0 number of input objects in the structure.
+ * @retval -1 an error occurred. See Exceptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ * @throw EINVAL invalid arguments.
+ */
+extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input);
+
+/**
+ * Free all of QRinput in the set.
+ * @param s a structured input object.
+ */
+extern void QRinput_Struct_free(QRinput_Struct *s);
+
+/**
+ * Split a QRinput to QRinput_Struct. It calculates a parity, set it, then
+ * insert structured-append headers. QRinput created by QRinput_newMQR() will
+ * be rejected.
+ * @param input input object. Version number and error correction level must be
+ * set.
+ * @return a set of input data. On error, NULL is returned, and errno is set
+ * to indicate the error. See Exceptions for the details.
+ * @throw ERANGE input data is too large.
+ * @throw EINVAL invalid input data.
+ * @throw ENOMEM unable to allocate memory.
+ */
+extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input);
+
+/**
+ * Insert structured-append headers to the input structure. It calculates
+ * a parity and set it if the parity is not set yet.
+ * @param s input structure
+ * @retval 0 success.
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw EINVAL invalid input object.
+ * @throw ENOMEM unable to allocate memory.
+ */
+extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s);
+
+/**
+ * Set FNC1-1st position flag.
+ */
+extern int QRinput_setFNC1First(QRinput *input);
+
+/**
+ * Set FNC1-2nd position flag and application identifier.
+ */
+extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid);
+
+/******************************************************************************
+ * QRcode output (qrencode.c)
+ *****************************************************************************/
+
+/**
+ * QRcode class.
+ * Symbol data is represented as an array contains width*width uchars.
+ * Each uchar represents a module (dot). If the less significant bit of
+ * the uchar is 1, the corresponding module is black. The other bits are
+ * meaningless for usual applications, but here its specification is described.
+ *
+ * @verbatim
+ MSB 76543210 LSB
+ |||||||`- 1=black/0=white
+ ||||||`-- 1=ecc/0=data code area
+ |||||`--- format information
+ ||||`---- version information
+ |||`----- timing pattern
+ ||`------ alignment pattern
+ |`------- finder pattern and separator
+ `-------- non-data modules (format, timing, etc.)
+ @endverbatim
+ *
+ * See \ref result section for a sample code snippet that shows how to use the
+ * obtained QRcode object.
+ */
+typedef struct {
+ int version; ///< version of the symbol
+ int width; ///< width of the symbol
+ unsigned char *data; ///< symbol data
+} QRcode;
+
+/**
+ * Singly-linked list of QRcode. Used to represent a structured symbols.
+ * A list is terminated with NULL.
+ */
+typedef struct _QRcode_List {
+ QRcode *code;
+ struct _QRcode_List *next;
+} QRcode_List;
+
+/**
+ * Create a symbol from the input data.
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ * @param input input data.
+ * @return an instance of QRcode class. The version of the result QRcode may
+ * be larger than the designated version. On error, NULL is returned,
+ * and errno is set to indicate the error. See Exceptions for the
+ * details.
+ * @throw EINVAL invalid input object.
+ * @throw ENOMEM unable to allocate memory for input objects.
+ */
+extern QRcode *QRcode_encodeInput(QRinput *input);
+
+/**
+ * Create a symbol from the string. The library automatically parses the input
+ * string and encodes in a QR Code symbol.
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ * @param string input string. It must be NUL terminated.
+ * @param version version of the symbol. If 0, the library chooses the minimum
+ * version for the given input data.
+ * @param level error correction level.
+ * @param hint tell the library how Japanese Kanji characters should be
+ * encoded. If QR_MODE_KANJI is given, the library assumes that the
+ * given string contains Shift-JIS characters and encodes them in
+ * Kanji-mode. If QR_MODE_8 is given, all non-alphanumerical
+ * characters will be encoded as is. If you want to embed UTF-8
+ * string, choose this. Other mode will cause EINVAL error.
+ * @param casesensitive case-sensitive(1) or not(0).
+ * @return an instance of QRcode class. The version of the result QRcode may
+ * be larger than the designated version. On error, NULL is returned,
+ * and errno is set to indicate the error. See Exceptions for the
+ * details.
+ * @throw EINVAL invalid input object.
+ * @throw ENOMEM unable to allocate memory for input objects.
+ * @throw ERANGE input data is too large.
+ */
+extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
+
+/**
+ * Same to QRcode_encodeString(), but encode whole data in 8-bit mode.
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ */
+extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level);
+
+/**
+ * Micro QR Code version of QRcode_encodeString().
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ */
+extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
+
+/**
+ * Micro QR Code version of QRcode_encodeString8bit().
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ */
+extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level);
+
+/**
+ * Encode byte stream (may include '\0') in 8-bit mode.
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ * @param size size of the input data.
+ * @param data input data.
+ * @param version version of the symbol. If 0, the library chooses the minimum
+ * version for the given input data.
+ * @param level error correction level.
+ * @throw EINVAL invalid input object.
+ * @throw ENOMEM unable to allocate memory for input objects.
+ * @throw ERANGE input data is too large.
+ */
+extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level);
+
+/**
+ * Micro QR Code version of QRcode_encodeData().
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ */
+extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level);
+
+/**
+ * Free the instance of QRcode class.
+ * @param qrcode an instance of QRcode class.
+ */
+extern void QRcode_free(QRcode *qrcode);
+
+/**
+ * Create structured symbols from the input data.
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ * @param s input data, structured.
+ * @return a singly-linked list of QRcode.
+ */
+extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s);
+
+/**
+ * Create structured symbols from the string. The library automatically parses
+ * the input string and encodes in a QR Code symbol.
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ * @param string input string. It must be NUL terminated.
+ * @param version version of the symbol.
+ * @param level error correction level.
+ * @param hint tell the library how Japanese Kanji characters should be
+ * encoded. If QR_MODE_KANJI is given, the library assumes that the
+ * given string contains Shift-JIS characters and encodes them in
+ * Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical
+ * characters will be encoded as is. If you want to embed UTF-8
+ * string, choose this. Other mode will cause EINVAL error.
+ * @param casesensitive case-sensitive(1) or not(0).
+ * @return a singly-linked list of QRcode. On error, NULL is returned, and
+ * errno is set to indicate the error. See Exceptions for the details.
+ * @throw EINVAL invalid input object.
+ * @throw ENOMEM unable to allocate memory for input objects.
+ */
+extern QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive);
+
+/**
+ * Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode.
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ */
+extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level);
+
+/**
+ * Create structured symbols from byte stream (may include '\0'). Wholde data
+ * are encoded in 8-bit mode.
+ * @warning This function is THREAD UNSAFE when pthread is disabled.
+ * @param size size of the input data.
+ * @param data input dat.
+ * @param version version of the symbol.
+ * @param level error correction level.
+ * @return a singly-linked list of QRcode. On error, NULL is returned, and
+ * errno is set to indicate the error. See Exceptions for the details.
+ * @throw EINVAL invalid input object.
+ * @throw ENOMEM unable to allocate memory for input objects.
+ */
+extern QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level);
+
+/**
+ * Return the number of symbols included in a QRcode_List.
+ * @param qrlist a head entry of a QRcode_List.
+ * @return number of symbols in the list.
+ */
+extern int QRcode_List_size(QRcode_List *qrlist);
+
+/**
+ * Free the QRcode_List.
+ * @param qrlist a head entry of a QRcode_List.
+ */
+extern void QRcode_List_free(QRcode_List *qrlist);
+
+
+/******************************************************************************
+ * System utilities
+ *****************************************************************************/
+
+/**
+ * Return the major.minor.micro version numbers that identifies the
+ * library version.
+ * @param major_version a pointer where to store the major version number
+ * @param minor_version a pointer where to store the minor version number
+ * @param micro_version a pointer where to store the micro version number
+ */
+extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version);
+
+/**
+ * Return a string that identifies the library version.
+ * @return a string identifies the library version. The string is held by the
+ * library. Do NOT free it.
+ */
+extern char *QRcode_APIVersionString(void);
+
+/**
+ * @deprecated
+ */
+#ifndef _MSC_VER
+extern void QRcode_clearCache(void) __attribute__ ((deprecated));
+#else
+extern void QRcode_clearCache(void);
+#endif
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* QRENCODE_H */
diff --git a/genqrcode/qrencode_inner.h b/genqrcode/qrencode_inner.h
new file mode 100644
index 0000000000..2ea54f59d0
--- /dev/null
+++ b/genqrcode/qrencode_inner.h
@@ -0,0 +1,88 @@
+/**
+ * qrencode - QR Code encoder
+ *
+ * Header for test use
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef QRENCODE_INNER_H
+#define QRENCODE_INNER_H
+
+/**
+ * This header file includes definitions for test use.
+ */
+
+/******************************************************************************
+ * Raw code
+ *****************************************************************************/
+
+typedef struct {
+ int dataLength;
+ int eccLength;
+ unsigned char *data;
+ unsigned char *ecc;
+} RSblock;
+
+typedef struct {
+ int version;
+ int dataLength;
+ int eccLength;
+ unsigned char *datacode;
+ unsigned char *ecccode;
+ int b1;
+ int blocks;
+ RSblock *rsblock;
+ int count;
+} QRRawCode;
+
+extern QRRawCode *QRraw_new(QRinput *input);
+extern unsigned char QRraw_getCode(QRRawCode *raw);
+extern void QRraw_free(QRRawCode *raw);
+
+/******************************************************************************
+ * Raw code for Micro QR Code
+ *****************************************************************************/
+
+typedef struct {
+ int version;
+ int dataLength;
+ int eccLength;
+ unsigned char *datacode;
+ unsigned char *ecccode;
+ RSblock *rsblock;
+ int oddbits;
+ int count;
+} MQRRawCode;
+
+extern MQRRawCode *MQRraw_new(QRinput *input);
+extern unsigned char MQRraw_getCode(MQRRawCode *raw);
+extern void MQRraw_free(MQRRawCode *raw);
+
+/******************************************************************************
+ * Frame filling
+ *****************************************************************************/
+extern unsigned char *FrameFiller_test(int version);
+extern unsigned char *FrameFiller_testMQR(int version);
+
+/******************************************************************************
+ * QR-code encoding
+ *****************************************************************************/
+extern QRcode *QRcode_encodeMask(QRinput *input, int mask);
+extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask);
+extern QRcode *QRcode_new(int version, int width, unsigned char *data);
+
+#endif /* QRENCODE_INNER_H */
diff --git a/genqrcode/qrinput.c b/genqrcode/qrinput.c
new file mode 100644
index 0000000000..266b586dc2
--- /dev/null
+++ b/genqrcode/qrinput.c
@@ -0,0 +1,1639 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Input data chunk class
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "qrencode.h"
+#include "qrspec.h"
+#include "mqrspec.h"
+#include "bitstream.h"
+#include "qrinput.h"
+
+/******************************************************************************
+ * Utilities
+ *****************************************************************************/
+int QRinput_isSplittableMode(QRencodeMode mode)
+{
+ return (mode >= QR_MODE_NUM && mode <= QR_MODE_KANJI);
+}
+
+/******************************************************************************
+ * Entry of input data
+ *****************************************************************************/
+
+static QRinput_List *QRinput_List_newEntry(QRencodeMode mode, int size, const unsigned char *data)
+{
+ QRinput_List *entry;
+
+ if(QRinput_check(mode, size, data)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ entry = (QRinput_List *)malloc(sizeof(QRinput_List));
+ if(entry == NULL) return NULL;
+
+ entry->mode = mode;
+ entry->size = size;
+ entry->data = NULL;
+ if(size > 0) {
+ entry->data = (unsigned char *)malloc((size_t)size);
+ if(entry->data == NULL) {
+ free(entry);
+ return NULL;
+ }
+ memcpy(entry->data, data, (size_t)size);
+ }
+ entry->bstream = NULL;
+ entry->next = NULL;
+
+ return entry;
+}
+
+static void QRinput_List_freeEntry(QRinput_List *entry)
+{
+ if(entry != NULL) {
+ free(entry->data);
+ BitStream_free(entry->bstream);
+ free(entry);
+ }
+}
+
+static QRinput_List *QRinput_List_dup(QRinput_List *entry)
+{
+ QRinput_List *n;
+
+ n = (QRinput_List *)malloc(sizeof(QRinput_List));
+ if(n == NULL) return NULL;
+
+ n->mode = entry->mode;
+ n->size = entry->size;
+ n->data = (unsigned char *)malloc((size_t)n->size);
+ if(n->data == NULL) {
+ free(n);
+ return NULL;
+ }
+ memcpy(n->data, entry->data, (size_t)entry->size);
+ n->bstream = NULL;
+ n->next = NULL;
+
+ return n;
+}
+
+/******************************************************************************
+ * Input Data
+ *****************************************************************************/
+
+QRinput *QRinput_new(void)
+{
+ return QRinput_new2(0, QR_ECLEVEL_L);
+}
+
+QRinput *QRinput_new2(int version, QRecLevel level)
+{
+ QRinput *input;
+
+ if(version < 0 || version > QRSPEC_VERSION_MAX || level < 0 || level > QR_ECLEVEL_H) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ input = (QRinput *)malloc(sizeof(QRinput));
+ if(input == NULL) return NULL;
+
+ input->head = NULL;
+ input->tail = NULL;
+ input->version = version;
+ input->level = level;
+ input->mqr = 0;
+ input->fnc1 = 0;
+
+ return input;
+}
+
+QRinput *QRinput_newMQR(int version, QRecLevel level)
+{
+ QRinput *input;
+
+ if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID;
+ if(MQRspec_getECCLength(version, level) == 0) goto INVALID;
+
+ input = QRinput_new2(version, level);
+ if(input == NULL) return NULL;
+
+ input->mqr = 1;
+
+ return input;
+
+INVALID:
+ errno = EINVAL;
+ return NULL;
+}
+
+int QRinput_getVersion(QRinput *input)
+{
+ return input->version;
+}
+
+int QRinput_setVersion(QRinput *input, int version)
+{
+ if(input->mqr || version < 0 || version > QRSPEC_VERSION_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ input->version = version;
+
+ return 0;
+}
+
+QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input)
+{
+ return input->level;
+}
+
+int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level)
+{
+ if(input->mqr || level > QR_ECLEVEL_H) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ input->level = level;
+
+ return 0;
+}
+
+int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level)
+{
+ if(input->mqr) {
+ if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID;
+ if(MQRspec_getECCLength(version, level) == 0) goto INVALID;
+ } else {
+ if(version < 0 || version > QRSPEC_VERSION_MAX) goto INVALID;
+ if(level > QR_ECLEVEL_H) goto INVALID;
+ }
+
+ input->version = version;
+ input->level = level;
+
+ return 0;
+
+INVALID:
+ errno = EINVAL;
+ return -1;
+}
+
+static void QRinput_appendEntry(QRinput *input, QRinput_List *entry)
+{
+ if(input->tail == NULL) {
+ input->head = entry;
+ input->tail = entry;
+ } else {
+ input->tail->next = entry;
+ input->tail = entry;
+ }
+ entry->next = NULL;
+}
+
+int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data)
+{
+ QRinput_List *entry;
+
+ entry = QRinput_List_newEntry(mode, size, data);
+ if(entry == NULL) {
+ return -1;
+ }
+
+ QRinput_appendEntry(input, entry);
+
+ return 0;
+}
+
+/**
+ * Insert a structured-append header to the head of the input data.
+ * @param input input data.
+ * @param size number of structured symbols.
+ * @param number index number of the symbol. (1 <= number <= size)
+ * @param parity parity among input data. (NOTE: each symbol of a set of structured symbols has the same parity data)
+ * @retval 0 success.
+ * @retval -1 error occurred and errno is set to indicate the error. See Execptions for the details.
+ * @throw EINVAL invalid parameter.
+ * @throw ENOMEM unable to allocate memory.
+ */
+STATIC_IN_RELEASE int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int number, int parity)
+{
+ QRinput_List *entry;
+ unsigned char buf[3];
+
+ if(size > MAX_STRUCTURED_SYMBOLS) {
+ errno = EINVAL;
+ return -1;
+ }
+ if(number <= 0 || number > size) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ buf[0] = (unsigned char)size;
+ buf[1] = (unsigned char)number;
+ buf[2] = (unsigned char)parity;
+ entry = QRinput_List_newEntry(QR_MODE_STRUCTURE, 3, buf);
+ if(entry == NULL) {
+ return -1;
+ }
+
+ entry->next = input->head;
+ input->head = entry;
+
+ return 0;
+}
+
+int QRinput_appendECIheader(QRinput *input, unsigned int ecinum)
+{
+ unsigned char data[4];
+
+ if(ecinum > 999999) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* We manually create byte array of ecinum because
+ (unsigned char *)&ecinum may cause bus error on some architectures, */
+ data[0] = ecinum & 0xff;
+ data[1] = (ecinum >> 8) & 0xff;
+ data[2] = (ecinum >> 16) & 0xff;
+ data[3] = (ecinum >> 24) & 0xff;
+ return QRinput_append(input, QR_MODE_ECI, 4, data);
+}
+
+void QRinput_free(QRinput *input)
+{
+ QRinput_List *list, *next;
+
+ if(input != NULL) {
+ list = input->head;
+ while(list != NULL) {
+ next = list->next;
+ QRinput_List_freeEntry(list);
+ list = next;
+ }
+ free(input);
+ }
+}
+
+static unsigned char QRinput_calcParity(QRinput *input)
+{
+ unsigned char parity = 0;
+ QRinput_List *list;
+ int i;
+
+ list = input->head;
+ while(list != NULL) {
+ if(list->mode != QR_MODE_STRUCTURE) {
+ for(i = list->size-1; i >= 0; i--) {
+ parity ^= list->data[i];
+ }
+ }
+ list = list->next;
+ }
+
+ return parity;
+}
+
+QRinput *QRinput_dup(QRinput *input)
+{
+ QRinput *n;
+ QRinput_List *list, *e;
+
+ if(input->mqr) {
+ n = QRinput_newMQR(input->version, input->level);
+ } else {
+ n = QRinput_new2(input->version, input->level);
+ }
+ if(n == NULL) return NULL;
+
+ list = input->head;
+ while(list != NULL) {
+ e = QRinput_List_dup(list);
+ if(e == NULL) {
+ QRinput_free(n);
+ return NULL;
+ }
+ QRinput_appendEntry(n, e);
+ list = list->next;
+ }
+
+ return n;
+}
+
+/******************************************************************************
+ * Numeric data
+ *****************************************************************************/
+
+/**
+ * Check the input data.
+ * @param size size of the input data.
+ * @param data input data.
+ * @return result
+ */
+static int QRinput_checkModeNum(int size, const char *data)
+{
+ int i;
+
+ for(i = 0; i < size; i++) {
+ if(data[i] < '0' || data[i] > '9')
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Estimate the length of the encoded bit stream of numeric data.
+ * @param size size of the input data.
+ * @return number of bits
+ */
+int QRinput_estimateBitsModeNum(int size)
+{
+ int w;
+ int bits;
+
+ w = size / 3;
+ bits = w * 10;
+ switch(size - w * 3) {
+ case 1:
+ bits += 4;
+ break;
+ case 2:
+ bits += 7;
+ break;
+ default:
+ break;
+ }
+
+ return bits;
+}
+
+/**
+ * Convert the number data and append to a bit stream.
+ * @param entry input data.
+ * @param mqr give 1 if generating Micro QR Code.
+ * @retval 0 success
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ */
+static int QRinput_encodeModeNum(QRinput_List *entry, BitStream *bstream, int version, int mqr)
+{
+ int words, i, ret;
+ unsigned int val;
+
+ if(mqr) {
+ if(version > 1) {
+ ret = BitStream_appendNum(bstream, (size_t)(version - 1), MQRSPEC_MODEID_NUM);
+ if(ret < 0) return -1;
+ }
+ ret = BitStream_appendNum(bstream, (size_t)MQRspec_lengthIndicator(QR_MODE_NUM, version), (unsigned int)entry->size);
+ if(ret < 0) return -1;
+ } else {
+ ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_NUM);
+ if(ret < 0) return -1;
+
+ ret = BitStream_appendNum(bstream, (size_t)QRspec_lengthIndicator(QR_MODE_NUM, version), (unsigned int)entry->size);
+ if(ret < 0) return -1;
+ }
+
+ words = entry->size / 3;
+ for(i = 0; i < words; i++) {
+ val = (unsigned int)(entry->data[i*3 ] - '0') * 100;
+ val += (unsigned int)(entry->data[i*3+1] - '0') * 10;
+ val += (unsigned int)(entry->data[i*3+2] - '0');
+
+ ret = BitStream_appendNum(bstream, 10, val);
+ if(ret < 0) return -1;
+ }
+
+ if(entry->size - words * 3 == 1) {
+ val = (unsigned int)(entry->data[words*3] - '0');
+ ret = BitStream_appendNum(bstream, 4, val);
+ if(ret < 0) return -1;
+ } else if(entry->size - words * 3 == 2) {
+ val = (unsigned int)(entry->data[words*3 ] - '0') * 10;
+ val += (unsigned int)(entry->data[words*3+1] - '0');
+ ret = BitStream_appendNum(bstream, 7, val);
+ if(ret < 0) return -1;
+ }
+
+ return 0;
+}
+
+/******************************************************************************
+ * Alphabet-numeric data
+ *****************************************************************************/
+
+const signed char QRinput_anTable[128] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
+ -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+/**
+ * Check the input data.
+ * @param size size of the input data.
+ * @param data input data.
+ * @return result
+ */
+static int QRinput_checkModeAn(int size, const char *data)
+{
+ int i;
+
+ for(i = 0; i < size; i++) {
+ if(QRinput_lookAnTable(data[i]) < 0)
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ * Estimate the length of the encoded bit stream of alphabet-numeric data.
+ * @param size size of the input data.
+ * @return number of bits
+ */
+int QRinput_estimateBitsModeAn(int size)
+{
+ int w;
+ int bits;
+
+ w = size / 2;
+ bits = w * 11;
+ if(size & 1) {
+ bits += 6;
+ }
+
+ return bits;
+}
+
+/**
+ * Convert the alphabet-numeric data and append to a bit stream.
+ * @param entry input data.
+ * @param mqr give 1 if generating Micro QR Code.
+ * @retval 0 success
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ * @throw EINVAL invalid version.
+ */
+static int QRinput_encodeModeAn(QRinput_List *entry, BitStream *bstream, int version, int mqr)
+{
+ int words, i, ret;
+ unsigned int val;
+
+ if(mqr) {
+ if(version < 2) {
+ errno = ERANGE;
+ return -1;
+ }
+ ret = BitStream_appendNum(bstream, (size_t)(version - 1), MQRSPEC_MODEID_AN);
+ if(ret < 0) return -1;
+ ret = BitStream_appendNum(bstream, (size_t)MQRspec_lengthIndicator(QR_MODE_AN, version), (unsigned int)entry->size);
+ if(ret < 0) return -1;
+ } else {
+ ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_AN);
+ if(ret < 0) return -1;
+ ret = BitStream_appendNum(bstream, (size_t)QRspec_lengthIndicator(QR_MODE_AN, version), (unsigned int)entry->size);
+ if(ret < 0) return -1;
+ }
+
+ words = entry->size / 2;
+ for(i = 0; i < words; i++) {
+ val = (unsigned int)QRinput_lookAnTable(entry->data[i*2 ]) * 45;
+ val += (unsigned int)QRinput_lookAnTable(entry->data[i*2+1]);
+
+ ret = BitStream_appendNum(bstream, 11, val);
+ if(ret < 0) return -1;
+ }
+
+ if(entry->size & 1) {
+ val = (unsigned int)QRinput_lookAnTable(entry->data[words * 2]);
+
+ ret = BitStream_appendNum(bstream, 6, val);
+ if(ret < 0) return -1;
+ }
+
+ return 0;
+}
+
+/******************************************************************************
+ * 8 bit data
+ *****************************************************************************/
+
+/**
+ * Estimate the length of the encoded bit stream of 8 bit data.
+ * @param size size of the input data.
+ * @return number of bits
+ */
+int QRinput_estimateBitsMode8(int size)
+{
+ return size * 8;
+}
+
+/**
+ * Convert the 8bits data and append to a bit stream.
+ * @param entry input data.
+ * @param mqr give 1 if generating Micro QR Code.
+ * @retval 0 success
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ */
+static int QRinput_encodeMode8(QRinput_List *entry, BitStream *bstream, int version, int mqr)
+{
+ int ret;
+
+ if(mqr) {
+ if(version < 3) {
+ errno = ERANGE;
+ return -1;
+ }
+ ret = BitStream_appendNum(bstream, (size_t)(version - 1), MQRSPEC_MODEID_8);
+ if(ret < 0) return -1;
+ ret = BitStream_appendNum(bstream, (size_t)MQRspec_lengthIndicator(QR_MODE_8, version), (unsigned int)entry->size);
+ if(ret < 0) return -1;
+ } else {
+ ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_8);
+ if(ret < 0) return -1;
+ ret = BitStream_appendNum(bstream, (size_t)QRspec_lengthIndicator(QR_MODE_8, version), (unsigned int)entry->size);
+ if(ret < 0) return -1;
+ }
+
+ ret = BitStream_appendBytes(bstream, (size_t)entry->size, entry->data);
+ if(ret < 0) return -1;
+
+ return 0;
+}
+
+
+/******************************************************************************
+ * Kanji data
+ *****************************************************************************/
+
+/**
+ * Estimate the length of the encoded bit stream of kanji data.
+ * @param size size of the input data.
+ * @return number of bits
+ */
+int QRinput_estimateBitsModeKanji(int size)
+{
+ return (size / 2) * 13;
+}
+
+/**
+ * Check the input data.
+ * @param size size of the input data.
+ * @param data input data.
+ * @return result
+ */
+static int QRinput_checkModeKanji(int size, const unsigned char *data)
+{
+ int i;
+ unsigned int val;
+
+ if(size & 1)
+ return -1;
+
+ for(i = 0; i < size; i+=2) {
+ val = ((unsigned int)data[i] << 8) | data[i+1];
+ if(val < 0x8140 || (val > 0x9ffc && val < 0xe040) || val > 0xebbf) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Convert the kanji data and append to a bit stream.
+ * @param entry input data.
+ * @param mqr give 1 if generating Micro QR Code.
+ * @retval 0 success
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ * @throw EINVAL invalid version.
+ */
+static int QRinput_encodeModeKanji(QRinput_List *entry, BitStream *bstream, int version, int mqr)
+{
+ int ret, i;
+ unsigned int val, h;
+
+ if(mqr) {
+ if(version < 2) {
+ errno = ERANGE;
+ return -1;
+ }
+ ret = BitStream_appendNum(bstream, (size_t)(version - 1), MQRSPEC_MODEID_KANJI);
+ if(ret < 0) return -1;
+ ret = BitStream_appendNum(bstream, (size_t)MQRspec_lengthIndicator(QR_MODE_KANJI, version), (unsigned int)entry->size/2);
+ if(ret < 0) return -1;
+ } else {
+ ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_KANJI);
+ if(ret < 0) return -1;
+ ret = BitStream_appendNum(bstream, (size_t)QRspec_lengthIndicator(QR_MODE_KANJI, version), (unsigned int)entry->size/2);
+ if(ret < 0) return -1;
+ }
+
+ for(i = 0; i < entry->size; i+=2) {
+ val = ((unsigned int)entry->data[i] << 8) | entry->data[i+1];
+ if(val <= 0x9ffc) {
+ val -= 0x8140;
+ } else {
+ val -= 0xc140;
+ }
+ h = (val >> 8) * 0xc0;
+ val = (val & 0xff) + h;
+
+ ret = BitStream_appendNum(bstream, 13, val);
+ if(ret < 0) return -1;
+ }
+
+ return 0;
+}
+
+/******************************************************************************
+ * Structured Symbol
+ *****************************************************************************/
+
+/**
+ * Convert a structure symbol code and append to a bit stream.
+ * @param entry input data.
+ * @param mqr give 1 if generating Micro QR Code.
+ * @retval 0 success
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ * @throw EINVAL invalid entry.
+ */
+static int QRinput_encodeModeStructure(QRinput_List *entry, BitStream *bstream, int mqr)
+{
+ int ret;
+
+ if(mqr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_STRUCTURE);
+ if(ret < 0) return -1;
+ ret = BitStream_appendNum(bstream, 4, entry->data[1] - 1U);
+ if(ret < 0) return -1;
+ ret = BitStream_appendNum(bstream, 4, entry->data[0] - 1U);
+ if(ret < 0) return -1;
+ ret = BitStream_appendNum(bstream, 8, entry->data[2]);
+ if(ret < 0) return -1;
+
+ return 0;
+}
+
+/******************************************************************************
+ * FNC1
+ *****************************************************************************/
+
+static int QRinput_checkModeFNC1Second(int size)
+{
+ if(size != 1) return -1;
+
+ /* No data check required. */
+
+ return 0;
+}
+
+static int QRinput_encodeModeFNC1Second(QRinput_List *entry, BitStream *bstream)
+{
+ int ret;
+
+ ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_FNC1SECOND);
+ if(ret < 0) return -1;
+
+ ret = BitStream_appendBytes(bstream, 1, entry->data);
+ if(ret < 0) return -1;
+
+ return 0;
+}
+
+/******************************************************************************
+ * ECI header
+ *****************************************************************************/
+static unsigned int QRinput_decodeECIfromByteArray(unsigned char *data)
+{
+ int i;
+ unsigned int ecinum;
+
+ ecinum = 0;
+ for(i = 0; i < 4; i++) {
+ ecinum = ecinum << 8;
+ ecinum |= data[3-i];
+ }
+
+ return ecinum;
+}
+
+static int QRinput_estimateBitsModeECI(unsigned char *data)
+{
+ unsigned int ecinum;
+
+ ecinum = QRinput_decodeECIfromByteArray(data);
+
+ /* See Table 4 of JISX 0510:2004 p.17. */
+ if(ecinum < 128) {
+ return MODE_INDICATOR_SIZE + 8;
+ } else if(ecinum < 16384) {
+ return MODE_INDICATOR_SIZE + 16;
+ } else {
+ return MODE_INDICATOR_SIZE + 24;
+ }
+}
+
+static int QRinput_encodeModeECI(QRinput_List *entry, BitStream *bstream)
+{
+ int ret, words;
+ unsigned int ecinum, code;
+
+ ecinum = QRinput_decodeECIfromByteArray(entry->data);
+
+ /* See Table 4 of JISX 0510:2004 p.17. */
+ if(ecinum < 128) {
+ words = 1;
+ code = ecinum;
+ } else if(ecinum < 16384) {
+ words = 2;
+ code = 0x8000 + ecinum;
+ } else {
+ words = 3;
+ code = 0xc0000 + ecinum;
+ }
+
+ ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_ECI);
+ if(ret < 0) return -1;
+
+ ret = BitStream_appendNum(bstream, (size_t)words * 8, code);
+ if(ret < 0) return -1;
+
+ return 0;
+}
+
+/******************************************************************************
+ * Validation
+ *****************************************************************************/
+
+int QRinput_check(QRencodeMode mode, int size, const unsigned char *data)
+{
+ if((mode == QR_MODE_FNC1FIRST && size < 0) || size <= 0) return -1;
+
+ switch(mode) {
+ case QR_MODE_NUM:
+ return QRinput_checkModeNum(size, (const char *)data);
+ case QR_MODE_AN:
+ return QRinput_checkModeAn(size, (const char *)data);
+ case QR_MODE_KANJI:
+ return QRinput_checkModeKanji(size, data);
+ case QR_MODE_8:
+ return 0;
+ case QR_MODE_STRUCTURE:
+ return 0;
+ case QR_MODE_ECI:
+ return 0;
+ case QR_MODE_FNC1FIRST:
+ return 0;
+ case QR_MODE_FNC1SECOND:
+ return QRinput_checkModeFNC1Second(size);
+ case QR_MODE_NUL:
+ break;
+ }
+
+ return -1;
+}
+
+/******************************************************************************
+ * Estimation of the bit length
+ *****************************************************************************/
+
+/**
+ * Estimate the length of the encoded bit stream on the current version.
+ * @param entry input data.
+ * @param version version of the symbol
+ * @param mqr give 1 if generating Micro QR Code.
+ * @return number of bits
+ */
+static int QRinput_estimateBitStreamSizeOfEntry(QRinput_List *entry, int version, int mqr)
+{
+ int bits = 0;
+ int l, m;
+ int num;
+
+ if(version == 0) version = 1;
+
+ switch(entry->mode) {
+ case QR_MODE_NUM:
+ bits = QRinput_estimateBitsModeNum(entry->size);
+ break;
+ case QR_MODE_AN:
+ bits = QRinput_estimateBitsModeAn(entry->size);
+ break;
+ case QR_MODE_8:
+ bits = QRinput_estimateBitsMode8(entry->size);
+ break;
+ case QR_MODE_KANJI:
+ bits = QRinput_estimateBitsModeKanji(entry->size);
+ break;
+ case QR_MODE_STRUCTURE:
+ return STRUCTURE_HEADER_SIZE;
+ case QR_MODE_ECI:
+ bits = QRinput_estimateBitsModeECI(entry->data);
+ break;
+ case QR_MODE_FNC1FIRST:
+ return MODE_INDICATOR_SIZE;
+ case QR_MODE_FNC1SECOND:
+ return MODE_INDICATOR_SIZE + 8;
+ default:
+ return 0;
+ }
+
+ if(mqr) {
+ l = MQRspec_lengthIndicator(entry->mode, version);
+ m = version - 1;
+ bits += l + m;
+ } else {
+ l = QRspec_lengthIndicator(entry->mode, version);
+ m = 1 << l;
+ if(entry->mode == QR_MODE_KANJI) {
+ num = (entry->size/2 + m - 1) / m;
+ } else {
+ num = (entry->size + m - 1) / m;
+ }
+
+ bits += num * (MODE_INDICATOR_SIZE + l);
+ }
+
+ return bits;
+}
+
+/**
+ * Estimate the length of the encoded bit stream of the data.
+ * @param input input data
+ * @param version version of the symbol
+ * @return number of bits
+ */
+STATIC_IN_RELEASE int QRinput_estimateBitStreamSize(QRinput *input, int version)
+{
+ QRinput_List *list;
+ int bits = 0;
+
+ list = input->head;
+ while(list != NULL) {
+ bits += QRinput_estimateBitStreamSizeOfEntry(list, version, input->mqr);
+ list = list->next;
+ }
+
+ return bits;
+}
+
+/**
+ * Estimate the required version number of the symbol.
+ * @param input input data
+ * @return required version number or -1 for failure.
+ */
+STATIC_IN_RELEASE int QRinput_estimateVersion(QRinput *input)
+{
+ int bits;
+ int version, prev;
+
+ version = 0;
+ do {
+ prev = version;
+ bits = QRinput_estimateBitStreamSize(input, prev);
+ version = QRspec_getMinimumVersion((bits + 7) / 8, input->level);
+ if(prev == 0 && version > 1) {
+ version--;
+ }
+ } while (version > prev);
+
+ return version;
+}
+
+/**
+ * Return required length in bytes for specified mode, version and bits.
+ * @param mode encode mode.
+ * @param version version of the symbol.
+ * @param bits length of the input data in bits.
+ * @return required length of code words in bytes.
+ */
+STATIC_IN_RELEASE int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits)
+{
+ int payload, size, chunks, remain, maxsize;
+
+ payload = bits - 4 - QRspec_lengthIndicator(mode, version);
+ switch(mode) {
+ case QR_MODE_NUM:
+ chunks = payload / 10;
+ remain = payload - chunks * 10;
+ size = chunks * 3;
+ if(remain >= 7) {
+ size += 2;
+ } else if(remain >= 4) {
+ size += 1;
+ }
+ break;
+ case QR_MODE_AN:
+ chunks = payload / 11;
+ remain = payload - chunks * 11;
+ size = chunks * 2;
+ if(remain >= 6) size++;
+ break;
+ case QR_MODE_8:
+ size = payload / 8;
+ break;
+ case QR_MODE_KANJI:
+ size = (payload / 13) * 2;
+ break;
+ case QR_MODE_STRUCTURE:
+ size = payload / 8;
+ break;
+ default:
+ size = 0;
+ break;
+ }
+ maxsize = QRspec_maximumWords(mode, version);
+ if(size < 0) size = 0;
+ if(maxsize > 0 && size > maxsize) size = maxsize;
+
+ return size;
+}
+
+/******************************************************************************
+ * Data conversion
+ *****************************************************************************/
+
+/**
+ * Convert the input data in the data chunk and append to a bit stream.
+ * @param entry input data.
+ * @param [out] bstream destination BitStream.
+ * @return number of bits (>0) or -1 for failure.
+ */
+static int QRinput_encodeBitStream(QRinput_List *entry, BitStream *bstream, int version, int mqr)
+{
+ int words, ret;
+ QRinput_List *st1 = NULL, *st2 = NULL;
+ int prevsize;
+
+ prevsize = (int)BitStream_size(bstream);
+
+ if(mqr) {
+ words = MQRspec_maximumWords(entry->mode, version);
+ } else {
+ words = QRspec_maximumWords(entry->mode, version);
+ }
+ if(words != 0 && entry->size > words) {
+ st1 = QRinput_List_newEntry(entry->mode, words, entry->data);
+ if(st1 == NULL) goto ABORT;
+ st2 = QRinput_List_newEntry(entry->mode, entry->size - words, &entry->data[words]);
+ if(st2 == NULL) goto ABORT;
+
+ ret = QRinput_encodeBitStream(st1, bstream, version, mqr);
+ if(ret < 0) goto ABORT;
+ ret = QRinput_encodeBitStream(st2, bstream, version, mqr);
+ if(ret < 0) goto ABORT;
+
+ QRinput_List_freeEntry(st1);
+ QRinput_List_freeEntry(st2);
+ } else {
+ ret = 0;
+ switch(entry->mode) {
+ case QR_MODE_NUM:
+ ret = QRinput_encodeModeNum(entry, bstream, version, mqr);
+ break;
+ case QR_MODE_AN:
+ ret = QRinput_encodeModeAn(entry, bstream, version, mqr);
+ break;
+ case QR_MODE_8:
+ ret = QRinput_encodeMode8(entry, bstream, version, mqr);
+ break;
+ case QR_MODE_KANJI:
+ ret = QRinput_encodeModeKanji(entry, bstream, version, mqr);
+ break;
+ case QR_MODE_STRUCTURE:
+ ret = QRinput_encodeModeStructure(entry, bstream, mqr);
+ break;
+ case QR_MODE_ECI:
+ ret = QRinput_encodeModeECI(entry, bstream);
+ break;
+ case QR_MODE_FNC1SECOND:
+ ret = QRinput_encodeModeFNC1Second(entry, bstream);
+ break;
+ default:
+ break;
+ }
+ if(ret < 0) return -1;
+ }
+
+ return (int)BitStream_size(bstream) - prevsize;
+ABORT:
+ QRinput_List_freeEntry(st1);
+ QRinput_List_freeEntry(st2);
+ return -1;
+}
+
+/**
+ * Convert the input data to a bit stream.
+ * @param input input data.
+ * @retval 0 success
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ */
+static int QRinput_createBitStream(QRinput *input, BitStream *bstream)
+{
+ QRinput_List *list;
+ int bits, total = 0;
+
+ list = input->head;
+ while(list != NULL) {
+ bits = QRinput_encodeBitStream(list, bstream, input->version, input->mqr);
+ if(bits < 0) return -1;
+ total += bits;
+ list = list->next;
+ }
+
+ return total;
+}
+
+/**
+ * Convert the input data to a bit stream.
+ * When the version number is given and that is not sufficient, it is increased
+ * automatically.
+ * @param input input data.
+ * @param bstream Bitstream to be appended.
+ * @retval 0 success
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ENOMEM unable to allocate memory.
+ * @throw ERANGE input data is too large.
+ */
+static int QRinput_convertData(QRinput *input, BitStream *bstream)
+{
+ int bits;
+ int ver;
+
+ ver = QRinput_estimateVersion(input);
+ if(ver > QRinput_getVersion(input)) {
+ QRinput_setVersion(input, ver);
+ }
+
+ for(;;) {
+ BitStream_reset(bstream);
+ bits = QRinput_createBitStream(input, bstream);
+ if(bits < 0) return -1;
+ ver = QRspec_getMinimumVersion((bits + 7) / 8, input->level);
+ if(ver > QRinput_getVersion(input)) {
+ QRinput_setVersion(input, ver);
+ } else {
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Append padding bits for the input data.
+ * @param bstream Bitstream to be appended.
+ * @param input input data.
+ * @retval 0 success
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ERANGE input data is too large.
+ * @throw ENOMEM unable to allocate memory.
+ */
+static int QRinput_appendPaddingBit(BitStream *bstream, QRinput *input)
+{
+ int bits, maxbits, words, maxwords, i, ret;
+ int padlen;
+
+ bits = (int)BitStream_size(bstream);
+ maxwords = QRspec_getDataLength(input->version, input->level);
+ maxbits = maxwords * 8;
+
+ if(maxbits < bits) {
+ errno = ERANGE;
+ return -1;
+ }
+ if(maxbits == bits) {
+ return 0;
+ }
+
+ if(maxbits - bits <= 4) {
+ return (int)BitStream_appendNum(bstream, (size_t)(maxbits - bits), 0);
+ }
+
+ words = (bits + 4 + 7) / 8;
+
+ ret = (int)BitStream_appendNum(bstream, (size_t)(words * 8 - bits), 0);
+ if(ret < 0) return ret;
+
+ padlen = maxwords - words;
+ if(padlen > 0) {
+ for(i = 0; i < padlen; i++) {
+ ret = (int)BitStream_appendNum(bstream, 8, (i&1)?0x11:0xec);
+ if(ret < 0) {
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Append padding bits for the input data - Micro QR Code version.
+ * @param bstream Bitstream to be appended.
+ * @param input input data.
+ * @retval 0 success
+ * @retval -1 an error occurred and errno is set to indicate the error.
+ * See Execptions for the details.
+ * @throw ERANGE input data is too large.
+ * @throw ENOMEM unable to allocate memory.
+ */
+static int QRinput_appendPaddingBitMQR(BitStream *bstream, QRinput *input)
+{
+ int bits, maxbits, words, maxwords, i, ret, termbits;
+ int padlen;
+
+ bits = (int)BitStream_size(bstream);
+ maxbits = MQRspec_getDataLengthBit(input->version, input->level);
+ maxwords = maxbits / 8;
+
+ if(maxbits < bits) {
+ errno = ERANGE;
+ return -1;
+ }
+ if(maxbits == bits) {
+ return 0;
+ }
+
+ termbits = input->version * 2 + 1;
+
+ if(maxbits - bits <= termbits) {
+ return (int)BitStream_appendNum(bstream, (size_t)(maxbits - bits), 0);
+ }
+
+ bits += termbits;
+
+ words = (bits + 7) / 8;
+ if(maxbits - words * 8 > 0) {
+ termbits += words * 8 - bits;
+ if(words == maxwords) termbits += maxbits - words * 8;
+ } else {
+ termbits += words * 8 - bits;
+ }
+ ret = (int)BitStream_appendNum(bstream, (size_t)termbits, 0);
+ if(ret < 0) return ret;
+
+ padlen = maxwords - words;
+ if(padlen > 0) {
+ for(i = 0; i < padlen; i++) {
+ ret = (int)BitStream_appendNum(bstream, 8, (i&1)?0x11:0xec);
+ if(ret < 0) return ret;
+ }
+ termbits = maxbits - maxwords * 8;
+ if(termbits > 0) {
+ ret = (int)BitStream_appendNum(bstream, (size_t)termbits, 0);
+ if(ret < 0) return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int QRinput_insertFNC1Header(QRinput *input)
+{
+ QRinput_List *entry = NULL;
+
+ if(input->fnc1 == 1) {
+ entry = QRinput_List_newEntry(QR_MODE_FNC1FIRST, 0, NULL);
+ } else if(input->fnc1 == 2) {
+ entry = QRinput_List_newEntry(QR_MODE_FNC1SECOND, 1, &(input->appid));
+ }
+ if(entry == NULL) {
+ return -1;
+ }
+
+ if(input->head->mode != QR_MODE_STRUCTURE && input->head->mode != QR_MODE_ECI) {
+ entry->next = input->head;
+ input->head = entry;
+ } else {
+ entry->next = input->head->next;
+ input->head->next = entry;
+ }
+
+ return 0;
+}
+
+/**
+ * Merge all bit streams in the input data.
+ * @param input input data.
+ * @return merged bit stream
+ */
+
+STATIC_IN_RELEASE int QRinput_mergeBitStream(QRinput *input, BitStream *bstream)
+{
+ if(input->mqr) {
+ if(QRinput_createBitStream(input, bstream) < 0) {
+ return -1;
+ }
+ } else {
+ if(input->fnc1) {
+ if(QRinput_insertFNC1Header(input) < 0) {
+ return -1;
+ }
+ }
+ if(QRinput_convertData(input, bstream) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Merge all bit streams in the input data and append padding bits
+ * @param input input data.
+ * @return padded merged bit stream
+ */
+
+STATIC_IN_RELEASE int QRinput_getBitStream(QRinput *input, BitStream *bstream)
+{
+ int ret;
+
+ ret = QRinput_mergeBitStream(input, bstream);
+ if(ret < 0) return -1;
+
+ if(input->mqr) {
+ ret = QRinput_appendPaddingBitMQR(bstream, input);
+ } else {
+ ret = QRinput_appendPaddingBit(bstream, input);
+ }
+ if(ret < 0) return -1;
+
+ return 0;
+}
+
+/**
+ * Pack all bit streams padding bits into a byte array.
+ * @param input input data.
+ * @return padded merged byte stream
+ */
+
+unsigned char *QRinput_getByteStream(QRinput *input)
+{
+ BitStream *bstream;
+ unsigned char *array;
+ int ret;
+
+ bstream = BitStream_new();
+ if(bstream == NULL) {
+ return NULL;
+ }
+
+ ret = QRinput_getBitStream(input, bstream);
+ if(ret < 0) {
+ BitStream_free(bstream);
+ return NULL;
+ }
+ array = BitStream_toByte(bstream);
+ BitStream_free(bstream);
+
+ return array;
+}
+
+/******************************************************************************
+ * Structured input data
+ *****************************************************************************/
+
+static QRinput_InputList *QRinput_InputList_newEntry(QRinput *input)
+{
+ QRinput_InputList *entry;
+
+ entry = (QRinput_InputList *)malloc(sizeof(QRinput_InputList));
+ if(entry == NULL) return NULL;
+
+ entry->input = input;
+ entry->next = NULL;
+
+ return entry;
+}
+
+static void QRinput_InputList_freeEntry(QRinput_InputList *entry)
+{
+ if(entry != NULL) {
+ QRinput_free(entry->input);
+ free(entry);
+ }
+}
+
+QRinput_Struct *QRinput_Struct_new(void)
+{
+ QRinput_Struct *s;
+
+ s = (QRinput_Struct *)malloc(sizeof(QRinput_Struct));
+ if(s == NULL) return NULL;
+
+ s->size = 0;
+ s->parity = -1;
+ s->head = NULL;
+ s->tail = NULL;
+
+ return s;
+}
+
+void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity)
+{
+ s->parity = (int)parity;
+}
+
+int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input)
+{
+ QRinput_InputList *e;
+
+ if(input->mqr) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ e = QRinput_InputList_newEntry(input);
+ if(e == NULL) return -1;
+
+ s->size++;
+ if(s->tail == NULL) {
+ s->head = e;
+ s->tail = e;
+ } else {
+ s->tail->next = e;
+ s->tail = e;
+ }
+
+ return s->size;
+}
+
+void QRinput_Struct_free(QRinput_Struct *s)
+{
+ QRinput_InputList *list, *next;
+
+ if(s != NULL) {
+ list = s->head;
+ while(list != NULL) {
+ next = list->next;
+ QRinput_InputList_freeEntry(list);
+ list = next;
+ }
+ free(s);
+ }
+}
+
+static unsigned char QRinput_Struct_calcParity(QRinput_Struct *s)
+{
+ QRinput_InputList *list;
+ unsigned char parity = 0;
+
+ list = s->head;
+ while(list != NULL) {
+ parity ^= QRinput_calcParity(list->input);
+ list = list->next;
+ }
+
+ QRinput_Struct_setParity(s, parity);
+
+ return parity;
+}
+
+static int QRinput_List_shrinkEntry(QRinput_List *entry, int bytes)
+{
+ unsigned char *data;
+
+ data = (unsigned char *)malloc((size_t)bytes);
+ if(data == NULL) return -1;
+
+ memcpy(data, entry->data, (size_t)bytes);
+ free(entry->data);
+ entry->data = data;
+ entry->size = bytes;
+
+ return 0;
+}
+
+STATIC_IN_RELEASE int QRinput_splitEntry(QRinput_List *entry, int bytes)
+{
+ QRinput_List *e;
+ int ret;
+
+ e = QRinput_List_newEntry(entry->mode, entry->size - bytes, entry->data + bytes);
+ if(e == NULL) {
+ return -1;
+ }
+
+ ret = QRinput_List_shrinkEntry(entry, bytes);
+ if(ret < 0) {
+ QRinput_List_freeEntry(e);
+ return -1;
+ }
+
+ e->next = entry->next;
+ entry->next = e;
+
+ return 0;
+}
+
+QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input)
+{
+ QRinput *p = NULL;
+ QRinput_Struct *s = NULL;
+ int bits, maxbits, nextbits, bytes, ret;
+ QRinput_List *list, *next, *prev;
+ BitStream *bstream = NULL;
+
+ if(input->mqr) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ s = QRinput_Struct_new();
+ if(s == NULL) return NULL;
+
+ input = QRinput_dup(input);
+ if(input == NULL) {
+ QRinput_Struct_free(s);
+ return NULL;
+ }
+
+ QRinput_Struct_setParity(s, QRinput_calcParity(input));
+ maxbits = QRspec_getDataLength(input->version, input->level) * 8 - STRUCTURE_HEADER_SIZE;
+
+ if(maxbits <= 0) goto ABORT;
+
+ bstream = BitStream_new();
+ if(bstream == NULL) goto ABORT;
+
+ bits = 0;
+ list = input->head;
+ prev = NULL;
+ while(list != NULL) {
+ nextbits = QRinput_estimateBitStreamSizeOfEntry(list, input->version, input->mqr);
+ if(bits + nextbits <= maxbits) {
+ BitStream_reset(bstream);
+ ret = QRinput_encodeBitStream(list, bstream, input->version, input->mqr);
+ if(ret < 0) goto ABORT;
+ bits += ret;
+ prev = list;
+ list = list->next;
+ } else {
+ bytes = QRinput_lengthOfCode(list->mode, input->version, maxbits - bits);
+ p = QRinput_new2(input->version, input->level);
+ if(p == NULL) goto ABORT;
+ if(bytes > 0) {
+ /* Splits this entry into 2 entries. */
+ ret = QRinput_splitEntry(list, bytes);
+ if(ret < 0) {
+ QRinput_free(p);
+ goto ABORT;
+ }
+ /* First half is the tail of the current input. */
+ next = list->next;
+ list->next = NULL;
+ /* Second half is the head of the next input, p.*/
+ p->head = next;
+ /* Renew QRinput.tail. */
+ p->tail = input->tail;
+ input->tail = list;
+ /* Point to the next entry. */
+ prev = list;
+ list = next;
+ } else {
+ /* Current entry will go to the next input. */
+ prev->next = NULL;
+ p->head = list;
+ p->tail = input->tail;
+ input->tail = prev;
+ }
+ ret = QRinput_Struct_appendInput(s, input);
+ if(ret < 0) {
+ QRinput_free(p);
+ goto ABORT;
+ }
+ input = p;
+ bits = 0;
+ }
+ }
+ ret = QRinput_Struct_appendInput(s, input);
+ if(ret < 0) goto ABORT;
+ if(s->size > MAX_STRUCTURED_SYMBOLS) {
+ errno = ERANGE;
+ QRinput_Struct_free(s);
+ BitStream_free(bstream);
+ return NULL;
+ }
+ ret = QRinput_Struct_insertStructuredAppendHeaders(s);
+ if(ret < 0) {
+ QRinput_Struct_free(s);
+ BitStream_free(bstream);
+ return NULL;
+ }
+
+ BitStream_free(bstream);
+ return s;
+
+ABORT:
+ BitStream_free(bstream);
+ QRinput_free(input);
+ QRinput_Struct_free(s);
+ return NULL;
+}
+
+int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s)
+{
+ int i;
+ QRinput_InputList *list;
+
+ if(s->size == 1) {
+ return 0;
+ }
+
+ if(s->parity < 0) {
+ QRinput_Struct_calcParity(s);
+ }
+ i = 1;
+ list = s->head;
+ while(list != NULL) {
+ if(QRinput_insertStructuredAppendHeader(list->input, s->size, i, s->parity))
+ return -1;
+ i++;
+ list = list->next;
+ }
+
+ return 0;
+}
+
+/******************************************************************************
+ * Extended encoding mode (FNC1 and ECI)
+ *****************************************************************************/
+
+int QRinput_setFNC1First(QRinput *input)
+{
+ if(input->mqr) {
+ errno = EINVAL;
+ return -1;
+ }
+ input->fnc1 = 1;
+
+ return 0;
+}
+
+int QRinput_setFNC1Second(QRinput *input, unsigned char appid)
+{
+ if(input->mqr) {
+ errno = EINVAL;
+ return -1;
+ }
+ input->fnc1 = 2;
+ input->appid = appid;
+
+ return 0;
+}
diff --git a/genqrcode/qrinput.h b/genqrcode/qrinput.h
new file mode 100644
index 0000000000..d1d3b25977
--- /dev/null
+++ b/genqrcode/qrinput.h
@@ -0,0 +1,124 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Input data chunk class
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef QRINPUT_H
+#define QRINPUT_H
+
+#include "qrencode.h"
+#include "bitstream.h"
+
+int QRinput_isSplittableMode(QRencodeMode mode);
+
+/******************************************************************************
+ * Entry of input data
+ *****************************************************************************/
+typedef struct _QRinput_List QRinput_List;
+
+struct _QRinput_List {
+ QRencodeMode mode;
+ int size; ///< Size of data chunk (byte).
+ unsigned char *data; ///< Data chunk.
+ BitStream *bstream;
+ QRinput_List *next;
+};
+
+/******************************************************************************
+ * Input Data
+ *****************************************************************************/
+struct _QRinput {
+ int version;
+ QRecLevel level;
+ QRinput_List *head;
+ QRinput_List *tail;
+ int mqr;
+ int fnc1;
+ unsigned char appid;
+};
+
+/******************************************************************************
+ * Structured append input data
+ *****************************************************************************/
+typedef struct _QRinput_InputList QRinput_InputList;
+
+struct _QRinput_InputList {
+ QRinput *input;
+ QRinput_InputList *next;
+};
+
+struct _QRinput_Struct {
+ int size; ///< number of structured symbols
+ int parity;
+ QRinput_InputList *head;
+ QRinput_InputList *tail;
+};
+
+/**
+ * Pack all bit streams padding bits into a byte array.
+ * @param input input data.
+ * @return padded merged byte stream
+ */
+extern unsigned char *QRinput_getByteStream(QRinput *input);
+
+
+extern int QRinput_estimateBitsModeNum(int size);
+extern int QRinput_estimateBitsModeAn(int size);
+extern int QRinput_estimateBitsMode8(int size);
+extern int QRinput_estimateBitsModeKanji(int size);
+
+extern QRinput *QRinput_dup(QRinput *input);
+
+extern const signed char QRinput_anTable[128];
+
+/**
+ * Look up the alphabet-numeric convesion table (see JIS X0510:2004, p.19).
+ * @param __c__ character
+ * @return value
+ */
+#define QRinput_lookAnTable(__c__) \
+ ((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__])
+
+/**
+ * Length of a standard mode indicator in bits.
+ */
+
+#define MODE_INDICATOR_SIZE 4
+
+/**
+ * Length of a segment of structured-append header.
+ */
+#define STRUCTURE_HEADER_SIZE 20
+
+/**
+ * Maximum number of symbols in a set of structured-appended symbols.
+ */
+#define MAX_STRUCTURED_SYMBOLS 16
+
+#ifdef WITH_TESTS
+extern int QRinput_mergeBitStream(QRinput *input, BitStream *bstream);
+extern int QRinput_getBitStream(QRinput *input, BitStream *bstream);
+extern int QRinput_estimateBitStreamSize(QRinput *input, int version);
+extern int QRinput_splitEntry(QRinput_List *entry, int bytes);
+extern int QRinput_estimateVersion(QRinput *input);
+extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits);
+extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, int parity);
+#endif
+
+#endif /* QRINPUT_H */
diff --git a/genqrcode/qrspec.c b/genqrcode/qrspec.c
new file mode 100644
index 0000000000..1232c0e0be
--- /dev/null
+++ b/genqrcode/qrspec.c
@@ -0,0 +1,514 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * QR Code specification in convenient format.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ * or
+ * "Automatic identification and data capture techniques --
+ * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "qrspec.h"
+#include "qrinput.h"
+
+/******************************************************************************
+ * Version and capacity
+ *****************************************************************************/
+
+typedef struct {
+ int width; ///< Edge length of the symbol
+ int words; ///< Data capacity (bytes)
+ int remainder; ///< Remainder bit (bits)
+ int ec[4]; ///< Number of ECC code (bytes)
+} QRspec_Capacity;
+
+/**
+ * Table of the capacity of symbols
+ * See Table 1 (p.13) and Table 12-16 (pp.30-36), JIS X0510:2004.
+ */
+static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = {
+ { 0, 0, 0, { 0, 0, 0, 0}},
+ { 21, 26, 0, { 7, 10, 13, 17}}, // 1
+ { 25, 44, 7, { 10, 16, 22, 28}},
+ { 29, 70, 7, { 15, 26, 36, 44}},
+ { 33, 100, 7, { 20, 36, 52, 64}},
+ { 37, 134, 7, { 26, 48, 72, 88}}, // 5
+ { 41, 172, 7, { 36, 64, 96, 112}},
+ { 45, 196, 0, { 40, 72, 108, 130}},
+ { 49, 242, 0, { 48, 88, 132, 156}},
+ { 53, 292, 0, { 60, 110, 160, 192}},
+ { 57, 346, 0, { 72, 130, 192, 224}}, //10
+ { 61, 404, 0, { 80, 150, 224, 264}},
+ { 65, 466, 0, { 96, 176, 260, 308}},
+ { 69, 532, 0, { 104, 198, 288, 352}},
+ { 73, 581, 3, { 120, 216, 320, 384}},
+ { 77, 655, 3, { 132, 240, 360, 432}}, //15
+ { 81, 733, 3, { 144, 280, 408, 480}},
+ { 85, 815, 3, { 168, 308, 448, 532}},
+ { 89, 901, 3, { 180, 338, 504, 588}},
+ { 93, 991, 3, { 196, 364, 546, 650}},
+ { 97, 1085, 3, { 224, 416, 600, 700}}, //20
+ {101, 1156, 4, { 224, 442, 644, 750}},
+ {105, 1258, 4, { 252, 476, 690, 816}},
+ {109, 1364, 4, { 270, 504, 750, 900}},
+ {113, 1474, 4, { 300, 560, 810, 960}},
+ {117, 1588, 4, { 312, 588, 870, 1050}}, //25
+ {121, 1706, 4, { 336, 644, 952, 1110}},
+ {125, 1828, 4, { 360, 700, 1020, 1200}},
+ {129, 1921, 3, { 390, 728, 1050, 1260}},
+ {133, 2051, 3, { 420, 784, 1140, 1350}},
+ {137, 2185, 3, { 450, 812, 1200, 1440}}, //30
+ {141, 2323, 3, { 480, 868, 1290, 1530}},
+ {145, 2465, 3, { 510, 924, 1350, 1620}},
+ {149, 2611, 3, { 540, 980, 1440, 1710}},
+ {153, 2761, 3, { 570, 1036, 1530, 1800}},
+ {157, 2876, 0, { 570, 1064, 1590, 1890}}, //35
+ {161, 3034, 0, { 600, 1120, 1680, 1980}},
+ {165, 3196, 0, { 630, 1204, 1770, 2100}},
+ {169, 3362, 0, { 660, 1260, 1860, 2220}},
+ {173, 3532, 0, { 720, 1316, 1950, 2310}},
+ {177, 3706, 0, { 750, 1372, 2040, 2430}} //40
+};
+
+int QRspec_getDataLength(int version, QRecLevel level)
+{
+ return qrspecCapacity[version].words - qrspecCapacity[version].ec[level];
+}
+
+int QRspec_getECCLength(int version, QRecLevel level)
+{
+ return qrspecCapacity[version].ec[level];
+}
+
+int QRspec_getMinimumVersion(int size, QRecLevel level)
+{
+ int i;
+ int words;
+
+ for(i = 1; i <= QRSPEC_VERSION_MAX; i++) {
+ words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level];
+ if(words >= size) return i;
+ }
+
+ return QRSPEC_VERSION_MAX;
+}
+
+int QRspec_getWidth(int version)
+{
+ return qrspecCapacity[version].width;
+}
+
+int QRspec_getRemainder(int version)
+{
+ return qrspecCapacity[version].remainder;
+}
+
+/******************************************************************************
+ * Length indicator
+ *****************************************************************************/
+
+static const int lengthTableBits[4][3] = {
+ {10, 12, 14},
+ { 9, 11, 13},
+ { 8, 16, 16},
+ { 8, 10, 12}
+};
+
+int QRspec_lengthIndicator(QRencodeMode mode, int version)
+{
+ int l;
+
+ if(!QRinput_isSplittableMode(mode)) return 0;
+ if(version <= 9) {
+ l = 0;
+ } else if(version <= 26) {
+ l = 1;
+ } else {
+ l = 2;
+ }
+
+ return lengthTableBits[mode][l];
+}
+
+int QRspec_maximumWords(QRencodeMode mode, int version)
+{
+ int l;
+ int bits;
+ int words;
+
+ if(!QRinput_isSplittableMode(mode)) return 0;
+ if(version <= 9) {
+ l = 0;
+ } else if(version <= 26) {
+ l = 1;
+ } else {
+ l = 2;
+ }
+
+ bits = lengthTableBits[mode][l];
+ words = (1 << bits) - 1;
+ if(mode == QR_MODE_KANJI) {
+ words *= 2; // the number of bytes is required
+ }
+
+ return words;
+}
+
+/******************************************************************************
+ * Error correction code
+ *****************************************************************************/
+
+/**
+ * Table of the error correction code (Reed-Solomon block)
+ * See Table 12-16 (pp.30-36), JIS X0510:2004.
+ */
+static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = {
+ {{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}},
+ {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1
+ {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}},
+ {{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}},
+ {{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}},
+ {{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5
+ {{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}},
+ {{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}},
+ {{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}},
+ {{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}},
+ {{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10
+ {{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}},
+ {{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}},
+ {{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}},
+ {{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}},
+ {{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15
+ {{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}},
+ {{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}},
+ {{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}},
+ {{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}},
+ {{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20
+ {{ 4, 4}, {17, 0}, {17, 6}, {19, 6}},
+ {{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}},
+ {{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}},
+ {{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}},
+ {{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25
+ {{10, 2}, {19, 4}, {28, 6}, {33, 4}},
+ {{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}},
+ {{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}},
+ {{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}},
+ {{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30
+ {{13, 3}, { 2, 29}, {42, 1}, {23, 28}},
+ {{17, 0}, {10, 23}, {10, 35}, {19, 35}},
+ {{17, 1}, {14, 21}, {29, 19}, {11, 46}},
+ {{13, 6}, {14, 23}, {44, 7}, {59, 1}},
+ {{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35
+ {{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}},
+ {{17, 4}, {29, 14}, {49, 10}, {24, 46}},
+ {{ 4, 18}, {13, 32}, {48, 14}, {42, 32}},
+ {{20, 4}, {40, 7}, {43, 22}, {10, 67}},
+ {{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40
+};
+
+void QRspec_getEccSpec(int version, QRecLevel level, int spec[5])
+{
+ int b1, b2;
+ int data, ecc;
+
+ b1 = eccTable[version][level][0];
+ b2 = eccTable[version][level][1];
+ data = QRspec_getDataLength(version, level);
+ ecc = QRspec_getECCLength(version, level);
+
+ if(b2 == 0) {
+ spec[0] = b1;
+ spec[1] = data / b1;
+ spec[2] = ecc / b1;
+ spec[3] = spec[4] = 0;
+ } else {
+ spec[0] = b1;
+ spec[1] = data / (b1 + b2);
+ spec[2] = ecc / (b1 + b2);
+ spec[3] = b2;
+ spec[4] = spec[1] + 1;
+ }
+}
+
+/******************************************************************************
+ * Alignment pattern
+ *****************************************************************************/
+
+/**
+ * Positions of alignment patterns.
+ * This array includes only the second and the third position of the alignment
+ * patterns. Rest of them can be calculated from the distance between them.
+ *
+ * See Table 1 in Appendix E (p.71) of JIS X0510:2004.
+ */
+static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = {
+ { 0, 0},
+ { 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5
+ {34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10
+ {30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15
+ {26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20
+ {28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25
+ {30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30
+ {30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35
+ {24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40
+};
+
+/**
+ * Put an alignment marker.
+ * @param frame destination frame data
+ * @param width frame width
+ * @param ox,oy center coordinate of the pattern
+ */
+static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy)
+{
+ static const unsigned char finder[] = {
+ 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
+ 0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
+ 0xa1, 0xa0, 0xa1, 0xa0, 0xa1,
+ 0xa1, 0xa0, 0xa0, 0xa0, 0xa1,
+ 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
+ };
+ int x, y;
+ const unsigned char *s;
+
+ frame += (oy - 2) * width + ox - 2;
+ s = finder;
+ for(y = 0; y < 5; y++) {
+ for(x = 0; x < 5; x++) {
+ frame[x] = s[x];
+ }
+ frame += width;
+ s += 5;
+ }
+}
+
+static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width)
+{
+ int d, w, x, y, cx, cy;
+
+ if(version < 2) return;
+
+ d = alignmentPattern[version][1] - alignmentPattern[version][0];
+ if(d < 0) {
+ w = 2;
+ } else {
+ w = (width - alignmentPattern[version][0]) / d + 2;
+ }
+
+ if(w * w - 3 == 1) {
+ x = alignmentPattern[version][0];
+ y = alignmentPattern[version][0];
+ QRspec_putAlignmentMarker(frame, width, x, y);
+ return;
+ }
+
+ cx = alignmentPattern[version][0];
+ for(x = 1; x < w - 1; x++) {
+ QRspec_putAlignmentMarker(frame, width, 6, cx);
+ QRspec_putAlignmentMarker(frame, width, cx, 6);
+ cx += d;
+ }
+
+ cy = alignmentPattern[version][0];
+ for(y = 0; y < w-1; y++) {
+ cx = alignmentPattern[version][0];
+ for(x = 0; x < w-1; x++) {
+ QRspec_putAlignmentMarker(frame, width, cx, cy);
+ cx += d;
+ }
+ cy += d;
+ }
+}
+
+/******************************************************************************
+ * Version information pattern
+ *****************************************************************************/
+
+/**
+ * Version information pattern (BCH coded).
+ * See Table 1 in Appendix D (p.68) of JIS X0510:2004.
+ */
+static const unsigned int versionPattern[QRSPEC_VERSION_MAX - 6] = {
+ 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
+ 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
+ 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
+ 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
+ 0x27541, 0x28c69
+};
+
+unsigned int QRspec_getVersionPattern(int version)
+{
+ if(version < 7 || version > QRSPEC_VERSION_MAX) return 0;
+
+ return versionPattern[version - 7];
+}
+
+/******************************************************************************
+ * Format information
+ *****************************************************************************/
+
+/* See calcFormatInfo in tests/test_qrspec.c */
+static const unsigned int formatInfo[4][8] = {
+ {0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976},
+ {0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0},
+ {0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed},
+ {0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b}
+};
+
+unsigned int QRspec_getFormatInfo(int mask, QRecLevel level)
+{
+ if(mask < 0 || mask > 7) return 0;
+
+ return formatInfo[level][mask];
+}
+
+/******************************************************************************
+ * Frame
+ *****************************************************************************/
+
+/**
+ * Put a finder pattern.
+ * @param frame destination frame data
+ * @param width frame width
+ * @param ox,oy upper-left coordinate of the pattern
+ */
+static void putFinderPattern(unsigned char *frame, int width, int ox, int oy)
+{
+ static const unsigned char finder[] = {
+ 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+ 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+ 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+ 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+ 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+ 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+ 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+ };
+ int x, y;
+ const unsigned char *s;
+
+ frame += oy * width + ox;
+ s = finder;
+ for(y = 0; y < 7; y++) {
+ for(x = 0; x < 7; x++) {
+ frame[x] = s[x];
+ }
+ frame += width;
+ s += 7;
+ }
+}
+
+
+static unsigned char *QRspec_createFrame(int version)
+{
+ unsigned char *frame, *p, *q;
+ int width;
+ int x, y;
+ unsigned int verinfo, v;
+
+ width = qrspecCapacity[version].width;
+ frame = (unsigned char *)malloc((size_t)(width * width));
+ if(frame == NULL) return NULL;
+
+ memset(frame, 0, (size_t)(width * width));
+ /* Finder pattern */
+ putFinderPattern(frame, width, 0, 0);
+ putFinderPattern(frame, width, width - 7, 0);
+ putFinderPattern(frame, width, 0, width - 7);
+ /* Separator */
+ p = frame;
+ q = frame + width * (width - 7);
+ for(y = 0; y < 7; y++) {
+ p[7] = 0xc0;
+ p[width - 8] = 0xc0;
+ q[7] = 0xc0;
+ p += width;
+ q += width;
+ }
+ memset(frame + width * 7, 0xc0, 8);
+ memset(frame + width * 8 - 8, 0xc0, 8);
+ memset(frame + width * (width - 8), 0xc0, 8);
+ /* Mask format information area */
+ memset(frame + width * 8, 0x84, 9);
+ memset(frame + width * 9 - 8, 0x84, 8);
+ p = frame + 8;
+ for(y = 0; y < 8; y++) {
+ *p = 0x84;
+ p += width;
+ }
+ p = frame + width * (width - 7) + 8;
+ for(y = 0; y < 7; y++) {
+ *p = 0x84;
+ p += width;
+ }
+ /* Timing pattern */
+ p = frame + width * 6 + 8;
+ q = frame + width * 8 + 6;
+ for(x = 1; x < width-15; x++) {
+ *p = 0x90 | (x & 1);
+ *q = 0x90 | (x & 1);
+ p++;
+ q += width;
+ }
+ /* Alignment pattern */
+ QRspec_putAlignmentPattern(version, frame, width);
+
+ /* Version information */
+ if(version >= 7) {
+ verinfo = QRspec_getVersionPattern(version);
+
+ p = frame + width * (width - 11);
+ v = verinfo;
+ for(x = 0; x < 6; x++) {
+ for(y = 0; y < 3; y++) {
+ p[width * y + x] = 0x88 | (v & 1);
+ v = v >> 1;
+ }
+ }
+
+ p = frame + width - 11;
+ v = verinfo;
+ for(y = 0; y < 6; y++) {
+ for(x = 0; x < 3; x++) {
+ p[x] = 0x88 | (v & 1);
+ v = v >> 1;
+ }
+ p += width;
+ }
+ }
+ /* and a little bit... */
+ frame[width * (width - 8) + 8] = 0x81;
+
+ return frame;
+}
+
+unsigned char *QRspec_newFrame(int version)
+{
+ if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL;
+
+ return QRspec_createFrame(version);
+}
diff --git a/genqrcode/qrspec.h b/genqrcode/qrspec.h
new file mode 100644
index 0000000000..017bb5518a
--- /dev/null
+++ b/genqrcode/qrspec.h
@@ -0,0 +1,174 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * QR Code specification in convenient format.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef QRSPEC_H
+#define QRSPEC_H
+
+#include "qrencode.h"
+
+/******************************************************************************
+ * Version and capacity
+ *****************************************************************************/
+
+/**
+ * Maximum width of a symbol
+ */
+#define QRSPEC_WIDTH_MAX 177
+
+/**
+ * Return maximum data code length (bytes) for the version.
+ * @param version version of the symbol
+ * @param level error correction level
+ * @return maximum size (bytes)
+ */
+extern int QRspec_getDataLength(int version, QRecLevel level);
+
+/**
+ * Return maximum error correction code length (bytes) for the version.
+ * @param version version of the symbol
+ * @param level error correction level
+ * @return ECC size (bytes)
+ */
+extern int QRspec_getECCLength(int version, QRecLevel level);
+
+/**
+ * Return a version number that satisfies the input code length.
+ * @param size input code length (byte)
+ * @param level error correction level
+ * @return version number
+ */
+extern int QRspec_getMinimumVersion(int size, QRecLevel level);
+
+/**
+ * Return the width of the symbol for the version.
+ * @param version vesion of the symbol
+ * @return width of the symbol
+ */
+extern int QRspec_getWidth(int version);
+
+/**
+ * Return the numer of remainder bits.
+ * @param version vesion of the symbol
+ * @return number of remainder bits
+ */
+extern int QRspec_getRemainder(int version);
+
+/******************************************************************************
+ * Length indicator
+ *****************************************************************************/
+
+/**
+ * Return the size of length indicator for the mode and version.
+ * @param mode encode mode
+ * @param version vesion of the symbol
+ * @return the size of the appropriate length indicator (bits).
+ */
+extern int QRspec_lengthIndicator(QRencodeMode mode, int version);
+
+/**
+ * Return the maximum length for the mode and version.
+ * @param mode encode mode
+ * @param version vesion of the symbol
+ * @return the maximum length (bytes)
+ */
+extern int QRspec_maximumWords(QRencodeMode mode, int version);
+
+/******************************************************************************
+ * Error correction code
+ *****************************************************************************/
+
+/**
+ * Return an array of ECC specification.
+ * @param version version of the symbol
+ * @param level error correction level
+ * @param spec an array of ECC specification contains as following:
+ * {# of type1 blocks, # of data code, # of ecc code,
+ * # of type2 blocks, # of data code}
+ */
+void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]);
+
+#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3])
+#define QRspec_rsBlockNum1(__spec__) (__spec__[0])
+#define QRspec_rsDataCodes1(__spec__) (__spec__[1])
+#define QRspec_rsEccCodes1(__spec__) (__spec__[2])
+#define QRspec_rsBlockNum2(__spec__) (__spec__[3])
+#define QRspec_rsDataCodes2(__spec__) (__spec__[4])
+#define QRspec_rsEccCodes2(__spec__) (__spec__[2])
+
+#define QRspec_rsDataLength(__spec__) \
+ ((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \
+ (QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__)))
+#define QRspec_rsEccLength(__spec__) \
+ (QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__))
+
+/******************************************************************************
+ * Version information pattern
+ *****************************************************************************/
+
+/**
+ * Return BCH encoded version information pattern that is used for the symbol
+ * of version 7 or greater. Use lower 18 bits.
+ * @param version version of the symbol
+ * @return BCH encoded version information pattern
+ */
+extern unsigned int QRspec_getVersionPattern(int version);
+
+/******************************************************************************
+ * Format information
+ *****************************************************************************/
+
+/**
+ * Return BCH encoded format information pattern.
+ * @param mask mask number
+ * @param level error correction level
+ * @return BCH encoded format information pattern
+ */
+extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level);
+
+/******************************************************************************
+ * Frame
+ *****************************************************************************/
+
+/**
+ * Return a copy of initialized frame.
+ * @param version version of the symbol
+ * @return Array of unsigned char. You can free it by free().
+ */
+extern unsigned char *QRspec_newFrame(int version);
+
+/******************************************************************************
+ * Mode indicator
+ *****************************************************************************/
+
+/**
+ * Mode indicator. See Table 2 of JIS X0510:2004, p.16.
+ */
+#define QRSPEC_MODEID_ECI 7
+#define QRSPEC_MODEID_NUM 1
+#define QRSPEC_MODEID_AN 2
+#define QRSPEC_MODEID_8 4
+#define QRSPEC_MODEID_KANJI 8
+#define QRSPEC_MODEID_FNC1FIRST 5
+#define QRSPEC_MODEID_FNC1SECOND 9
+#define QRSPEC_MODEID_STRUCTURE 3
+#define QRSPEC_MODEID_TERMINATOR 0
+
+#endif /* QRSPEC_H */
diff --git a/genqrcode/rsecc.c b/genqrcode/rsecc.c
new file mode 100644
index 0000000000..95be0f00c5
--- /dev/null
+++ b/genqrcode/rsecc.c
@@ -0,0 +1,149 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Reed solomon error correction code encoder specialized for QR code.
+ * This code is rewritten by Kentaro Fukuchi, referring to the FEC library
+ * developed by Phil Karn (KA9Q).
+ *
+ * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
+ * Copyright (C) 2014-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <string.h>
+#if HAVE_LIBPTHREAD
+#include <pthread.h>
+#endif
+
+#include "rsecc.h"
+
+#if HAVE_LIBPTHREAD
+static pthread_mutex_t RSECC_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+static int initialized = 0;
+
+#define SYMBOL_SIZE (8)
+#define symbols ((1U << SYMBOL_SIZE) - 1)
+static const unsigned int proot = 0x11d; /* stands for x^8+x^4+x^3+x^2+1 (see p.37 of JIS X0510:2004) */
+
+/* min/max codeword length of ECC, calculated from the specification. */
+#define min_length (2)
+#define max_length (30)
+#define max_generatorSize (max_length)
+
+static unsigned char alpha[symbols + 1];
+static unsigned char aindex[symbols + 1];
+static unsigned char generator[max_length - min_length + 1][max_generatorSize + 1];
+static unsigned char generatorInitialized[max_length - min_length + 1];
+
+static void RSECC_initLookupTable(void)
+{
+ unsigned int i, b;
+
+ alpha[symbols] = 0;
+ aindex[0] = symbols;
+
+ b = 1;
+ for(i = 0; i < symbols; i++) {
+ alpha[i] = (unsigned char)b;
+ aindex[b] = (unsigned char)i;
+ b <<= 1;
+ if(b & (symbols + 1)) {
+ b ^= proot;
+ }
+ b &= symbols;
+ }
+}
+
+static void RSECC_init(void)
+{
+ RSECC_initLookupTable();
+ memset(generatorInitialized, 0, (max_length - min_length + 1));
+ initialized = 1;
+}
+
+static void generator_init(size_t length)
+{
+ size_t i, j;
+ int g[max_generatorSize + 1];
+
+ g[0] = 1;
+ for(i = 0; i < length; i++) {
+ g[i + 1] = 1;
+ /* Because g[0] never be zero, skipped some conditional checks. */
+ for(j = i; j > 0; j--) {
+ g[j] = g[j - 1] ^ alpha[(aindex[g[j]] + i) % symbols];
+ }
+ g[0] = alpha[(aindex[g[0]] + i) % symbols];
+ }
+
+ for(i = 0; i <= length; i++) {
+ generator[length - min_length][i] = aindex[g[i]];
+ }
+
+ generatorInitialized[length - min_length] = 1;
+}
+
+int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc)
+{
+ size_t i, j;
+ unsigned char feedback;
+ unsigned char *gen;
+
+#if HAVE_LIBPTHREAD
+ pthread_mutex_lock(&RSECC_mutex);
+#endif
+ if(!initialized) {
+ RSECC_init();
+ }
+#if HAVE_LIBPTHREAD
+ pthread_mutex_unlock(&RSECC_mutex);
+#endif
+
+ if(ecc_length > max_length) return -1;
+
+ memset(ecc, 0, ecc_length);
+#if HAVE_LIBPTHREAD
+ pthread_mutex_lock(&RSECC_mutex);
+#endif
+ if(!generatorInitialized[ecc_length - min_length]) generator_init(ecc_length);
+#if HAVE_LIBPTHREAD
+ pthread_mutex_unlock(&RSECC_mutex);
+#endif
+ gen = generator[ecc_length - min_length];
+
+ for(i = 0; i < data_length; i++) {
+ feedback = aindex[data[i] ^ ecc[0]];
+ if(feedback != symbols) {
+ for(j = 1; j < ecc_length; j++) {
+ ecc[j] ^= alpha[(unsigned int)(feedback + gen[ecc_length - j]) % symbols];
+ }
+ }
+ memmove(&ecc[0], &ecc[1], ecc_length - 1);
+ if(feedback != symbols) {
+ ecc[ecc_length - 1] = alpha[(unsigned int)(feedback + gen[0]) % symbols];
+ } else {
+ ecc[ecc_length - 1] = 0;
+ }
+ }
+
+ return 0;
+}
diff --git a/genqrcode/rsecc.h b/genqrcode/rsecc.h
new file mode 100644
index 0000000000..2c17dedb92
--- /dev/null
+++ b/genqrcode/rsecc.h
@@ -0,0 +1,31 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Reed solomon error correction code encoder specialized for QR code.
+ * This code is rewritten by Kentaro Fukuchi, referring to the FEC library
+ * developed by Phil Karn (KA9Q).
+ *
+ * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
+ * Copyright (C) 2014-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RSECC_H
+#define RSECC_H
+
+extern int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc);
+
+#endif /* RSECC_H */
diff --git a/genqrcode/split.c b/genqrcode/split.c
new file mode 100644
index 0000000000..9975128a5e
--- /dev/null
+++ b/genqrcode/split.c
@@ -0,0 +1,323 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Input data splitter.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ * or
+ * "Automatic identification and data capture techniques --
+ * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "qrencode.h"
+#include "qrinput.h"
+#include "qrspec.h"
+#include "split.h"
+
+#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10)
+#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0)
+
+#if !HAVE_STRDUP
+#undef strdup
+char *strdup(const char *s)
+{
+ size_t len = strlen(s) + 1;
+ void *newstring = malloc(len);
+ if(newstring == NULL) return NULL;
+ return (char *)memcpy(newstring, s, len);
+}
+#endif
+
+static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint)
+{
+ unsigned char c, d;
+ unsigned int word;
+
+ c = (unsigned char)string[0];
+
+ if(c == '\0') return QR_MODE_NUL;
+ if(isdigit(c)) {
+ return QR_MODE_NUM;
+ } else if(isalnum(c)) {
+ return QR_MODE_AN;
+ } else if(hint == QR_MODE_KANJI) {
+ d = (unsigned char)string[1];
+ if(d != '\0') {
+ word = ((unsigned int)c << 8) | d;
+ if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) {
+ return QR_MODE_KANJI;
+ }
+ }
+ }
+
+ return QR_MODE_8;
+}
+
+static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint);
+static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint);
+
+static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint)
+{
+ const char *p;
+ int ret;
+ int run;
+ int dif;
+ int ln;
+ QRencodeMode mode;
+
+ ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
+
+ p = string;
+ while(isdigit(*p)) {
+ p++;
+ }
+ run = (int)(p - string);
+ mode = Split_identifyMode(p, hint);
+ if(mode == QR_MODE_8) {
+ dif = QRinput_estimateBitsModeNum(run) + 4 + ln
+ + QRinput_estimateBitsMode8(1) /* + 4 + l8 */
+ - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
+ if(dif > 0) {
+ return Split_eat8(string, input, hint);
+ }
+ }
+ if(mode == QR_MODE_AN) {
+ dif = QRinput_estimateBitsModeNum(run) + 4 + ln
+ + QRinput_estimateBitsModeAn(1) /* + 4 + la */
+ - QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */;
+ if(dif > 0) {
+ return Split_eatAn(string, input, hint);
+ }
+ }
+
+ ret = QRinput_append(input, QR_MODE_NUM, run, (const unsigned char *)string);
+ if(ret < 0) return -1;
+
+ return run;
+}
+
+static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint)
+{
+ const char *p, *q;
+ int ret;
+ int run;
+ int dif;
+ int la, ln;
+
+ la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
+ ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
+
+ p = string;
+ while(isalnum(*p)) {
+ if(isdigit(*p)) {
+ q = p;
+ while(isdigit(*q)) {
+ q++;
+ }
+ dif = QRinput_estimateBitsModeAn((int)(p - string)) /* + 4 + la */
+ + QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
+ + (isalnum(*q)?(4 + ln):0)
+ - QRinput_estimateBitsModeAn((int)(q - string)) /* - 4 - la */;
+ if(dif < 0) {
+ break;
+ }
+ p = q;
+ } else {
+ p++;
+ }
+ }
+
+ run = (int)(p - string);
+
+ if(*p && !isalnum(*p)) {
+ dif = QRinput_estimateBitsModeAn(run) + 4 + la
+ + QRinput_estimateBitsMode8(1) /* + 4 + l8 */
+ - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */;
+ if(dif > 0) {
+ return Split_eat8(string, input, hint);
+ }
+ }
+
+ ret = QRinput_append(input, QR_MODE_AN, run, (const unsigned char *)string);
+ if(ret < 0) return -1;
+
+ return run;
+}
+
+static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint)
+{
+ const char *p;
+ int ret;
+ int run;
+
+ p = string;
+ while(Split_identifyMode(p, hint) == QR_MODE_KANJI) {
+ p += 2;
+ }
+ run = (int)(p - string);
+ ret = QRinput_append(input, QR_MODE_KANJI, run, (const unsigned char *)string);
+ if(ret < 0) return -1;
+
+ return run;
+}
+
+static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint)
+{
+ const char *p, *q;
+ QRencodeMode mode;
+ int ret;
+ int run;
+ int dif;
+ int la, ln, l8;
+ int swcost;
+
+ la = QRspec_lengthIndicator(QR_MODE_AN, input->version);
+ ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version);
+ l8 = QRspec_lengthIndicator(QR_MODE_8, input->version);
+
+ p = string + 1;
+ while(*p != '\0') {
+ mode = Split_identifyMode(p, hint);
+ if(mode == QR_MODE_KANJI) {
+ break;
+ }
+ if(mode == QR_MODE_NUM) {
+ q = p;
+ while(isdigit(*q)) {
+ q++;
+ }
+ if(Split_identifyMode(q, hint) == QR_MODE_8) {
+ swcost = 4 + l8;
+ } else {
+ swcost = 0;
+ }
+ dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */
+ + QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln
+ + swcost
+ - QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
+ if(dif < 0) {
+ break;
+ }
+ p = q;
+ } else if(mode == QR_MODE_AN) {
+ q = p;
+ while(isalnum(*q)) {
+ q++;
+ }
+ if(Split_identifyMode(q, hint) == QR_MODE_8) {
+ swcost = 4 + l8;
+ } else {
+ swcost = 0;
+ }
+ dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */
+ + QRinput_estimateBitsModeAn((int)(q - p)) + 4 + la
+ + swcost
+ - QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */;
+ if(dif < 0) {
+ break;
+ }
+ p = q;
+ } else {
+ p++;
+ }
+ }
+
+ run = (int)(p - string);
+ ret = QRinput_append(input, QR_MODE_8, run, (const unsigned char *)string);
+ if(ret < 0) return -1;
+
+ return run;
+}
+
+static int Split_splitString(const char *string, QRinput *input,
+ QRencodeMode hint)
+{
+ int length;
+ QRencodeMode mode;
+
+ while(*string != '\0') {
+ mode = Split_identifyMode(string, hint);
+ if(mode == QR_MODE_NUM) {
+ length = Split_eatNum(string, input, hint);
+ } else if(mode == QR_MODE_AN) {
+ length = Split_eatAn(string, input, hint);
+ } else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) {
+ length = Split_eatKanji(string, input, hint);
+ } else {
+ length = Split_eat8(string, input, hint);
+ }
+ if(length == 0) break;
+ if(length < 0) return -1;
+ string += length;
+ }
+
+ return 0;
+}
+
+static char *dupAndToUpper(const char *str, QRencodeMode hint)
+{
+ char *newstr, *p;
+ QRencodeMode mode;
+
+ newstr = strdup(str);
+ if(newstr == NULL) return NULL;
+
+ p = newstr;
+ while(*p != '\0') {
+ mode = Split_identifyMode(p, hint);
+ if(mode == QR_MODE_KANJI) {
+ p += 2;
+ } else {
+ if (*p >= 'a' && *p <= 'z') {
+ *p = (char)((int)*p - 32);
+ }
+ p++;
+ }
+ }
+
+ return newstr;
+}
+
+int Split_splitStringToQRinput(const char *string, QRinput *input,
+ QRencodeMode hint, int casesensitive)
+{
+ char *newstr;
+ int ret;
+
+ if(string == NULL || *string == '\0') {
+ errno = EINVAL;
+ return -1;
+ }
+ if(!casesensitive) {
+ newstr = dupAndToUpper(string, hint);
+ if(newstr == NULL) return -1;
+ ret = Split_splitString(newstr, input, hint);
+ free(newstr);
+ } else {
+ ret = Split_splitString(string, input, hint);
+ }
+
+ return ret;
+}
diff --git a/genqrcode/split.h b/genqrcode/split.h
new file mode 100644
index 0000000000..81829e078e
--- /dev/null
+++ b/genqrcode/split.h
@@ -0,0 +1,47 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Input data splitter.
+ * Copyright (C) 2006-2017 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * The following data / specifications are taken from
+ * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
+ * or
+ * "Automatic identification and data capture techniques --
+ * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef SPLIT_H
+#define SPLIT_H
+
+#include "qrencode.h"
+
+/**
+ * Split the input string (null terminated) into QRinput.
+ * @param string input string
+ * @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8.
+ * @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS.
+ * @retval 0 success.
+ * @retval -1 an error occurred. errno is set to indicate the error. See
+ * Exceptions for the details.
+ * @throw EINVAL invalid input object.
+ * @throw ENOMEM unable to allocate memory for input objects.
+ */
+extern int Split_splitStringToQRinput(const char *string, QRinput *input,
+ QRencodeMode hint, int casesensitive);
+
+#endif /* SPLIT_H */
diff --git a/genqrcode/tests/CMakeLists.txt b/genqrcode/tests/CMakeLists.txt
new file mode 100644
index 0000000000..4c4a5e8171
--- /dev/null
+++ b/genqrcode/tests/CMakeLists.txt
@@ -0,0 +1,81 @@
+add_library(common
+ common.c common.h)
+target_link_libraries(common qrencode)
+
+add_library(rscode
+ rscode.c rscode.h)
+target_link_libraries(rscode common)
+
+macro(MAKE_TEST test_name)
+ set(ADDITIONAL_LIBS "${ARGN}")
+ add_executable(${test_name} ${test_name}.c)
+ target_link_libraries(${test_name} common ${ADDITIONAL_LIBS})
+ add_test(${test_name} ${test_name})
+endmacro(MAKE_TEST)
+
+if(TARGET PNG::PNG)
+ add_executable(create_frame_pattern create_frame_pattern.c)
+ target_link_libraries(create_frame_pattern common PNG::PNG)
+
+ add_executable(create_mqr_frame_pattern create_mqr_frame_pattern.c)
+ target_link_libraries(create_mqr_frame_pattern common PNG::PNG)
+endif()
+
+if(HAVE_SDL)
+ add_executable(view_qrcode view_qrcode.c)
+ target_link_libraries(view_qrcode common)
+endif(HAVE_SDL)
+
+if(TARGET Threads::Threads)
+ if(HAVE_SYS_TIME_H)
+ add_definitions(-DHAVE_SYS_TIME_H)
+ endif()
+
+ if(HAVE_TIME_H)
+ add_definitions(-DHAVE_TIME_H)
+ endif()
+
+ add_executable(prof_qrencode prof_qrencode.c)
+ target_link_libraries(prof_qrencode common Threads::Threads)
+
+ if(HAVE_PTHREAD_H)
+ add_executable(pthread_qrencode pthread_qrencode.c)
+ target_link_libraries(pthread_qrencode common Threads::Threads)
+ endif()
+endif()
+
+MAKE_TEST(test_bitstream)
+MAKE_TEST(test_estimatebit)
+MAKE_TEST(test_split)
+
+if(TARGET ICONV::ICONV)
+ add_library(decoder STATIC
+ decoder.c decoder.h
+ datachunk.c datachunk.h
+ rsecc_decoder.c rsecc_decoder.h)
+ target_link_libraries(decoder ICONV::ICONV)
+
+ MAKE_TEST(test_qrinput decoder)
+ MAKE_TEST(test_qrspec decoder)
+ target_compile_definitions(test_qrspec PRIVATE -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}/")
+ MAKE_TEST(test_mqrspec decoder)
+ MAKE_TEST(test_qrencode decoder)
+ MAKE_TEST(test_split_urls decoder)
+ MAKE_TEST(test_monkey decoder)
+
+ include(CheckCSourceCompiles)
+ check_c_source_compiles(
+ "int main(){
+ const int w = 1;
+ char buf[w];
+ return 0;
+ }"
+ FIXED_SIZE_BUFFER_INITIALIZATION)
+
+ if(FIXED_SIZE_BUFFER_INITIALIZATION)
+ MAKE_TEST(test_mask decoder)
+ MAKE_TEST(test_mmask decoder)
+ MAKE_TEST(test_rs rscode decoder)
+ endif()
+endif()
+
diff --git a/genqrcode/tests/Makefile.am b/genqrcode/tests/Makefile.am
new file mode 100644
index 0000000000..c7cfad1b37
--- /dev/null
+++ b/genqrcode/tests/Makefile.am
@@ -0,0 +1,86 @@
+AM_CFLAGS =
+AM_LDFLAGS =
+
+if HAVE_SDL
+sdlPROGRAMS = view_qrcode
+AM_CFLAGS += $(SDL_CFLAGS)
+AM_LDFLAGS += $(SDL_LIBS)
+endif
+
+if HAVE_PNG
+pngPROGRAMS = create_frame_pattern create_mqr_frame_pattern
+endif
+
+check_PROGRAMS = test_qrinput test_bitstream test_estimatebit test_qrspec \
+ test_rs test_qrencode test_mqrspec test_split test_mask \
+ test_mmask test_split_urls test_monkey
+noinst_PROGRAMS = $(pngPROGRAMS) $(sdlPROGRAMS) $(check_PROGRAMS) prof_qrencode
+noinst_LIBRARIES = libdecoder.a
+DECODER_LIBS = libdecoder.a $(LIBICONV)
+noinst_HEADERS = common.h rscode.h
+if HAVE_LIBPTHREAD
+noinst_PROGRAMS += pthread_qrencode
+endif
+
+TESTS = $(check_PROGRAMS)
+EXTRA_DIST = test_all.sh test_basic.sh test_configure.sh frame URI_testset.inc CMakeLists.txt
+
+libdecoder_a_SOURCES = decoder.c decoder.h datachunk.c datachunk.h rsecc_decoder.c rsecc_decoder.h
+
+test_qrinput_SOURCES = test_qrinput.c common.c
+test_qrinput_LDADD = $(DECODER_LIBS) ../libqrencode.la
+
+test_bitstream_SOURCES = test_bitstream.c common.c
+test_bitstream_LDADD = ../libqrencode.la
+
+test_estimatebit_SOURCES = test_estimatebit.c common.c
+test_estimatebit_LDADD = ../libqrencode.la
+
+test_qrspec_SOURCES = test_qrspec.c common.c
+test_qrspec_CPPFLAGS = -DSRCDIR=\"$(srcdir)/\"
+test_qrspec_LDADD = $(DECODER_LIBS) ../libqrencode.la
+
+test_mqrspec_SOURCES = test_mqrspec.c common.c
+test_mqrspec_LDADD = $(DECODER_LIBS) ../libqrencode.la
+
+test_rs_SOURCES = test_rs.c rscode.c common.c
+test_rs_LDADD = $(DECODER_LIBS) ../libqrencode.la
+
+test_qrencode_SOURCES = test_qrencode.c common.c
+test_qrencode_LDADD = $(DECODER_LIBS) ../libqrencode.la
+
+test_split_SOURCES = test_split.c common.c
+test_split_LDADD = ../libqrencode.la
+
+test_split_urls_SOURCES = test_split_urls.c common.c
+test_split_urls_LDADD = $(DECODER_LIBS) ../libqrencode.la
+
+test_monkey_SOURCES = test_monkey.c common.c
+test_monkey_LDADD = $(DECODER_LIBS) ../libqrencode.la
+
+test_mask_SOURCES = test_mask.c common.c
+test_mask_LDADD = $(DECODER_LIBS) ../libqrencode.la
+
+test_mmask_SOURCES = test_mmask.c common.c
+test_mmask_LDADD = $(DECODER_LIBS) ../libqrencode.la
+
+prof_qrencode_SOURCES = prof_qrencode.c common.c
+prof_qrencode_LDADD = ../libqrencode.la
+
+pthread_qrencode_SOURCES = pthread_qrencode.c common.c
+pthread_qrencode_LDADD = ../libqrencode.la
+
+if HAVE_PNG
+create_frame_pattern_SOURCES = create_frame_pattern.c common.c
+create_frame_pattern_CFLAGS = $(png_CFLAGS) $(AM_CFLAGS)
+create_frame_pattern_LDADD = ../libqrencode.la $(png_LIBS)
+
+create_mqr_frame_pattern_SOURCES = create_mqr_frame_pattern.c common.c
+create_mqr_frame_pattern_CFLAGS = $(png_CFLAGS) $(AM_CFLAGS)
+create_mqr_frame_pattern_LDADD = ../libqrencode.la $(png_LIBS)
+endif
+
+if HAVE_SDL
+view_qrcode_SOURCES = view_qrcode.c common.c
+view_qrcode_LDADD = ../libqrencode.la
+endif
diff --git a/genqrcode/tests/URI_testset.inc b/genqrcode/tests/URI_testset.inc
new file mode 100644
index 0000000000..9d0fa35ea0
--- /dev/null
+++ b/genqrcode/tests/URI_testset.inc
@@ -0,0 +1,1273 @@
+struct TestSet {
+ size_t expected_length;
+ char *url;
+};
+
+static struct TestSet testset[] = {
+{3132,"http://ads.bluelithium.com/clk?3,eJytjcFqwzAQRL8mNyO0luUoiB7WcQUGS8RFbXBuqVEcxxbKwSDy93HS0P5AH3uYYXd2AKT4hpOjJ-d4njGWdxIySB2nnB0hoVJKRvkmhTXb8GRyIWBVdw0W01bRAh-Y3Vfb4ItS4Ee.fcqdQBJLQsTg2.5nmzOT479QirH4fOkKcfnfL9WDMk09vhd.ZxpM2cSD17G2yh8uetZWTfoGQ7tXY22N1xa53lfc2DYz.W.yLUnO83xdMVylapkYI7kdzyGQLvjF3wHZQ1eK,http%3A%2F%2Fomicronpath.com%2F%3Fa%3D448%26c%3D3201%26s1%3DYahooStream_917_Nevada4"},
+{3745,"http://ads.bluelithium.com/clk?3,eJytjd2OgjAQhZ.GO9K0lEpJ48WwUNekdIWoBO8UCfKX7gUJ4tNv3bj6AvtlLs7knDlDiDgzSi8sqDzOAtfnviAecSuGGT25DhZCUGwN4tOAOX1lDGxUmULYZT0O4cGnyYoankQcsvrjV245oClCiDfDn8.UYQn.QsS7cP.UGwDbX9vXjdSp6uLwHUuIjtL5ay1btZPDsU3GZCf7ZCZNkcte5YdG3.c33cZY5wU7pq.LleNcx.F7QWHhSjvTNKH5dDUGlWaw-w-Jy1ek,http%3A%2F%2Ftanphysics.com%2Farticles%2Freview1.php%3Futm_source%3DUSA%26utm_medium%3DYHO%26utm_content%3D917-STRM4%26utm_campaign%3DYHO%26keyword%3DYHO-917-STRM4"},
+{896,"http://amigo.geneontology.org/cgi-bin/amigo/go.cgi?view=details&search_constraint=terms&depth=0&query=GO:0042438"},
+{611,"http://amigo.geneontology.org/cgi-bin/amigo/gp-assoc.cgi?gp=UniProtKB:P30046"},
+{212,"http://answers.yahoo.com/"},
+{196,"http://autos.yahoo.com/"},
+{348,"http://baseball.fantasysports.yahoo.com/b1"},
+{234,"http://biogps.org/gene/1652/"},
+{644,"http://blog.washingtonpost.com/dcsportsbog/2007/05/a_caron_butler_surprise.html"},
+{340,"http://ca.wikipedia.org/wiki/Caron_Butler"},
+{212,"http://careers.yahoo.com/"},
+{404,"http://commons.wikimedia.org/wiki/Atlas_of_Turkey"},
+{380,"http://creativecommons.org/licenses/by-sa/3.0/"},
+{380,"http://da.wikipedia.org/wiki/Johann_David_Wyss"},
+{244,"http://de.wikipedia.org/wiki/"},
+{340,"http://de.wikipedia.org/wiki/Caron_Butler"},
+{380,"http://de.wikipedia.org/wiki/Johann_David_Wyss"},
+{340,"http://de.wikipedia.org/wiki/Massey_Lopes"},
+{512,"http://de.wikipedia.org/wiki/T%C3%BCrkische_Verfassung_von_1921"},
+{336,"http://dx.doi.org/10.1002%2Felps.11501301201"},
+{334,"http://dx.doi.org/10.1006%2Fbbrc.1993.2524"},
+{296,"http://dx.doi.org/10.1007%2Fs003359900858"},
+{304,"http://dx.doi.org/10.1021%2Fbi982184o"},
+{402,"http://dx.doi.org/10.1034%2Fj.1600-0625.2003.120307.x"},
+{255,"http://dx.doi.org/10.1038%2F990031"},
+{296,"http://dx.doi.org/10.1038%2Fmsb4100134"},
+{282,"http://dx.doi.org/10.1038%2Fnbt810"},
+{329,"http://dx.doi.org/10.1073%2Fpnas.242603899"},
+{326,"http://dx.doi.org/10.1074%2Fjbc.M203220200"},
+{307,"http://dx.doi.org/10.1101%2Fgr.2596504"},
+{360,"http://dx.doi.org/10.1186%2Fgb-2004-5-10-r84"},
+{228,"http://education.yahoo.com/"},
+{364,"http://en.m.wikipedia.org/wiki/Ambrose_Dyson"},
+{356,"http://en.m.wikipedia.org/wiki/Caron_Butler"},
+{340,"http://en.m.wikipedia.org/wiki/DDT_(gene)"},
+{396,"http://en.m.wikipedia.org/wiki/Johann_David_Wyss"},
+{332,"http://en.m.wikipedia.org/wiki/Lady_Anne"},
+{492,"http://en.m.wikipedia.org/wiki/Sir_Massey_Lopes,_3rd_Baronet"},
+{308,"http://en.m.wikipedia.org/wiki/Tumula"},
+{480,"http://en.m.wikipedia.org/wiki/Turkish_Constitution_of_1921"},
+{556,"http://en.m.wikipedia.org/wiki/Vietnam_University_Admission_Rankings"},
+{444,"http://en.m.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{196,"http://en.wikipedia.org"},
+{816,"http://en.wikipedia.org/w/index.php?title=2013%E2%80%9314_Milwaukee_Bucks_season&action=edit&redlink=1"},
+{548,"http://en.wikipedia.org/w/index.php?title=Ambrose_Dyson&action=edit"},
+{628,"http://en.wikipedia.org/w/index.php?title=Ambrose_Dyson&action=edit&section=1"},
+{572,"http://en.wikipedia.org/w/index.php?title=Ambrose_Dyson&action=history"},
+{548,"http://en.wikipedia.org/w/index.php?title=Ambrose_Dyson&action=info"},
+{552,"http://en.wikipedia.org/w/index.php?title=Ambrose_Dyson&oldid=562636681"},
+{564,"http://en.wikipedia.org/w/index.php?title=Ambrose_Dyson&printable=yes"},
+{564,"http://en.wikipedia.org/w/index.php?title=Ambrose_Dyson&veaction=edit"},
+{644,"http://en.wikipedia.org/w/index.php?title=Ambrose_Dyson&veaction=edit&section=1"},
+{540,"http://en.wikipedia.org/w/index.php?title=Caron_Butler&action=edit"},
+{620,"http://en.wikipedia.org/w/index.php?title=Caron_Butler&action=edit&section=1"},
+{564,"http://en.wikipedia.org/w/index.php?title=Caron_Butler&action=history"},
+{540,"http://en.wikipedia.org/w/index.php?title=Caron_Butler&action=info"},
+{544,"http://en.wikipedia.org/w/index.php?title=Caron_Butler&oldid=571697645"},
+{556,"http://en.wikipedia.org/w/index.php?title=Caron_Butler&printable=yes"},
+{556,"http://en.wikipedia.org/w/index.php?title=Caron_Butler&veaction=edit"},
+{636,"http://en.wikipedia.org/w/index.php?title=Caron_Butler&veaction=edit&section=1"},
+{780,"http://en.wikipedia.org/w/index.php?title=Court_of_Jurisdictional_Conflict&action=edit&redlink=1"},
+{524,"http://en.wikipedia.org/w/index.php?title=DDT_(gene)&action=edit"},
+{604,"http://en.wikipedia.org/w/index.php?title=DDT_(gene)&action=edit&section=1"},
+{548,"http://en.wikipedia.org/w/index.php?title=DDT_(gene)&action=history"},
+{524,"http://en.wikipedia.org/w/index.php?title=DDT_(gene)&action=info"},
+{528,"http://en.wikipedia.org/w/index.php?title=DDT_(gene)&oldid=453962249"},
+{540,"http://en.wikipedia.org/w/index.php?title=DDT_(gene)&printable=yes"},
+{540,"http://en.wikipedia.org/w/index.php?title=DDT_(gene)&veaction=edit"},
+{620,"http://en.wikipedia.org/w/index.php?title=DDT_(gene)&veaction=edit&section=1"},
+{724,"http://en.wikipedia.org/w/index.php?title=Devonshire_County_Council&action=edit&redlink=1"},
+{812,"http://en.wikipedia.org/w/index.php?title=H%C3%A0_T%C4%A9nh_Gifted_High_School&action=edit&redlink=1"},
+{820,"http://en.wikipedia.org/w/index.php?title=H%C6%B0ng_Y%C3%AAn_Gifted_High_School&action=edit&redlink=1"},
+{580,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&action=edit"},
+{660,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&action=edit&section=1"},
+{660,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&action=edit&section=2"},
+{604,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&action=history"},
+{580,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&action=info"},
+{584,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&oldid=568638498"},
+{596,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&printable=yes"},
+{596,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&veaction=edit"},
+{676,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&veaction=edit&section=1"},
+{676,"http://en.wikipedia.org/w/index.php?title=Johann_David_Wyss&veaction=edit&section=2"},
+{684,"http://en.wikipedia.org/w/index.php?title=Johann_Emmanuel_Wyss&action=edit&redlink=1"},
+{652,"http://en.wikipedia.org/w/index.php?title=Josh_Oppenheimer&action=edit&redlink=1"},
+{588,"http://en.wikipedia.org/w/index.php?title=Lady_Ann&action=edit&redlink=1"},
+{516,"http://en.wikipedia.org/w/index.php?title=Lady_Anne&action=edit"},
+{596,"http://en.wikipedia.org/w/index.php?title=Lady_Anne&action=edit&section=1"},
+{540,"http://en.wikipedia.org/w/index.php?title=Lady_Anne&action=history"},
+{516,"http://en.wikipedia.org/w/index.php?title=Lady_Anne&action=info"},
+{520,"http://en.wikipedia.org/w/index.php?title=Lady_Anne&oldid=372343156"},
+{532,"http://en.wikipedia.org/w/index.php?title=Lady_Anne&printable=yes"},
+{532,"http://en.wikipedia.org/w/index.php?title=Lady_Anne&veaction=edit"},
+{612,"http://en.wikipedia.org/w/index.php?title=Lady_Anne&veaction=edit&section=1"},
+{740,"http://en.wikipedia.org/w/index.php?title=Military_Court_of_Cassation&action=edit&redlink=1"},
+{820,"http://en.wikipedia.org/w/index.php?title=Military_High_Court_of_Administration&action=edit&redlink=1"},
+{620,"http://en.wikipedia.org/w/index.php?title=Monte_Mathis&action=edit&redlink=1"},
+{764,"http://en.wikipedia.org/w/index.php?title=Quang_Trung_Gifted_High_School&action=edit&redlink=1"},
+{740,"http://en.wikipedia.org/w/index.php?title=Robert_Hackett_(basketball)&action=edit&redlink=1"},
+{676,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&action=edit"},
+{756,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&action=edit&section=1"},
+{700,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&action=history"},
+{676,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&action=info"},
+{680,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&oldid=545042390"},
+{692,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&printable=yes"},
+{692,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&veaction=edit"},
+{772,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&veaction=edit&section=1"},
+{772,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&veaction=edit&section=2"},
+{772,"http://en.wikipedia.org/w/index.php?title=Sir_Massey_Lopes,_3rd_Baronet&veaction=edit&section=3"},
+{788,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=Ambrose+Dyson"},
+{780,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=Caron+Butler"},
+{796,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=DDT+%28gene%29"},
+{820,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=Johann+David+Wyss"},
+{756,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=Lady+Anne"},
+{932,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=Sir+Massey+Lopes%2C+3rd+Baronet"},
+{732,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=Tumula"},
+{908,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=Turkish+Constitution+of+1921"},
+{980,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=Vietnam+University+Admission+Rankings"},
+{868,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=book_creator&referer=Vy%C5%A1n%C3%BD+Slavkov"},
+{1004,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=Ambrose+Dyson&oldid=562636681&writer=rl"},
+{996,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=Caron+Butler&oldid=571697645&writer=rl"},
+{1012,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=DDT+%28gene%29&oldid=453962249&writer=rl"},
+{1036,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=Johann+David+Wyss&oldid=568638498&writer=rl"},
+{972,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=Lady+Anne&oldid=372343156&writer=rl"},
+{1148,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=Sir+Massey+Lopes%2C+3rd+Baronet&oldid=545042390&writer=rl"},
+{948,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=Tumula&oldid=401070860&writer=rl"},
+{1124,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=Turkish+Constitution+of+1921&oldid=566504847&writer=rl"},
+{1196,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=Vietnam+University+Admission+Rankings&oldid=568532236&writer=rl"},
+{1084,"http://en.wikipedia.org/w/index.php?title=Special:Book&bookcmd=render_article&arttitle=Vy%C5%A1n%C3%BD+Slavkov&oldid=541325469&writer=rl"},
+{672,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=Ambrose_Dyson&id=562636681"},
+{664,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=Caron_Butler&id=571697645"},
+{680,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=DDT_%28gene%29&id=453962249"},
+{704,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=Johann_David_Wyss&id=568638498"},
+{640,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=Lady_Anne&id=372343156"},
+{816,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=Sir_Massey_Lopes%2C_3rd_Baronet&id=545042390"},
+{616,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=Tumula&id=401070860"},
+{792,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=Turkish_Constitution_of_1921&id=566504847"},
+{864,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=Vietnam_University_Admission_Rankings&id=568532236"},
+{752,"http://en.wikipedia.org/w/index.php?title=Special:Cite&page=Vy%C5%A1n%C3%BD_Slavkov&id=541325469"},
+{668,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Ambrose+Dyson"},
+{764,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Ambrose+Dyson&type=signup"},
+{660,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Caron+Butler"},
+{756,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Caron+Butler&type=signup"},
+{676,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=DDT+%28gene%29"},
+{772,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=DDT+%28gene%29&type=signup"},
+{700,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Johann+David+Wyss"},
+{796,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Johann+David+Wyss&type=signup"},
+{636,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Lady+Anne"},
+{732,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Lady+Anne&type=signup"},
+{812,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Sir+Massey+Lopes%2C+3rd+Baronet"},
+{908,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Sir+Massey+Lopes%2C+3rd+Baronet&type=signup"},
+{612,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Tumula"},
+{708,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Tumula&type=signup"},
+{788,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Turkish+Constitution+of+1921"},
+{884,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Turkish+Constitution+of+1921&type=signup"},
+{860,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Vietnam+University+Admission+Rankings"},
+{956,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Vietnam+University+Admission+Rankings&type=signup"},
+{748,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Vy%C5%A1n%C3%BD+Slavkov"},
+{844,"http://en.wikipedia.org/w/index.php?title=Special:UserLogin&returnto=Vy%C5%A1n%C3%BD+Slavkov&type=signup"},
+{692,"http://en.wikipedia.org/w/index.php?title=Special:WhatLinksHere/Lady_Anne&namespace=0"},
+{636,"http://en.wikipedia.org/w/index.php?title=Talk:Lady_Anne&action=edit&redlink=1"},
+{628,"http://en.wikipedia.org/w/index.php?title=Template:2002_NBA_Draft&action=edit"},
+{1028,"http://en.wikipedia.org/w/index.php?title=Template:Big_East_Conference_Men%27s_Basketball_Player_of_the_Year_navbox&action=edit"},
+{636,"http://en.wikipedia.org/w/index.php?title=Template:Cartoonist-stub&action=edit"},
+{692,"http://en.wikipedia.org/w/index.php?title=Template:Constitution_of_Turkey&action=edit"},
+{872,"http://en.wikipedia.org/w/index.php?title=Template:Dallas_Mavericks_2010%E2%80%9311_NBA_champions&action=edit"},
+{612,"http://en.wikipedia.org/w/index.php?title=Template:Gene-22-stub&action=edit"},
+{676,"http://en.wikipedia.org/w/index.php?title=Template:Levo%C4%8Da_District&action=edit"},
+{756,"http://en.wikipedia.org/w/index.php?title=Template:Milwaukee_Bucks_current_roster&action=edit"},
+{636,"http://en.wikipedia.org/w/index.php?title=Template:Noctuoidea-stub&action=edit"},
+{580,"http://en.wikipedia.org/w/index.php?title=Template:PBB/1652&action=edit"},
+{604,"http://en.wikipedia.org/w/index.php?title=Template:PDB_Gallery&action=edit"},
+{660,"http://en.wikipedia.org/w/index.php?title=Template:Politics_of_Turkey&action=edit"},
+{676,"http://en.wikipedia.org/w/index.php?title=Template:Pre%C5%A1ov-geo-stub&action=edit"},
+{700,"http://en.wikipedia.org/w/index.php?title=Template:Switzerland-writer-stub&action=edit"},
+{716,"http://en.wikipedia.org/w/index.php?title=Template:The_Swiss_Family_Robinson&action=edit"},
+{700,"http://en.wikipedia.org/w/index.php?title=Template_talk:PBB/1652&action=edit&redlink=1"},
+{836,"http://en.wikipedia.org/w/index.php?title=Template_talk:The_Swiss_Family_Robinson&action=edit&redlink=1"},
+{492,"http://en.wikipedia.org/w/index.php?title=Tumula&action=edit"},
+{572,"http://en.wikipedia.org/w/index.php?title=Tumula&action=edit&section=1"},
+{516,"http://en.wikipedia.org/w/index.php?title=Tumula&action=history"},
+{492,"http://en.wikipedia.org/w/index.php?title=Tumula&action=info"},
+{496,"http://en.wikipedia.org/w/index.php?title=Tumula&oldid=401070860"},
+{508,"http://en.wikipedia.org/w/index.php?title=Tumula&printable=yes"},
+{508,"http://en.wikipedia.org/w/index.php?title=Tumula&veaction=edit"},
+{588,"http://en.wikipedia.org/w/index.php?title=Tumula&veaction=edit&section=1"},
+{668,"http://en.wikipedia.org/w/index.php?title=Turkish_Constitution_of_1921&action=edit"},
+{748,"http://en.wikipedia.org/w/index.php?title=Turkish_Constitution_of_1921&action=edit&section=1"},
+{692,"http://en.wikipedia.org/w/index.php?title=Turkish_Constitution_of_1921&action=history"},
+{668,"http://en.wikipedia.org/w/index.php?title=Turkish_Constitution_of_1921&action=info"},
+{672,"http://en.wikipedia.org/w/index.php?title=Turkish_Constitution_of_1921&oldid=566504847"},
+{684,"http://en.wikipedia.org/w/index.php?title=Turkish_Constitution_of_1921&printable=yes"},
+{684,"http://en.wikipedia.org/w/index.php?title=Turkish_Constitution_of_1921&veaction=edit"},
+{764,"http://en.wikipedia.org/w/index.php?title=Turkish_Constitution_of_1921&veaction=edit&section=1"},
+{724,"http://en.wikipedia.org/w/index.php?title=Turkish_Court_of_Accounts&action=edit&redlink=1"},
+{740,"http://en.wikipedia.org/w/index.php?title=Vietnam_University_Admission_Rankings&action=edit"},
+{820,"http://en.wikipedia.org/w/index.php?title=Vietnam_University_Admission_Rankings&action=edit&section=1"},
+{764,"http://en.wikipedia.org/w/index.php?title=Vietnam_University_Admission_Rankings&action=history"},
+{740,"http://en.wikipedia.org/w/index.php?title=Vietnam_University_Admission_Rankings&action=info"},
+{744,"http://en.wikipedia.org/w/index.php?title=Vietnam_University_Admission_Rankings&oldid=568532236"},
+{756,"http://en.wikipedia.org/w/index.php?title=Vietnam_University_Admission_Rankings&printable=yes"},
+{756,"http://en.wikipedia.org/w/index.php?title=Vietnam_University_Admission_Rankings&veaction=edit"},
+{836,"http://en.wikipedia.org/w/index.php?title=Vietnam_University_Admission_Rankings&veaction=edit&section=1"},
+{628,"http://en.wikipedia.org/w/index.php?title=Vy%C5%A1n%C3%BD_Slavkov&action=edit"},
+{708,"http://en.wikipedia.org/w/index.php?title=Vy%C5%A1n%C3%BD_Slavkov&action=edit&section=1"},
+{652,"http://en.wikipedia.org/w/index.php?title=Vy%C5%A1n%C3%BD_Slavkov&action=history"},
+{628,"http://en.wikipedia.org/w/index.php?title=Vy%C5%A1n%C3%BD_Slavkov&action=info"},
+{632,"http://en.wikipedia.org/w/index.php?title=Vy%C5%A1n%C3%BD_Slavkov&oldid=541325469"},
+{644,"http://en.wikipedia.org/w/index.php?title=Vy%C5%A1n%C3%BD_Slavkov&printable=yes"},
+{644,"http://en.wikipedia.org/w/index.php?title=Vy%C5%A1n%C3%BD_Slavkov&veaction=edit"},
+{724,"http://en.wikipedia.org/w/index.php?title=Vy%C5%A1n%C3%BD_Slavkov&veaction=edit&section=1"},
+{568,"http://en.wikipedia.org/w/index.php?title=Vyšný_Slavkov&oldid=541325469"},
+{525,"http://en.wikipedia.org/wiki/%C4%90%E1%BA%AFk_L%E1%BA%AFk_Province"},
+{469,"http://en.wikipedia.org/wiki/%C4%90%E1%BB%93ng_Nai_Province"},
+{685,"http://en.wikipedia.org/wiki/2001%E2%80%9302_NCAA_Division_I_men%27s_basketball_season"},
+{493,"http://en.wikipedia.org/wiki/2002%E2%80%9303_Miami_Heat_season"},
+{437,"http://en.wikipedia.org/wiki/2002%E2%80%9303_NBA_season"},
+{356,"http://en.wikipedia.org/wiki/2002_NBA_Draft"},
+{356,"http://en.wikipedia.org/wiki/2002_NBA_draft"},
+{493,"http://en.wikipedia.org/wiki/2003%E2%80%9304_Miami_Heat_season"},
+{437,"http://en.wikipedia.org/wiki/2003%E2%80%9304_NBA_season"},
+{557,"http://en.wikipedia.org/wiki/2004%E2%80%9305_Los_Angeles_Lakers_season"},
+{437,"http://en.wikipedia.org/wiki/2004%E2%80%9305_NBA_season"},
+{380,"http://en.wikipedia.org/wiki/2004_NBA_Playoffs"},
+{437,"http://en.wikipedia.org/wiki/2005%E2%80%9306_NBA_season"},
+{557,"http://en.wikipedia.org/wiki/2005%E2%80%9306_Washington_Wizards_season"},
+{437,"http://en.wikipedia.org/wiki/2006%E2%80%9307_NBA_season"},
+{557,"http://en.wikipedia.org/wiki/2006%E2%80%9307_Washington_Wizards_season"},
+{364,"http://en.wikipedia.org/wiki/2006_NBA_Finals"},
+{380,"http://en.wikipedia.org/wiki/2006_NBA_Playoffs"},
+{437,"http://en.wikipedia.org/wiki/2007%E2%80%9308_NBA_season"},
+{557,"http://en.wikipedia.org/wiki/2007%E2%80%9308_Washington_Wizards_season"},
+{420,"http://en.wikipedia.org/wiki/2007_NBA_All-Star_Game"},
+{437,"http://en.wikipedia.org/wiki/2008%E2%80%9309_NBA_season"},
+{557,"http://en.wikipedia.org/wiki/2008%E2%80%9309_Washington_Wizards_season"},
+{420,"http://en.wikipedia.org/wiki/2008_NBA_All-Star_Game"},
+{380,"http://en.wikipedia.org/wiki/2008_NBA_Playoffs"},
+{541,"http://en.wikipedia.org/wiki/2009%E2%80%9310_Dallas_Mavericks_season"},
+{437,"http://en.wikipedia.org/wiki/2009%E2%80%9310_NBA_season"},
+{557,"http://en.wikipedia.org/wiki/2009%E2%80%9310_Washington_Wizards_season"},
+{541,"http://en.wikipedia.org/wiki/2010%E2%80%9311_Dallas_Mavericks_season"},
+{437,"http://en.wikipedia.org/wiki/2010%E2%80%9311_NBA_season"},
+{380,"http://en.wikipedia.org/wiki/2010_NBA_Playoffs"},
+{573,"http://en.wikipedia.org/wiki/2011%E2%80%9312_Los_Angeles_Clippers_season"},
+{437,"http://en.wikipedia.org/wiki/2011%E2%80%9312_NBA_season"},
+{364,"http://en.wikipedia.org/wiki/2011_NBA_Finals"},
+{380,"http://en.wikipedia.org/wiki/2011_NBA_Playoffs"},
+{573,"http://en.wikipedia.org/wiki/2012%E2%80%9313_Los_Angeles_Clippers_season"},
+{437,"http://en.wikipedia.org/wiki/2012%E2%80%9313_NBA_season"},
+{380,"http://en.wikipedia.org/wiki/2012_NBA_Playoffs"},
+{437,"http://en.wikipedia.org/wiki/2013%E2%80%9314_NBA_season"},
+{380,"http://en.wikipedia.org/wiki/2013_NBA_Playoffs"},
+{380,"http://en.wikipedia.org/wiki/Abdullah_G%C3%BCl"},
+{572,"http://en.wikipedia.org/wiki/Accession_of_Turkey_to_the_European_Union"},
+{308,"http://en.wikipedia.org/wiki/Adelaide"},
+{332,"http://en.wikipedia.org/wiki/Albert_Pell"},
+{308,"http://en.wikipedia.org/wiki/Alderman"},
+{396,"http://en.wikipedia.org/wiki/Alfredton,_Victoria"},
+{340,"http://en.wikipedia.org/wiki/All_American"},
+{412,"http://en.wikipedia.org/wiki/Allies_of_World_War_I"},
+{364,"http://en.wikipedia.org/wiki/Alonzo_Mourning"},
+{396,"http://en.wikipedia.org/wiki/Amar%27e_Stoudemire"},
+{420,"http://en.wikipedia.org/wiki/Amateur_Athletic_Union"},
+{348,"http://en.wikipedia.org/wiki/Ambrose_Dyson"},
+{356,"http://en.wikipedia.org/wiki/Ambrose_Dyson#"},
+{444,"http://en.wikipedia.org/wiki/Ambrose_Dyson#cite_note-2"},
+{516,"http://en.wikipedia.org/wiki/Ambrose_Dyson#cite_note-lindesay-1"},
+{436,"http://en.wikipedia.org/wiki/Ambrose_Dyson#cite_ref-2"},
+{524,"http://en.wikipedia.org/wiki/Ambrose_Dyson#cite_ref-lindesay_1-0"},
+{524,"http://en.wikipedia.org/wiki/Ambrose_Dyson#cite_ref-lindesay_1-1"},
+{460,"http://en.wikipedia.org/wiki/Ambrose_Dyson#mw-navigation"},
+{420,"http://en.wikipedia.org/wiki/Ambrose_Dyson#p-search"},
+{292,"http://en.wikipedia.org/wiki/Animal"},
+{580,"http://en.wikipedia.org/wiki/Anne,_Duchess_of_Cumberland_and_Strathearn"},
+{324,"http://en.wikipedia.org/wiki/Anne_Bacon"},
+{332,"http://en.wikipedia.org/wiki/Anne_Brewis"},
+{492,"http://en.wikipedia.org/wiki/Anne_Conway,_Viscountess_Conway"},
+{340,"http://en.wikipedia.org/wiki/Anne_Halkett"},
+{316,"http://en.wikipedia.org/wiki/Anne_Hyde"},
+{340,"http://en.wikipedia.org/wiki/Anne_Lambton"},
+{500,"http://en.wikipedia.org/wiki/Anne_Lennard,_Countess_of_Sussex"},
+{500,"http://en.wikipedia.org/wiki/Anne_Stanley,_Countess_of_Ancram"},
+{540,"http://en.wikipedia.org/wiki/Anne_Stanley,_Countess_of_Castlehaven"},
+{332,"http://en.wikipedia.org/wiki/Anne_Wilson"},
+{356,"http://en.wikipedia.org/wiki/Antawn_Jamison"},
+{276,"http://en.wikipedia.org/wiki/Area"},
+{316,"http://en.wikipedia.org/wiki/Arthropod"},
+{396,"http://en.wikipedia.org/wiki/Assist_(basketball)"},
+{436,"http://en.wikipedia.org/wiki/Atat%C3%BCrk%27s_Reforms"},
+{380,"http://en.wikipedia.org/wiki/Authority_control"},
+{669,"http://en.wikipedia.org/wiki/B%C3%A0_R%E1%BB%8Ba%E2%80%93V%C5%A9ng_T%C3%A0u_Province"},
+{520,"http://en.wikipedia.org/wiki/B%C3%ACnh_%C4%90%E1%BB%8Bnh_Province"},
+{528,"http://en.wikipedia.org/wiki/B%C3%ACnh_Ph%C6%B0%E1%BB%9Bc_Province"},
+{450,"http://en.wikipedia.org/wiki/B%E1%BA%AFc_Giang_Province"},
+{442,"http://en.wikipedia.org/wiki/B%E1%BA%AFc_Ninh_Province"},
+{308,"http://en.wikipedia.org/wiki/Baldovce"},
+{308,"http://en.wikipedia.org/wiki/Ballarat"},
+{388,"http://en.wikipedia.org/wiki/Ballarat,_Victoria"},
+{364,"http://en.wikipedia.org/wiki/Baron_Roborough"},
+{324,"http://en.wikipedia.org/wiki/Basketball"},
+{316,"http://en.wikipedia.org/wiki/Beharovce"},
+{356,"http://en.wikipedia.org/wiki/Ben_Hansbrough"},
+{380,"http://en.wikipedia.org/wiki/Benjamin_Disraeli"},
+{476,"http://en.wikipedia.org/wiki/Beverly_Hills_Family_Robinson"},
+{539,"http://en.wikipedia.org/wiki/Big_East_Conference_(1979%E2%80%932013)"},
+{700,"http://en.wikipedia.org/wiki/Big_East_Conference_Men%27s_Basketball_Player_of_the_Year"},
+{316,"http://en.wikipedia.org/wiki/Bijacovce"},
+{644,"http://en.wikipedia.org/wiki/Bill_Russell_NBA_Finals_Most_Valuable_Player_Award"},
+{332,"http://en.wikipedia.org/wiki/Billy_Owens"},
+{444,"http://en.wikipedia.org/wiki/Biological_classification"},
+{388,"http://en.wikipedia.org/wiki/Block_(basketball)"},
+{284,"http://en.wikipedia.org/wiki/Blogs"},
+{404,"http://en.wikipedia.org/wiki/Bo%C5%A1tjan_Nachbar"},
+{324,"http://en.wikipedia.org/wiki/Bob_Bender"},
+{356,"http://en.wikipedia.org/wiki/Brandin_Knight"},
+{460,"http://en.wikipedia.org/wiki/Brandon_Knight_(basketball)"},
+{364,"http://en.wikipedia.org/wiki/Brendan_Haywood"},
+{356,"http://en.wikipedia.org/wiki/Brian_Cardinal"},
+{332,"http://en.wikipedia.org/wiki/Brian_Grant"},
+{308,"http://en.wikipedia.org/wiki/Brutovce"},
+{308,"http://en.wikipedia.org/wiki/Buglovce"},
+{332,"http://en.wikipedia.org/wiki/Burger_King"},
+{340,"http://en.wikipedia.org/wiki/C._J._Dennis"},
+{380,"http://en.wikipedia.org/wiki/Cabinet_of_Turkey"},
+{292,"http://en.wikipedia.org/wiki/Caliph"},
+{316,"http://en.wikipedia.org/wiki/Caliphate"},
+{372,"http://en.wikipedia.org/wiki/Carlo_Pellegrini"},
+{348,"http://en.wikipedia.org/wiki/Carlos_Boozer"},
+{356,"http://en.wikipedia.org/wiki/Carlos_Delfino"},
+{340,"http://en.wikipedia.org/wiki/Caron_Butler"},
+{348,"http://en.wikipedia.org/wiki/Caron_Butler#"},
+{460,"http://en.wikipedia.org/wiki/Caron_Butler#College_career"},
+{428,"http://en.wikipedia.org/wiki/Caron_Butler#Early_life"},
+{460,"http://en.wikipedia.org/wiki/Caron_Butler#External_links"},
+{428,"http://en.wikipedia.org/wiki/Caron_Butler#NBA_career"},
+{516,"http://en.wikipedia.org/wiki/Caron_Butler#NBA_career_statistics"},
+{452,"http://en.wikipedia.org/wiki/Caron_Butler#Personal_life"},
+{412,"http://en.wikipedia.org/wiki/Caron_Butler#Playoffs"},
+{428,"http://en.wikipedia.org/wiki/Caron_Butler#References"},
+{460,"http://en.wikipedia.org/wiki/Caron_Butler#Regular_season"},
+{444,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-10"},
+{436,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-5"},
+{524,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-AllStories-7"},
+{466,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-BK-20"},
+{492,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-oprah1-1"},
+{492,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-oprah2-2"},
+{492,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-straws-3"},
+{524,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-toughjuice-8"},
+{516,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-washtimes-9"},
+{556,"http://en.wikipedia.org/wiki/Caron_Butler#cite_note-wp-greatescape-4"},
+{436,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-10"},
+{428,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-5"},
+{532,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-AllStories_7-0"},
+{532,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-AllStories_7-1"},
+{476,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-BK_20-0"},
+{476,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-BK_20-1"},
+{500,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-oprah1_1-0"},
+{500,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-oprah2_2-0"},
+{500,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-straws_3-0"},
+{500,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-straws_3-1"},
+{500,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-straws_3-2"},
+{532,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-toughjuice_8-0"},
+{524,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-washtimes_9-0"},
+{564,"http://en.wikipedia.org/wiki/Caron_Butler#cite_ref-wp-greatescape_4-0"},
+{452,"http://en.wikipedia.org/wiki/Caron_Butler#mw-navigation"},
+{412,"http://en.wikipedia.org/wiki/Caron_Butler#p-search"},
+{324,"http://en.wikipedia.org/wiki/Cartoonist"},
+{356,"http://en.wikipedia.org/wiki/Casey_Jacobsen"},
+{404,"http://en.wikipedia.org/wiki/Category:1743_births"},
+{404,"http://en.wikipedia.org/wiki/Category:1818_births"},
+{404,"http://en.wikipedia.org/wiki/Category:1818_deaths"},
+{404,"http://en.wikipedia.org/wiki/Category:1876_births"},
+{404,"http://en.wikipedia.org/wiki/Category:1908_deaths"},
+{404,"http://en.wikipedia.org/wiki/Category:1913_deaths"},
+{524,"http://en.wikipedia.org/wiki/Category:1921_in_the_Ottoman_Empire"},
+{404,"http://en.wikipedia.org/wiki/Category:1980_births"},
+{492,"http://en.wikipedia.org/wiki/Category:19th-century_novelists"},
+{576,"http://en.wikipedia.org/wiki/Category:Accuracy_disputes_from_March_2012"},
+{596,"http://en.wikipedia.org/wiki/Category:African-American_basketball_players"},
+{572,"http://en.wikipedia.org/wiki/Category:All_article_disambiguation_pages"},
+{636,"http://en.wikipedia.org/wiki/Category:All_articles_lacking_reliable_references"},
+{652,"http://en.wikipedia.org/wiki/Category:All_articles_needing_additional_references"},
+{572,"http://en.wikipedia.org/wiki/Category:All_articles_needing_coordinates"},
+{532,"http://en.wikipedia.org/wiki/Category:All_articles_to_be_expanded"},
+{620,"http://en.wikipedia.org/wiki/Category:All_articles_with_unsourced_statements"},
+{508,"http://en.wikipedia.org/wiki/Category:All_disambiguation_pages"},
+{620,"http://en.wikipedia.org/wiki/Category:All_pages_needing_factual_verification"},
+{644,"http://en.wikipedia.org/wiki/Category:Articles_containing_Turkish-language_text"},
+{752,"http://en.wikipedia.org/wiki/Category:Articles_lacking_reliable_references_from_February_2013"},
+{760,"http://en.wikipedia.org/wiki/Category:Articles_needing_additional_references_from_January_2011"},
+{716,"http://en.wikipedia.org/wiki/Category:Articles_needing_translation_from_German_Wikipedia"},
+{632,"http://en.wikipedia.org/wiki/Category:Articles_to_be_expanded_from_August_2013"},
+{636,"http://en.wikipedia.org/wiki/Category:Articles_with_%27species%27_microformats"},
+{744,"http://en.wikipedia.org/wiki/Category:Articles_with_unsourced_statements_from_September_2010"},
+{492,"http://en.wikipedia.org/wiki/Category:Australian_cartoonists"},
+{500,"http://en.wikipedia.org/wiki/Category:Australian_illustrators"},
+{476,"http://en.wikipedia.org/wiki/Category:Australian_satirists"},
+{700,"http://en.wikipedia.org/wiki/Category:Baronets_in_the_Baronetage_of_the_United_Kingdom"},
+{580,"http://en.wikipedia.org/wiki/Category:Basketball_players_from_Wisconsin"},
+{444,"http://en.wikipedia.org/wiki/Category:Cartoonist_stubs"},
+{524,"http://en.wikipedia.org/wiki/Category:Cartoonists_from_Melbourne"},
+{508,"http://en.wikipedia.org/wiki/Category:Chromosome_22_gene_stubs"},
+{684,"http://en.wikipedia.org/wiki/Category:Connecticut_Huskies_men%27s_basketball_players"},
+{532,"http://en.wikipedia.org/wiki/Category:Conservative_Party_(UK)_MPs"},
+{500,"http://en.wikipedia.org/wiki/Category:Constitutions_of_Turkey"},
+{508,"http://en.wikipedia.org/wiki/Category:Dallas_Mavericks_players"},
+{484,"http://en.wikipedia.org/wiki/Category:Defunct_constitutions"},
+{476,"http://en.wikipedia.org/wiki/Category:Disambiguation_pages"},
+{492,"http://en.wikipedia.org/wiki/Category:High_Sheriffs_of_Devon"},
+{620,"http://en.wikipedia.org/wiki/Category:High_schools_for_the_gifted_in_Vietnam"},
+{500,"http://en.wikipedia.org/wiki/Category:High_schools_in_Vietnam"},
+{428,"http://en.wikipedia.org/wiki/Category:Human_proteins"},
+{420,"http://en.wikipedia.org/wiki/Category:Living_people"},
+{540,"http://en.wikipedia.org/wiki/Category:Los_Angeles_Clippers_players"},
+{524,"http://en.wikipedia.org/wiki/Category:Los_Angeles_Lakers_players"},
+{852,"http://en.wikipedia.org/wiki/Category:Members_of_the_United_Kingdom_Parliament_for_English_constituencies"},
+{492,"http://en.wikipedia.org/wiki/Category:Miami_Heat_draft_picks"},
+{460,"http://en.wikipedia.org/wiki/Category:Miami_Heat_players"},
+{428,"http://en.wikipedia.org/wiki/Category:Micronoctuidae"},
+{644,"http://en.wikipedia.org/wiki/Category:National_Basketball_Association_All-Stars"},
+{444,"http://en.wikipedia.org/wiki/Category:Noctuoidea_stubs"},
+{556,"http://en.wikipedia.org/wiki/Category:Pages_with_no_translate_target"},
+{444,"http://en.wikipedia.org/wiki/Category:People_from_Bern"},
+{548,"http://en.wikipedia.org/wiki/Category:People_from_Racine,_Wisconsin"},
+{588,"http://en.wikipedia.org/wiki/Category:Pre%C5%A1ov_Region_geography_stubs"},
+{460,"http://en.wikipedia.org/wiki/Category:Schools_in_Vietnam"},
+{436,"http://en.wikipedia.org/wiki/Category:Shooting_guards"},
+{428,"http://en.wikipedia.org/wiki/Category:Small_forwards"},
+{386,"http://en.wikipedia.org/wiki/Category:Spi%C5%A1"},
+{524,"http://en.wikipedia.org/wiki/Category:Swiss_children%27s_writers"},
+{436,"http://en.wikipedia.org/wiki/Category:Swiss_novelists"},
+{460,"http://en.wikipedia.org/wiki/Category:Swiss_writer_stubs"},
+{479,"http://en.wikipedia.org/wiki/Category:UK_MPs_1857%E2%80%931859"},
+{479,"http://en.wikipedia.org/wiki/Category:UK_MPs_1859%E2%80%931865"},
+{479,"http://en.wikipedia.org/wiki/Category:UK_MPs_1868%E2%80%931874"},
+{479,"http://en.wikipedia.org/wiki/Category:UK_MPs_1874%E2%80%931880"},
+{479,"http://en.wikipedia.org/wiki/Category:UK_MPs_1880%E2%80%931885"},
+{548,"http://en.wikipedia.org/wiki/Category:United_States_Navy_ship_names"},
+{592,"http://en.wikipedia.org/wiki/Category:Use_British_English_from_March_2012"},
+{560,"http://en.wikipedia.org/wiki/Category:Use_dmy_dates_from_January_2012"},
+{536,"http://en.wikipedia.org/wiki/Category:Use_dmy_dates_from_July_2013"},
+{660,"http://en.wikipedia.org/wiki/Category:Vietnam_articles_missing_geocoordinate_data"},
+{724,"http://en.wikipedia.org/wiki/Category:Villages_and_municipalities_in_Levo%C4%8Da_District"},
+{524,"http://en.wikipedia.org/wiki/Category:Washington_Wizards_players"},
+{964,"http://en.wikipedia.org/wiki/Category:Wikipedia_articles_incorporating_an_LRPP-Bt_template_without_an_unnamed_parameter"},
+{816,"http://en.wikipedia.org/wiki/Category:Wikipedia_articles_needing_factual_verification_from_March_2012"},
+{848,"http://en.wikipedia.org/wiki/Category:Wikipedia_articles_needing_page_number_citations_from_February_2013"},
+{636,"http://en.wikipedia.org/wiki/Category:Wikipedia_articles_with_VIAF_identifiers"},
+{412,"http://en.wikipedia.org/wiki/Cemil_%C3%87i%C3%A7ek"},
+{540,"http://en.wikipedia.org/wiki/Charles_Smith_(basketball,_born_1965)"},
+{540,"http://en.wikipedia.org/wiki/Charles_Smith_(basketball,_born_1967)"},
+{364,"http://en.wikipedia.org/wiki/Chris_Jefferies"},
+{444,"http://en.wikipedia.org/wiki/Chris_Mullin_(basketball)"},
+{436,"http://en.wikipedia.org/wiki/Chris_Owens_(basketball)"},
+{340,"http://en.wikipedia.org/wiki/Chris_Wilcox"},
+{348,"http://en.wikipedia.org/wiki/Chromosome_22"},
+{348,"http://en.wikipedia.org/wiki/Chucky_Atkins"},
+{380,"http://en.wikipedia.org/wiki/Clare_Sewell_Read"},
+{396,"http://en.wikipedia.org/wiki/Cleveland_Cavaliers"},
+{548,"http://en.wikipedia.org/wiki/Connecticut_Huskies_men%27s_basketball"},
+{499,"http://en.wikipedia.org/wiki/Conservative_Government_1874-1880"},
+{428,"http://en.wikipedia.org/wiki/Conservative_Party_(UK)"},
+{340,"http://en.wikipedia.org/wiki/Constitution"},
+{420,"http://en.wikipedia.org/wiki/Constitution_of_Turkey"},
+{484,"http://en.wikipedia.org/wiki/Constitutional_Court_of_Turkey"},
+{500,"http://en.wikipedia.org/wiki/Constitutional_history_of_Turkey"},
+{428,"http://en.wikipedia.org/wiki/Constitutional_monarchy"},
+{340,"http://en.wikipedia.org/wiki/Corey_Brewer"},
+{364,"http://en.wikipedia.org/wiki/Corsley_Edwards"},
+{460,"http://en.wikipedia.org/wiki/Court_of_Cassation_(Turkey)"},
+{372,"http://en.wikipedia.org/wiki/Curtis_Borchardt"},
+{516,"http://en.wikipedia.org/wiki/D%C3%BAbrava,_Levo%C4%8Da_District"},
+{324,"http://en.wikipedia.org/wiki/DDT_(gene)"},
+{332,"http://en.wikipedia.org/wiki/DDT_(gene)#"},
+{476,"http://en.wikipedia.org/wiki/DDT_(gene)#cite_note-entrez-3"},
+{506,"http://en.wikipedia.org/wiki/DDT_(gene)#cite_note-pmid9480844-1"},
+{484,"http://en.wikipedia.org/wiki/DDT_(gene)#cite_ref-entrez_3-0"},
+{484,"http://en.wikipedia.org/wiki/DDT_(gene)#cite_ref-entrez_3-1"},
+{518,"http://en.wikipedia.org/wiki/DDT_(gene)#cite_ref-pmid9480844_1-0"},
+{436,"http://en.wikipedia.org/wiki/DDT_(gene)#mw-navigation"},
+{396,"http://en.wikipedia.org/wiki/DDT_(gene)#p-search"},
+{300,"http://en.wikipedia.org/wiki/Da_Nang"},
+{348,"http://en.wikipedia.org/wiki/Dajuan_Wagner"},
+{372,"http://en.wikipedia.org/wiki/Dallas_Mavericks"},
+{372,"http://en.wikipedia.org/wiki/Dan_Callandrillo"},
+{324,"http://en.wikipedia.org/wiki/Dan_Dickau"},
+{340,"http://en.wikipedia.org/wiki/Dan_Gadzuric"},
+{340,"http://en.wikipedia.org/wiki/Daniel_Defoe"},
+{364,"http://en.wikipedia.org/wiki/Darius_Songaila"},
+{380,"http://en.wikipedia.org/wiki/Darrell_Armstrong"},
+{300,"http://en.wikipedia.org/wiki/Das_Bus"},
+{356,"http://en.wikipedia.org/wiki/David_Andersen"},
+{340,"http://en.wikipedia.org/wiki/DeJuan_Blair"},
+{380,"http://en.wikipedia.org/wiki/DeShawn_Stevenson"},
+{364,"http://en.wikipedia.org/wiki/Derrick_Coleman"},
+{380,"http://en.wikipedia.org/wiki/Deshawn_Stevenson"},
+{444,"http://en.wikipedia.org/wiki/Digital_object_identifier"},
+{348,"http://en.wikipedia.org/wiki/Dirk_Nowitzki"},
+{447,"http://en.wikipedia.org/wiki/Dlh%C3%A9_Str%C3%A1%C5%BEe"},
+{508,"http://en.wikipedia.org/wiki/Do%C4%BEany,_Levo%C4%8Da_District"},
+{356,"http://en.wikipedia.org/wiki/Doma%C5%88ovce"},
+{364,"http://en.wikipedia.org/wiki/Dominique_Jones"},
+{372,"http://en.wikipedia.org/wiki/Donyell_Marshall"},
+{292,"http://en.wikipedia.org/wiki/Dravce"},
+{332,"http://en.wikipedia.org/wiki/Drew_Gooden"},
+{364,"http://en.wikipedia.org/wiki/Duke_University"},
+{332,"http://en.wikipedia.org/wiki/Dwane_Casey"},
+{436,"http://en.wikipedia.org/wiki/Eastern_Conference_(NBA)"},
+{380,"http://en.wikipedia.org/wiki/Economy_of_Turkey"},
+{444,"http://en.wikipedia.org/wiki/Eddie_Jordan_(basketball)"},
+{404,"http://en.wikipedia.org/wiki/Edward_Ambrose_Dyson"},
+{340,"http://en.wikipedia.org/wiki/Edward_Dyson"},
+{316,"http://en.wikipedia.org/wiki/Ekpe_Udoh"},
+{396,"http://en.wikipedia.org/wiki/Elections_in_Turkey"},
+{540,"http://en.wikipedia.org/wiki/Elections_in_Turkey#General_elections"},
+{524,"http://en.wikipedia.org/wiki/Elections_in_Turkey#Local_elections"},
+{316,"http://en.wikipedia.org/wiki/Elevation"},
+{300,"http://en.wikipedia.org/wiki/Elite_8"},
+{340,"http://en.wikipedia.org/wiki/Emeka_Okafor"},
+{300,"http://en.wikipedia.org/wiki/Ensembl"},
+{356,"http://en.wikipedia.org/wiki/Entente_powers"},
+{292,"http://en.wikipedia.org/wiki/Entrez"},
+{292,"http://en.wikipedia.org/wiki/Enzyme"},
+{436,"http://en.wikipedia.org/wiki/Enzyme_Commission_number"},
+{436,"http://en.wikipedia.org/wiki/Erdo%C4%9Fan_III_Cabinet"},
+{340,"http://en.wikipedia.org/wiki/Eric_Bledsoe"},
+{396,"http://en.wikipedia.org/wiki/Ersan_%C4%B0lyasova"},
+{580,"http://en.wikipedia.org/wiki/Establishment_of_Turkish_national_movement"},
+{604,"http://en.wikipedia.org/wiki/European_Union_%E2%80%93_Turkey_Customs_Union"},
+{420,"http://en.wikipedia.org/wiki/Executive_(government)"},
+{500,"http://en.wikipedia.org/wiki/FIBA_Under-21_World_Championship"},
+{372,"http://en.wikipedia.org/wiki/Family_(biology)"},
+{396,"http://en.wikipedia.org/wiki/Federico_Kammerichs"},
+{428,"http://en.wikipedia.org/wiki/Field_goal_(basketball)"},
+{484,"http://en.wikipedia.org/wiki/File:A_coloured_voting_box.svg"},
+{508,"http://en.wikipedia.org/wiki/File:Bryant_Fades_Over_Butler.jpg"},
+{412,"http://en.wikipedia.org/wiki/File:Caron_Butler.JPG"},
+{428,"http://en.wikipedia.org/wiki/File:Creatorballoon.png"},
+{380,"http://en.wikipedia.org/wiki/File:DNA_stub.png"},
+{420,"http://en.wikipedia.org/wiki/File:Disambig_gray.svg"},
+{428,"http://en.wikipedia.org/wiki/File:Flag_of_Turkey.svg"},
+{610,"http://en.wikipedia.org/wiki/File:Massey_Lopes,_Vanity_Fair,_1875-05-15.jpg"},
+{468,"http://en.wikipedia.org/wiki/File:Noctua.pronuba.7199.jpg"},
+{412,"http://en.wikipedia.org/wiki/File:Okres_levoca.png"},
+{514,"http://en.wikipedia.org/wiki/File:PBB_GE_DDT_202929_s_at_tn.png"},
+{412,"http://en.wikipedia.org/wiki/File:PDB_1dpt_EBI.jpg"},
+{356,"http://en.wikipedia.org/wiki/File:P_vip.svg"},
+{476,"http://en.wikipedia.org/wiki/File:Protein_DDT_PDB_1dpt.png"},
+{420,"http://en.wikipedia.org/wiki/File:Quill_and_ink.svg"},
+{460,"http://en.wikipedia.org/wiki/File:Slovakiatynk%C3%A4.svg"},
+{412,"http://en.wikipedia.org/wiki/File:Speaker_Icon.svg"},
+{540,"http://en.wikipedia.org/wiki/File:Translation_to_english_arrow.svg"},
+{436,"http://en.wikipedia.org/wiki/File:Wikisource-logo.svg"},
+{524,"http://en.wikipedia.org/wiki/Financial_Secretary_to_the_Treasury"},
+{524,"http://en.wikipedia.org/wiki/Foreign_Language_Specialized_School"},
+{460,"http://en.wikipedia.org/wiki/Foreign_relations_of_Turkey"},
+{564,"http://en.wikipedia.org/wiki/Francis_Cottington,_1st_Baron_Cottington"},
+{460,"http://en.wikipedia.org/wiki/Frank_Williams_(basketball)"},
+{428,"http://en.wikipedia.org/wiki/Fred_Jones_(basketball)"},
+{324,"http://en.wikipedia.org/wiki/Free_throw"},
+{456,"http://en.wikipedia.org/wiki/French_Constitution_of_1791"},
+{316,"http://en.wikipedia.org/wiki/Gary_Neal"},
+{276,"http://en.wikipedia.org/wiki/Gene"},
+{316,"http://en.wikipedia.org/wiki/GeneCards"},
+{348,"http://en.wikipedia.org/wiki/Gene_Ontology"},
+{284,"http://en.wikipedia.org/wiki/Genus"},
+{468,"http://en.wikipedia.org/wiki/Geographic_coordinate_system"},
+{412,"http://en.wikipedia.org/wiki/Geography_of_Slovakia"},
+{412,"http://en.wikipedia.org/wiki/Giannis_Antetokounmpo"},
+{356,"http://en.wikipedia.org/wiki/Gilbert_Arenas"},
+{396,"http://en.wikipedia.org/wiki/Gran%C4%8D-Petrovce"},
+{508,"http://en.wikipedia.org/wiki/Grand_National_Assembly_of_Turkey"},
+{412,"http://en.wikipedia.org/wiki/Great_Western_Railway"},
+{404,"http://en.wikipedia.org/wiki/H%C3%A0_Nam_Province"},
+{452,"http://en.wikipedia.org/wiki/H%C3%A0_T%C4%A9nh_Province"},
+{460,"http://en.wikipedia.org/wiki/H%C6%B0ng_Y%C3%AAn_Province"},
+{523,"http://en.wikipedia.org/wiki/H%E1%BA%A3i_D%C6%B0%C6%A1ng_Province"},
+{316,"http://en.wikipedia.org/wiki/Hai_Phong"},
+{348,"http://en.wikipedia.org/wiki/Hakim_Warrick"},
+{284,"http://en.wikipedia.org/wiki/Hanoi"},
+{540,"http://en.wikipedia.org/wiki/Hanoi_%E2%80%93_Amsterdam_High_School"},
+{316,"http://en.wikipedia.org/wiki/Harakovce"},
+{364,"http://en.wikipedia.org/wiki/Hasheem_Thabeet"},
+{348,"http://en.wikipedia.org/wiki/Help:Category"},
+{348,"http://en.wikipedia.org/wiki/Help:Contents"},
+{396,"http://en.wikipedia.org/wiki/Help:Disambiguation"},
+{396,"http://en.wikipedia.org/wiki/Help:IPA_for_German"},
+{516,"http://en.wikipedia.org/wiki/Help:Introduction_to_referencing/1"},
+{524,"http://en.wikipedia.org/wiki/Henry_Chaplin,_1st_Viscount_Chaplin"},
+{476,"http://en.wikipedia.org/wiki/Henry_Lopes,_1st_Baron_Ludlow"},
+{500,"http://en.wikipedia.org/wiki/Henry_Lopes,_1st_Baron_Roborough"},
+{604,"http://en.wikipedia.org/wiki/Her_Majesty%27s_Most_Honourable_Privy_Council"},
+{812,"http://en.wikipedia.org/wiki/High_School_for_Gifted_Students,_Hanoi_National_University_of_Education"},
+{724,"http://en.wikipedia.org/wiki/High_School_for_Gifted_Students,_Hanoi_University_of_Science"},
+{452,"http://en.wikipedia.org/wiki/High_School_for_the_Gifted"},
+{412,"http://en.wikipedia.org/wiki/High_Sheriff_of_Devon"},
+{300,"http://en.wikipedia.org/wiki/History"},
+{380,"http://en.wikipedia.org/wiki/History_of_Turkey"},
+{572,"http://en.wikipedia.org/wiki/History_of_Turkish_presidential_elections"},
+{372,"http://en.wikipedia.org/wiki/Ho_Chi_Minh_City"},
+{324,"http://en.wikipedia.org/wiki/HomoloGene"},
+{444,"http://en.wikipedia.org/wiki/Human_Genome_Organisation"},
+{332,"http://en.wikipedia.org/wiki/Ian_Mahinmi"},
+{292,"http://en.wikipedia.org/wiki/Insect"},
+{372,"http://en.wikipedia.org/wiki/Internet_Archive"},
+{316,"http://en.wikipedia.org/wiki/Ish_Smith"},
+{332,"http://en.wikipedia.org/wiki/Islamic_Law"},
+{340,"http://en.wikipedia.org/wiki/J._J._Redick"},
+{308,"http://en.wikipedia.org/wiki/Jablonov"},
+{332,"http://en.wikipedia.org/wiki/Jae_Crowder"},
+{348,"http://en.wikipedia.org/wiki/Jamal_Sampson"},
+{468,"http://en.wikipedia.org/wiki/James_Singleton_(basketball)"},
+{468,"http://en.wikipedia.org/wiki/James_Wilson_(UK_politician)"},
+{340,"http://en.wikipedia.org/wiki/Jared_Dudley"},
+{356,"http://en.wikipedia.org/wiki/Jared_Jeffries"},
+{460,"http://en.wikipedia.org/wiki/Jason_Jennings_(basketball)"},
+{324,"http://en.wikipedia.org/wiki/Jason_Kidd"},
+{332,"http://en.wikipedia.org/wiki/Jason_Terry"},
+{444,"http://en.wikipedia.org/wiki/Jay_Williams_(basketball)"},
+{428,"http://en.wikipedia.org/wiki/Jeff_Green_(basketball)"},
+{407,"http://en.wikipedia.org/wiki/Ji%C5%99%C3%AD_Welsch"},
+{332,"http://en.wikipedia.org/wiki/Jim_Calhoun"},
+{340,"http://en.wikipedia.org/wiki/Jim_Cleamons"},
+{380,"http://en.wikipedia.org/wiki/Johann_David_Wyss"},
+{388,"http://en.wikipedia.org/wiki/Johann_David_Wyss#"},
+{476,"http://en.wikipedia.org/wiki/Johann_David_Wyss#cite_note-1"},
+{468,"http://en.wikipedia.org/wiki/Johann_David_Wyss#cite_ref-1"},
+{492,"http://en.wikipedia.org/wiki/Johann_David_Wyss#mw-navigation"},
+{452,"http://en.wikipedia.org/wiki/Johann_David_Wyss#p-search"},
+{388,"http://en.wikipedia.org/wiki/Johann_Rudolf_Wyss"},
+{436,"http://en.wikipedia.org/wiki/John_Bagley_(basketball)"},
+{420,"http://en.wikipedia.org/wiki/John_Carpenter_Garnier"},
+{324,"http://en.wikipedia.org/wiki/John_Duren"},
+{436,"http://en.wikipedia.org/wiki/John_Henson_(basketball)"},
+{380,"http://en.wikipedia.org/wiki/John_Lewis_Phipps"},
+{492,"http://en.wikipedia.org/wiki/John_Russell,_Viscount_Amberley"},
+{340,"http://en.wikipedia.org/wiki/John_Salmons"},
+{460,"http://en.wikipedia.org/wiki/John_Tremayne_(1825_-_1901)"},
+{540,"http://en.wikipedia.org/wiki/John_Yarde-Buller,_1st_Baron_Churston"},
+{404,"http://en.wikipedia.org/wiki/Jos%C3%A9_Juan_Barea"},
+{332,"http://en.wikipedia.org/wiki/Josh_Howard"},
+{500,"http://en.wikipedia.org/wiki/Juan_Carlos_Navarro_(basketball)"},
+{324,"http://en.wikipedia.org/wiki/Juan_Dixon"},
+{332,"http://en.wikipedia.org/wiki/Kareem_Rush"},
+{543,"http://en.wikipedia.org/wiki/Kemal_K%C4%B1l%C4%B1%C3%A7daro%C4%9Flu"},
+{348,"http://en.wikipedia.org/wiki/Kerry_Kittles"},
+{324,"http://en.wikipedia.org/wiki/Kew_Asylum"},
+{468,"http://en.wikipedia.org/wiki/Kh%C3%A1nh_H%C3%B2a_Province"},
+{364,"http://en.wikipedia.org/wiki/Khris_Middleton"},
+{324,"http://en.wikipedia.org/wiki/Kl%C4%8Dov"},
+{332,"http://en.wikipedia.org/wiki/Kobe_Bryant"},
+{338,"http://en.wikipedia.org/wiki/Korytn%C3%A9"},
+{308,"http://en.wikipedia.org/wiki/Kurimany"},
+{332,"http://en.wikipedia.org/wiki/Kwame_Brown"},
+{530,"http://en.wikipedia.org/wiki/L%C3%BA%C4%8Dka,_Levo%C4%8Da_District"},
+{316,"http://en.wikipedia.org/wiki/Lady_Anne"},
+{324,"http://en.wikipedia.org/wiki/Lady_Anne#"},
+{484,"http://en.wikipedia.org/wiki/Lady_Anne#Fictional_characters"},
+{372,"http://en.wikipedia.org/wiki/Lady_Anne#People"},
+{388,"http://en.wikipedia.org/wiki/Lady_Anne#See_also"},
+{364,"http://en.wikipedia.org/wiki/Lady_Anne#Ships"},
+{428,"http://en.wikipedia.org/wiki/Lady_Anne#mw-navigation"},
+{388,"http://en.wikipedia.org/wiki/Lady_Anne#p-search"},
+{412,"http://en.wikipedia.org/wiki/Lady_Anne-Marie_Byrne"},
+{380,"http://en.wikipedia.org/wiki/Lady_Anne_Barnard"},
+{364,"http://en.wikipedia.org/wiki/Lady_Anne_Berry"},
+{364,"http://en.wikipedia.org/wiki/Lady_Anne_Blunt"},
+{468,"http://en.wikipedia.org/wiki/Lady_Anne_Cavendish-Bentinck"},
+{396,"http://en.wikipedia.org/wiki/Lady_Anne_Churchill"},
+{388,"http://en.wikipedia.org/wiki/Lady_Anne_Clifford"},
+{500,"http://en.wikipedia.org/wiki/Lady_Anne_Farquharson-MacKintosh"},
+{356,"http://en.wikipedia.org/wiki/Lady_Anne_Rhys"},
+{396,"http://en.wikipedia.org/wiki/Lam_Son_High_School"},
+{324,"http://en.wikipedia.org/wiki/Lamar_Odom"},
+{340,"http://en.wikipedia.org/wiki/Laron_Profit"},
+{324,"http://en.wikipedia.org/wiki/Larry_Drew"},
+{452,"http://en.wikipedia.org/wiki/Larry_Sanders_(basketball)"},
+{492,"http://en.wikipedia.org/wiki/Lawrence_Palk,_1st_Baron_Haldon"},
+{340,"http://en.wikipedia.org/wiki/LeBron_James"},
+{444,"http://en.wikipedia.org/wiki/Le_Hong_Phong_High_School"},
+{556,"http://en.wikipedia.org/wiki/Leader_of_the_Main_Opposition_of_Turkey"},
+{548,"http://en.wikipedia.org/wiki/Legal_System_in_the_Republic_of_Turkey"},
+{756,"http://en.wikipedia.org/wiki/Legal_System_in_the_Republic_of_Turkey#Turkish_Court_of_Accounts"},
+{548,"http://en.wikipedia.org/wiki/Legal_system_of_the_Republic_of_Turkey"},
+{332,"http://en.wikipedia.org/wiki/Legislative"},
+{332,"http://en.wikipedia.org/wiki/Lepidoptera"},
+{332,"http://en.wikipedia.org/wiki/Levo%C4%8Da"},
+{404,"http://en.wikipedia.org/wiki/Levo%C4%8Da_District"},
+{308,"http://en.wikipedia.org/wiki/LibriVox"},
+{412,"http://en.wikipedia.org/wiki/List_of_NBA_champions"},
+{468,"http://en.wikipedia.org/wiki/List_of_Presidents_of_Turkey"},
+{692,"http://en.wikipedia.org/wiki/List_of_Presidents_of_the_Constitutional_Court_of_Turkey"},
+{508,"http://en.wikipedia.org/wiki/List_of_Prime_Ministers_of_Turkey"},
+{596,"http://en.wikipedia.org/wiki/List_of_Speakers_of_the_Parliament_of_Turkey"},
+{444,"http://en.wikipedia.org/wiki/List_of_Turkish_diplomats"},
+{540,"http://en.wikipedia.org/wiki/List_of_diplomatic_missions_of_Turkey"},
+{452,"http://en.wikipedia.org/wiki/List_of_extant_baronetcies"},
+{524,"http://en.wikipedia.org/wiki/List_of_political_parties_in_Turkey"},
+{372,"http://en.wikipedia.org/wiki/Long_An_Province"},
+{340,"http://en.wikipedia.org/wiki/Lonny_Baxter"},
+{516,"http://en.wikipedia.org/wiki/Lord_Commissioner_of_the_Admiralty"},
+{404,"http://en.wikipedia.org/wiki/Los_Angeles_Clippers"},
+{388,"http://en.wikipedia.org/wiki/Los_Angeles_Lakers"},
+{348,"http://en.wikipedia.org/wiki/Lost_in_Space"},
+{324,"http://en.wikipedia.org/wiki/Luis_Scola"},
+{356,"http://en.wikipedia.org/wiki/Luke_Harangody"},
+{340,"http://en.wikipedia.org/wiki/Luke_Ridnour"},
+{548,"http://en.wikipedia.org/wiki/Macrophage_migration_inhibitory_factor"},
+{604,"http://en.wikipedia.org/wiki/Macrophage_migration_inhibitory_factor_domain"},
+{316,"http://en.wikipedia.org/wiki/Main_Page"},
+{428,"http://en.wikipedia.org/wiki/Maine_Central_Institute"},
+{356,"http://en.wikipedia.org/wiki/Marcus_Haislip"},
+{348,"http://en.wikipedia.org/wiki/Marcus_Taylor"},
+{332,"http://en.wikipedia.org/wiki/Mario_Kasun"},
+{388,"http://en.wikipedia.org/wiki/Maryland_Terrapins"},
+{332,"http://en.wikipedia.org/wiki/Matt_Barnes"},
+{372,"http://en.wikipedia.org/wiki/Melbourne_Herald"},
+{364,"http://en.wikipedia.org/wiki/Melbourne_Punch"},
+{324,"http://en.wikipedia.org/wiki/Melvin_Ely"},
+{468,"http://en.wikipedia.org/wiki/Mendelian_Inheritance_in_Man"},
+{324,"http://en.wikipedia.org/wiki/Miami_Heat"},
+{356,"http://en.wikipedia.org/wiki/Micronoctuidae"},
+{388,"http://en.wikipedia.org/wiki/Mike_Dunleavy,_Jr."},
+{426,"http://en.wikipedia.org/wiki/Milo%C5%A1_Vujani%C4%87"},
+{364,"http://en.wikipedia.org/wiki/Milwaukee_Bucks"},
+{404,"http://en.wikipedia.org/wiki/Ministries_of_Turkey"},
+{596,"http://en.wikipedia.org/wiki/Ministry_of_Education_and_Training_(Vietnam)"},
+{532,"http://en.wikipedia.org/wiki/Ministry_of_Foreign_Affairs_(Turkey)"},
+{388,"http://en.wikipedia.org/wiki/Miroslav_Raduljica"},
+{412,"http://en.wikipedia.org/wiki/Mladen_%C5%A0ekularac"},
+{300,"http://en.wikipedia.org/wiki/Monarch"},
+{276,"http://en.wikipedia.org/wiki/Moth"},
+{340,"http://en.wikipedia.org/wiki/Mountain_Dew"},
+{436,"http://en.wikipedia.org/wiki/Mouse_Genome_Informatics"},
+{340,"http://en.wikipedia.org/wiki/Municipality"},
+{452,"http://en.wikipedia.org/wiki/Mustafa_Kemal_Atat%C3%BCrk"},
+{268,"http://en.wikipedia.org/wiki/NBA"},
+{396,"http://en.wikipedia.org/wiki/NBA_All-Rookie_Team"},
+{380,"http://en.wikipedia.org/wiki/NBA_All-Star_Game"},
+{292,"http://en.wikipedia.org/wiki/Nahiye"},
+{472,"http://en.wikipedia.org/wiki/Nam_%C4%90%E1%BB%8Bnh_Province"},
+{340,"http://en.wikipedia.org/wiki/Nate_Wolters"},
+{540,"http://en.wikipedia.org/wiki/National_Basketball_Association_draft"},
+{516,"http://en.wikipedia.org/wiki/National_Security_Council_(Turkey)"},
+{404,"http://en.wikipedia.org/wiki/National_sovereignty"},
+{348,"http://en.wikipedia.org/wiki/Neme%C5%A1any"},
+{314,"http://en.wikipedia.org/wiki/Nen%C3%AA"},
+{378,"http://en.wikipedia.org/wiki/Nenad_Krsti%C4%87"},
+{420,"http://en.wikipedia.org/wiki/New_Orleans,_Louisiana"},
+{364,"http://en.wikipedia.org/wiki/New_York_Knicks"},
+{436,"http://en.wikipedia.org/wiki/Ngh%E1%BB%87_An_Province"},
+{484,"http://en.wikipedia.org/wiki/Nguyen_Thuong_Hien_High_School"},
+{460,"http://en.wikipedia.org/wiki/Ni%C5%BEn%C3%A9_Repa%C5%A1e"},
+{348,"http://en.wikipedia.org/wiki/Nick_Van_Exel"},
+{404,"http://en.wikipedia.org/wiki/Nikoloz_Tskitishvili"},
+{324,"http://en.wikipedia.org/wiki/Noctuoidea"},
+{378,"http://en.wikipedia.org/wiki/O%C4%BE%C5%A1avica"},
+{324,"http://en.wikipedia.org/wiki/O._J._Mayo"},
+{340,"http://en.wikipedia.org/wiki/Open_Library"},
+{316,"http://en.wikipedia.org/wiki/Ordzovany"},
+{412,"http://en.wikipedia.org/wiki/Oriel_College,_Oxford"},
+{332,"http://en.wikipedia.org/wiki/Otto_Porter"},
+{356,"http://en.wikipedia.org/wiki/Ottoman_Empire"},
+{364,"http://en.wikipedia.org/wiki/Ottoman_dynasty"},
+{372,"http://en.wikipedia.org/wiki/Ottoman_language"},
+{620,"http://en.wikipedia.org/wiki/Outline_of_political_science#Politics_by_region"},
+{500,"http://en.wikipedia.org/wiki/Parliament_of_the_United_Kingdom"},
+{332,"http://en.wikipedia.org/wiki/Pat_Garrity"},
+{348,"http://en.wikipedia.org/wiki/Patrick_Ewing"},
+{340,"http://en.wikipedia.org/wiki/Pav%C4%BEany"},
+{402,"http://en.wikipedia.org/wiki/Peja_Stojakovi%C4%87"},
+{388,"http://en.wikipedia.org/wiki/Perils_of_the_Wild"},
+{332,"http://en.wikipedia.org/wiki/Peter_Fehse"},
+{476,"http://en.wikipedia.org/wiki/Ph%C3%BA_Th%E1%BB%8D_Province"},
+{452,"http://en.wikipedia.org/wiki/Ph%C3%BA_Y%C3%AAn_Province"},
+{340,"http://en.wikipedia.org/wiki/Phoenix_Suns"},
+{380,"http://en.wikipedia.org/wiki/Pittsfield,_Maine"},
+{356,"http://en.wikipedia.org/wiki/Po%C4%BEanovce"},
+{388,"http://en.wikipedia.org/wiki/Politics_of_Turkey"},
+{524,"http://en.wikipedia.org/wiki/Politics_of_Turkey#Executive_branch"},
+{540,"http://en.wikipedia.org/wiki/Politics_of_Turkey#Legislative_branch"},
+{372,"http://en.wikipedia.org/wiki/Pongr%C3%A1covce"},
+{324,"http://en.wikipedia.org/wiki/Population"},
+{372,"http://en.wikipedia.org/wiki/Portal:Biography"},
+{364,"http://en.wikipedia.org/wiki/Portal:Contents"},
+{412,"http://en.wikipedia.org/wiki/Portal:Current_events"},
+{428,"http://en.wikipedia.org/wiki/Portal:Featured_content"},
+{364,"http://en.wikipedia.org/wiki/Portal:Politics"},
+{348,"http://en.wikipedia.org/wiki/Portal:Turkey"},
+{388,"http://en.wikipedia.org/wiki/Pre%C5%A1ov_Region"},
+{396,"http://en.wikipedia.org/wiki/President_of_Turkey"},
+{436,"http://en.wikipedia.org/wiki/Prime_Minister_of_Turkey"},
+{380,"http://en.wikipedia.org/wiki/Project_Gutenberg"},
+{380,"http://en.wikipedia.org/wiki/Protein_Data_Bank"},
+{292,"http://en.wikipedia.org/wiki/PubMed"},
+{356,"http://en.wikipedia.org/wiki/PubMed_Central"},
+{380,"http://en.wikipedia.org/wiki/PubMed_Identifier"},
+{372,"http://en.wikipedia.org/wiki/Public_relations"},
+{284,"http://en.wikipedia.org/wiki/Qadaa"},
+{460,"http://en.wikipedia.org/wiki/Qu%E1%BA%A3ng_Ninh_Province"},
+{340,"http://en.wikipedia.org/wiki/Quinton_Ross"},
+{636,"http://en.wikipedia.org/wiki/Quoc_Hoc_%E2%80%93_Hue_High_School_for_the_Gifted"},
+{340,"http://en.wikipedia.org/wiki/Qyntel_Woods"},
+{380,"http://en.wikipedia.org/wiki/Racine,_Wisconsin"},
+{428,"http://en.wikipedia.org/wiki/Racine_Park_High_School"},
+{324,"http://en.wikipedia.org/wiki/Randy_Foye"},
+{348,"http://en.wikipedia.org/wiki/Randy_Holcomb"},
+{348,"http://en.wikipedia.org/wiki/Rasual_Butler"},
+{316,"http://en.wikipedia.org/wiki/Ray_Allen"},
+{404,"http://en.wikipedia.org/wiki/Rebound_(basketball)"},
+{444,"http://en.wikipedia.org/wiki/Recep_Tayyip_Erdo%C4%9Fan"},
+{556,"http://en.wikipedia.org/wiki/Reggie_Williams_(basketball,_born_1964)"},
+{308,"http://en.wikipedia.org/wiki/Republic"},
+{388,"http://en.wikipedia.org/wiki/Republic_of_Turkey"},
+{476,"http://en.wikipedia.org/wiki/Richard_Hamilton_(basketball)"},
+{348,"http://en.wikipedia.org/wiki/Rick_Carlisle"},
+{372,"http://en.wikipedia.org/wiki/Robert_Archibald"},
+{604,"http://en.wikipedia.org/wiki/Robert_Haldane-Duncan,_3rd_Earl_of_Camperdown"},
+{364,"http://en.wikipedia.org/wiki/Robinson_Crusoe"},
+{340,"http://en.wikipedia.org/wiki/Rod_Grizzard"},
+{380,"http://en.wikipedia.org/wiki/Rodrigue_Beaubois"},
+{372,"http://en.wikipedia.org/wiki/Roger_Mason,_Jr."},
+{348,"http://en.wikipedia.org/wiki/Ronald_Murray"},
+{348,"http://en.wikipedia.org/wiki/Ryan_Humphrey"},
+{364,"http://en.wikipedia.org/wiki/Sam_Clancy,_Jr."},
+{436,"http://en.wikipedia.org/wiki/Samuel_Trehawke_Kekewich"},
+{380,"http://en.wikipedia.org/wiki/San_Antonio_Spurs"},
+{460,"http://en.wikipedia.org/wiki/Scott_Williams_(basketball)"},
+{404,"http://en.wikipedia.org/wiki/Secularism_in_Turkey"},
+{348,"http://en.wikipedia.org/wiki/Sephardi_Jews"},
+{388,"http://en.wikipedia.org/wiki/Shaquille_O%27Neal"},
+{340,"http://en.wikipedia.org/wiki/Shawn_Marion"},
+{548,"http://en.wikipedia.org/wiki/Sir_Manasseh_Masseh_Lopes,_1st_Baronet"},
+{476,"http://en.wikipedia.org/wiki/Sir_Massey_Lopes,_3rd_Baronet"},
+{484,"http://en.wikipedia.org/wiki/Sir_Massey_Lopes,_3rd_Baronet#"},
+{572,"http://en.wikipedia.org/wiki/Sir_Massey_Lopes,_3rd_Baronet#cite_note-1"},
+{564,"http://en.wikipedia.org/wiki/Sir_Massey_Lopes,_3rd_Baronet#cite_ref-1"},
+{588,"http://en.wikipedia.org/wiki/Sir_Massey_Lopes,_3rd_Baronet#mw-navigation"},
+{548,"http://en.wikipedia.org/wiki/Sir_Massey_Lopes,_3rd_Baronet#p-search"},
+{468,"http://en.wikipedia.org/wiki/Sir_Ralph_Lopes,_2nd_Baronet"},
+{308,"http://en.wikipedia.org/wiki/Slovakia"},
+{348,"http://en.wikipedia.org/wiki/Small_forward"},
+{564,"http://en.wikipedia.org/wiki/South_Devon_(UK_Parliament_constituency)"},
+{444,"http://en.wikipedia.org/wiki/South_Melbourne,_Victoria"},
+{332,"http://en.wikipedia.org/wiki/Sovereignty"},
+{412,"http://en.wikipedia.org/wiki/Space_Family_Robinson"},
+{463,"http://en.wikipedia.org/wiki/Special:BookSources/0091354609"},
+{356,"http://en.wikipedia.org/wiki/Special:Random"},
+{412,"http://en.wikipedia.org/wiki/Special:RecentChanges"},
+{572,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/Ambrose_Dyson"},
+{564,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/Caron_Butler"},
+{548,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/DDT_(gene)"},
+{604,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/Johann_David_Wyss"},
+{540,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/Lady_Anne"},
+{700,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/Sir_Massey_Lopes,_3rd_Baronet"},
+{516,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/Tumula"},
+{688,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/Turkish_Constitution_of_1921"},
+{764,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/Vietnam_University_Admission_Rankings"},
+{652,"http://en.wikipedia.org/wiki/Special:RecentChangesLinked/Vy%C5%A1n%C3%BD_Slavkov"},
+{404,"http://en.wikipedia.org/wiki/Special:SpecialPages"},
+{524,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/Ambrose_Dyson"},
+{516,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/Caron_Butler"},
+{500,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/DDT_(gene)"},
+{556,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/Johann_David_Wyss"},
+{492,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/Lady_Anne"},
+{652,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/Sir_Massey_Lopes,_3rd_Baronet"},
+{468,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/Tumula"},
+{640,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/Turkish_Constitution_of_1921"},
+{716,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/Vietnam_University_Admission_Rankings"},
+{604,"http://en.wikipedia.org/wiki/Special:WhatLinksHere/Vy%C5%A1n%C3%BD_Slavkov"},
+{460,"http://en.wikipedia.org/wiki/Spi%C5%A1sk%C3%A9_Podhradie"},
+{484,"http://en.wikipedia.org/wiki/Spi%C5%A1sk%C3%BD_%C5%A0tvrtok"},
+{428,"http://en.wikipedia.org/wiki/Spi%C5%A1sk%C3%BD_Hrhov"},
+{388,"http://en.wikipedia.org/wiki/Steal_(basketball)"},
+{332,"http://en.wikipedia.org/wiki/Steve_Logan"},
+{404,"http://en.wikipedia.org/wiki/Stranded_(2002_film)"},
+{492,"http://en.wikipedia.org/wiki/Studenec_(Levo%C4%8Da_District)"},
+{292,"http://en.wikipedia.org/wiki/Sultan"},
+{524,"http://en.wikipedia.org/wiki/Supreme_Electoral_Council_of_Turkey"},
+{444,"http://en.wikipedia.org/wiki/Swiss_Family_Guy_Robinson"},
+{508,"http://en.wikipedia.org/wiki/Swiss_Family_Robinson_(1940_film)"},
+{508,"http://en.wikipedia.org/wiki/Swiss_Family_Robinson_(1960_film)"},
+{548,"http://en.wikipedia.org/wiki/Swiss_Family_Robinson_(1974_TV_series)"},
+{332,"http://en.wikipedia.org/wiki/Switzerland"},
+{292,"http://en.wikipedia.org/wiki/Sydney"},
+{324,"http://en.wikipedia.org/wiki/Tactusinae"},
+{388,"http://en.wikipedia.org/wiki/Talk:Ambrose_Dyson"},
+{380,"http://en.wikipedia.org/wiki/Talk:Caron_Butler"},
+{364,"http://en.wikipedia.org/wiki/Talk:DDT_(gene)"},
+{420,"http://en.wikipedia.org/wiki/Talk:Johann_David_Wyss"},
+{516,"http://en.wikipedia.org/wiki/Talk:Sir_Massey_Lopes,_3rd_Baronet"},
+{332,"http://en.wikipedia.org/wiki/Talk:Tumula"},
+{504,"http://en.wikipedia.org/wiki/Talk:Turkish_Constitution_of_1921"},
+{580,"http://en.wikipedia.org/wiki/Talk:Vietnam_University_Admission_Rankings"},
+{468,"http://en.wikipedia.org/wiki/Talk:Vy%C5%A1n%C3%BD_Slavkov"},
+{324,"http://en.wikipedia.org/wiki/Tamar_Slay"},
+{364,"http://en.wikipedia.org/wiki/Tayshaun_Prince"},
+{428,"http://en.wikipedia.org/wiki/Template:2002_NBA_Draft"},
+{828,"http://en.wikipedia.org/wiki/Template:Big_East_Conference_Men%27s_Basketball_Player_of_the_Year_navbox"},
+{436,"http://en.wikipedia.org/wiki/Template:Cartoonist-stub"},
+{436,"http://en.wikipedia.org/wiki/Template:Citation_needed"},
+{492,"http://en.wikipedia.org/wiki/Template:Constitution_of_Turkey"},
+{672,"http://en.wikipedia.org/wiki/Template:Dallas_Mavericks_2010%E2%80%9311_NBA_champions"},
+{412,"http://en.wikipedia.org/wiki/Template:Gene-22-stub"},
+{476,"http://en.wikipedia.org/wiki/Template:Levo%C4%8Da_District"},
+{556,"http://en.wikipedia.org/wiki/Template:Milwaukee_Bucks_current_roster"},
+{436,"http://en.wikipedia.org/wiki/Template:Noctuoidea-stub"},
+{371,"http://en.wikipedia.org/wiki/Template:PBB/1652"},
+{404,"http://en.wikipedia.org/wiki/Template:PDB_Gallery"},
+{460,"http://en.wikipedia.org/wiki/Template:Politics_of_Turkey"},
+{476,"http://en.wikipedia.org/wiki/Template:Pre%C5%A1ov-geo-stub"},
+{500,"http://en.wikipedia.org/wiki/Template:Switzerland-writer-stub"},
+{516,"http://en.wikipedia.org/wiki/Template:The_Swiss_Family_Robinson"},
+{396,"http://en.wikipedia.org/wiki/Template:Translated"},
+{468,"http://en.wikipedia.org/wiki/Template_talk:2002_NBA_Draft"},
+{868,"http://en.wikipedia.org/wiki/Template_talk:Big_East_Conference_Men%27s_Basketball_Player_of_the_Year_navbox"},
+{476,"http://en.wikipedia.org/wiki/Template_talk:Cartoonist-stub"},
+{532,"http://en.wikipedia.org/wiki/Template_talk:Constitution_of_Turkey"},
+{712,"http://en.wikipedia.org/wiki/Template_talk:Dallas_Mavericks_2010%E2%80%9311_NBA_champions"},
+{452,"http://en.wikipedia.org/wiki/Template_talk:Gene-22-stub"},
+{516,"http://en.wikipedia.org/wiki/Template_talk:Levo%C4%8Da_District"},
+{596,"http://en.wikipedia.org/wiki/Template_talk:Milwaukee_Bucks_current_roster"},
+{476,"http://en.wikipedia.org/wiki/Template_talk:Noctuoidea-stub"},
+{444,"http://en.wikipedia.org/wiki/Template_talk:PDB_Gallery"},
+{500,"http://en.wikipedia.org/wiki/Template_talk:Politics_of_Turkey"},
+{516,"http://en.wikipedia.org/wiki/Template_talk:Pre%C5%A1ov-geo-stub"},
+{540,"http://en.wikipedia.org/wiki/Template_talk:Switzerland-writer-stub"},
+{340,"http://en.wikipedia.org/wiki/Terry_Dehere"},
+{340,"http://en.wikipedia.org/wiki/Terry_Stotts"},
+{468,"http://en.wikipedia.org/wiki/Th%C3%A1i_B%C3%ACnh_Province"},
+{660,"http://en.wikipedia.org/wiki/Th%E1%BB%ABa_Thi%C3%AAn%E2%80%93Hu%E1%BA%BF_Province"},
+{356,"http://en.wikipedia.org/wiki/Thanh_H%C3%B3a"},
+{428,"http://en.wikipedia.org/wiki/Thanh_H%C3%B3a_Province"},
+{340,"http://en.wikipedia.org/wiki/The_Bulletin"},
+{444,"http://en.wikipedia.org/wiki/The_Castaways_of_the_Flag"},
+{388,"http://en.wikipedia.org/wiki/The_London_Gazette"},
+{444,"http://en.wikipedia.org/wiki/The_Swiss_Family_Robinson"},
+{700,"http://en.wikipedia.org/wiki/The_Swiss_Family_Robinson:_Flone_of_the_Mysterious_Island"},
+{580,"http://en.wikipedia.org/wiki/The_Swiss_Family_Robinson_(1975_TV_series)"},
+{500,"http://en.wikipedia.org/wiki/Thomas_Brassey,_1st_Earl_Brassey"},
+{420,"http://en.wikipedia.org/wiki/Three-point_field_goal"},
+{340,"http://en.wikipedia.org/wiki/Tim_Grgurich"},
+{420,"http://en.wikipedia.org/wiki/Tim_James_(basketball)"},
+{332,"http://en.wikipedia.org/wiki/Tito_Maddox"},
+{324,"http://en.wikipedia.org/wiki/Tom_Durkin"},
+{300,"http://en.wikipedia.org/wiki/Torysky"},
+{452,"http://en.wikipedia.org/wiki/Tran_Dai_Nghia_High_School"},
+{388,"http://en.wikipedia.org/wiki/Treaty_of_Lausanne"},
+{412,"http://en.wikipedia.org/wiki/Treaty_of_S%C3%A8vres"},
+{316,"http://en.wikipedia.org/wiki/Troy_Bell"},
+{332,"http://en.wikipedia.org/wiki/Troy_Murphy"},
+{292,"http://en.wikipedia.org/wiki/Tumula"},
+{300,"http://en.wikipedia.org/wiki/Tumula#"},
+{404,"http://en.wikipedia.org/wiki/Tumula#mw-navigation"},
+{364,"http://en.wikipedia.org/wiki/Tumula#p-search"},
+{388,"http://en.wikipedia.org/wiki/Tumula_flavicollis"},
+{292,"http://en.wikipedia.org/wiki/Turkey"},
+{660,"http://en.wikipedia.org/wiki/Turkey%27s_membership_of_international_organizations"},
+{404,"http://en.wikipedia.org/wiki/Turkish_Armed_Forces"},
+{464,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921"},
+{476,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#"},
+{556,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#Background"},
+{588,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#External_links"},
+{540,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#Overview"},
+{556,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#References"},
+{644,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#Text_.28as_enacted.29"},
+{540,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#Timeline"},
+{564,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#cite_note-1"},
+{556,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#cite_ref-1"},
+{580,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#mw-navigation"},
+{540,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1921#p-search"},
+{464,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1924"},
+{464,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1961"},
+{464,"http://en.wikipedia.org/wiki/Turkish_Constitution_of_1982"},
+{436,"http://en.wikipedia.org/wiki/Turkish_Council_of_State"},
+{436,"http://en.wikipedia.org/wiki/Turkish_Independence_War"},
+{460,"http://en.wikipedia.org/wiki/Turkish_War_of_Independence"},
+{480,"http://en.wikipedia.org/wiki/Turkish_general_election,_2011"},
+{372,"http://en.wikipedia.org/wiki/Turkish_language"},
+{472,"http://en.wikipedia.org/wiki/Turkish_local_elections,_2009"},
+{520,"http://en.wikipedia.org/wiki/Turkish_presidential_election,_2007"},
+{356,"http://en.wikipedia.org/wiki/Tyson_Chandler"},
+{420,"http://en.wikipedia.org/wiki/USS_Lady_Anne_(SP-154)"},
+{324,"http://en.wikipedia.org/wiki/Ulo%C5%BEa"},
+{300,"http://en.wikipedia.org/wiki/UniProt"},
+{348,"http://en.wikipedia.org/wiki/United_States"},
+{548,"http://en.wikipedia.org/wiki/United_States_national_basketball_team"},
+{444,"http://en.wikipedia.org/wiki/University_of_Connecticut"},
+{468,"http://en.wikipedia.org/wiki/V%C4%A9nh_Ph%C3%BAc_Province"},
+{567,"http://en.wikipedia.org/wiki/Vanity_Fair_(British_magazine_1868-1914)"},
+{396,"http://en.wikipedia.org/wiki/Viacheslav_Kravtsov"},
+{540,"http://en.wikipedia.org/wiki/Vietnam_University_Admission_Rankings"},
+{548,"http://en.wikipedia.org/wiki/Vietnam_University_Admission_Rankings#"},
+{636,"http://en.wikipedia.org/wiki/Vietnam_University_Admission_Rankings#cite_note-1"},
+{628,"http://en.wikipedia.org/wiki/Vietnam_University_Admission_Rankings#cite_ref-1"},
+{652,"http://en.wikipedia.org/wiki/Vietnam_University_Admission_Rankings#mw-navigation"},
+{612,"http://en.wikipedia.org/wiki/Vietnam_University_Admission_Rankings#p-search"},
+{340,"http://en.wikipedia.org/wiki/Vil%C3%A2yet"},
+{300,"http://en.wikipedia.org/wiki/Village"},
+{380,"http://en.wikipedia.org/wiki/Vincent_Yarbrough"},
+{532,"http://en.wikipedia.org/wiki/Virtual_International_Authority_File"},
+{460,"http://en.wikipedia.org/wiki/Vy%C5%A1n%C3%A9_Repa%C5%A1e"},
+{428,"http://en.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{436,"http://en.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov#"},
+{540,"http://en.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov#mw-navigation"},
+{500,"http://en.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov#p-search"},
+{444,"http://en.wikipedia.org/wiki/Walter_Berry_(basketball)"},
+{372,"http://en.wikipedia.org/wiki/Washington,_D.C."},
+{460,"http://en.wikipedia.org/wiki/Washington_Park_High_School"},
+{388,"http://en.wikipedia.org/wiki/Washington_Wizards"},
+{460,"http://en.wikipedia.org/wiki/Wesley_Johnson_(basketball)"},
+{540,"http://en.wikipedia.org/wiki/Westbury_(UK_Parliament_constituency)"},
+{364,"http://en.wikipedia.org/wiki/Wikipedia:About"},
+{444,"http://en.wikipedia.org/wiki/Wikipedia:Citation_needed"},
+{436,"http://en.wikipedia.org/wiki/Wikipedia:Citing_sources"},
+{452,"http://en.wikipedia.org/wiki/Wikipedia:Community_portal"},
+{404,"http://en.wikipedia.org/wiki/Wikipedia:Contact_us"},
+{516,"http://en.wikipedia.org/wiki/Wikipedia:Copying_within_Wikipedia"},
+{468,"http://en.wikipedia.org/wiki/Wikipedia:File_Upload_Wizard"},
+{468,"http://en.wikipedia.org/wiki/Wikipedia:General_disclaimer"},
+{548,"http://en.wikipedia.org/wiki/Wikipedia:Identifying_reliable_sources"},
+{362,"http://en.wikipedia.org/wiki/Wikipedia:NOTRS"},
+{404,"http://en.wikipedia.org/wiki/Wikipedia:Persondata"},
+{356,"http://en.wikipedia.org/wiki/Wikipedia:Stub"},
+{868,"http://en.wikipedia.org/wiki/Wikipedia:Text_of_Creative_Commons_Attribution-ShareAlike_3.0_Unported_License"},
+{412,"http://en.wikipedia.org/wiki/Wikipedia:Translation"},
+{372,"http://en.wikipedia.org/wiki/Wikipedia:V#SELF"},
+{580,"http://en.wikipedia.org/wiki/Wikipedia:Verifiability#Burden_of_evidence"},
+{324,"http://en.wikipedia.org/wiki/Will_Dyson"},
+{388,"http://en.wikipedia.org/wiki/Winchester_College"},
+{316,"http://en.wikipedia.org/wiki/Wisconsin"},
+{332,"http://en.wikipedia.org/wiki/World_War_I"},
+{292,"http://en.wikipedia.org/wiki/Yahoo!"},
+{308,"http://en.wikipedia.org/wiki/Yao_Ming"},
+{348,"http://en.wikipedia.org/wiki/Zaza_Pachulia"},
+{556,"http://en.wikisource.org/wiki/Constitution_of_the_Republic_of_Turkey"},
+{428,"http://eo.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{340,"http://es.wikipedia.org/wiki/Caron_Butler"},
+{380,"http://es.wikipedia.org/wiki/Johann_David_Wyss"},
+{228,"http://everything.yahoo.com"},
+{236,"http://everything.yahoo.com/"},
+{420,"http://feedback.yahoo.com/forums/206380-us-homepage"},
+{204,"http://finance.yahoo.com"},
+{212,"http://finance.yahoo.com/"},
+{602,"http://finance.yahoo.com/news/brazil-looks-break-us-centric-040621384.html"},
+{554,"http://finance.yahoo.com/news/did-ted-cruz-just-force-211204954.html"},
+{642,"http://finance.yahoo.com/news/theyve-turned-over-costa-concordia-102731647.html"},
+{284,"http://finance.yahoo.com/q?s=^IXIC"},
+{578,"http://finance.yahoo.com/video/winning-lottery-beat-odds-193258229.html"},
+{148,"http://flickr.com"},
+{404,"http://flss.edu.vn/Home.asp?param=news&NewsID=147"},
+{980,"http://football.fantasysports.yahoo.com/?ovchn=YAH&ovcpn=Front+Page&ovcrn=Front+page+P+Link+Nav+button&ovrfd=YAH&ovtac=AD"},
+{340,"http://fr.wikipedia.org/wiki/Caron_Butler"},
+{380,"http://fr.wikipedia.org/wiki/Johann_David_Wyss"},
+{428,"http://fr.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{196,"http://games.yahoo.com/"},
+{697,"http://genome.ucsc.edu/cgi-bin/hgTracks?org=Human&db=hg19&position=chr22:24313554-24322660"},
+{689,"http://genome.ucsc.edu/cgi-bin/hgTracks?org=Mouse&db=mm9&position=chr10:75771230-75773414"},
+{340,"http://gl.wikipedia.org/wiki/Caron_Butler"},
+{196,"http://green.yahoo.com/"},
+{204,"http://groups.yahoo.com/"},
+{687,"http://hangtime.blogs.nba.com/2011/01/04/caron-butler-out-for-season/?ls=iref:nbahpt2"},
+{476,"http://hansard.millbanksystems.com/people/sir-massey-lopes"},
+{618,"http://he.wikipedia.org/wiki/%D7%A7%D7%90%D7%A8%D7%95%D7%9F_%D7%91%D7%90%D7%98%D7%9C%D7%A8"},
+{196,"http://health.yahoo.net"},
+{636,"http://health.yahoo.net/articles/weight-loss/why-obese-people-cant-lose-weight"},
+{653,"http://help.yahoo.com/kb/index?page=content&y=PROD_FRONT&locale=en_US&id=SLN14553"},
+{372,"http://help.yahoo.com/l/us/yahoo/helpcentral/"},
+{268,"http://homes.yahoo.com/own-rent/"},
+{340,"http://hr.wikipedia.org/wiki/Caron_Butler"},
+{412,"http://hu.wikipedia.org/wiki/Fels%C5%91szal%C3%B3k"},
+{180,"http://info.yahoo.com"},
+{188,"http://info.yahoo.com/"},
+{396,"http://info.yahoo.com/legal/us/yahoo/utos/terms/"},
+{396,"http://info.yahoo.com/privacy/us/yahoo/homepage/"},
+{452,"http://info.yahoo.com/privacy/us/yahoo/relevantads.html"},
+{340,"http://it.wikipedia.org/wiki/Caron_Butler"},
+{428,"http://it.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{651,"http://ja.wikipedia.org/wiki/%E3%82%AB%E3%83%AD%E3%83%B3%E3%83%BB%E3%83%90%E3%83%88%E3%83%A9%E3%83%BC"},
+{898,"http://ja.wikipedia.org/wiki/%E3%83%A8%E3%83%8F%E3%83%B3%E3%83%BB%E3%83%80%E3%83%93%E3%83%83%E3%83%88%E3%83%BB%E3%82%A6%E3%82%A3%E3%83%BC%E3%82%B9"},
+{564,"http://jobsearch.monster.com/search/?cy=us&WT.mc_n=yta_trough_jsrtest"},
+{596,"http://librivox.org/newcatalog/search.php?title=&author=Johann+David+Wyss"},
+{356,"http://lv.wikipedia.org/wiki/Kerons_Batlers"},
+{252,"http://mail.yahoo.com?.intl=us"},
+{188,"http://maps.yahoo.com/"},
+{220,"http://messenger.yahoo.com"},
+{196,"http://movies.yahoo.com"},
+{522,"http://movies.yahoo.com/video/short-game-crushing-224038083.html"},
+{428,"http://ms.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{188,"http://music.yahoo.com"},
+{276,"http://my.yahoo.com/?fr=yfp-t-403"},
+{634,"http://myespn.go.com/blogs/truehoop/0-24-118/Caron-Butler-in-the-Basement.html"},
+{188,"http://news.yahoo.com/"},
+{618,"http://news.yahoo.com/amazing-roll-cloud-tumbles-over-dc-area-161409111.html"},
+{994,"http://news.yahoo.com/blogs/trending-now/family-sells-home--goes-on-epic-yearlong-trip-to-all-50-states-185712913.html?vp=1"},
+{388,"http://news.yahoo.com/comics/dilbert-slideshow/"},
+{746,"http://news.yahoo.com/cost-cutting-may-have-played-role-in-navy-yard-shooting-134106229.html"},
+{682,"http://news.yahoo.com/giant-underground-blob-magma-puzzles-scientists-210726200.html"},
+{746,"http://news.yahoo.com/lightbox/dilbert-slideshow/20130523-dt130523-gif-photo-050423497.html"},
+{516,"http://news.yahoo.com/photos/costa-concordia-salvage-slideshow/"},
+{599,"http://news.yahoo.com/photos/turtle-rescue-in-israel-1379421810-slideshow/"},
+{666,"http://news.yahoo.com/put-business-trauma-doctor-pleads-u-navy-yard-181522657.html"},
+{698,"http://news.yahoo.com/touting-obamacare-us-says-millions-could-pay-less-212243340.html"},
+{578,"http://news.yahoo.com/video/old-soda-bottles-giving-life-001700872.html"},
+{380,"http://nl.wikipedia.org/wiki/Johann_David_Wyss"},
+{428,"http://nl.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{380,"http://no.wikipedia.org/wiki/Johann_David_Wyss"},
+{180,"http://omg.yahoo.com/"},
+{650,"http://omg.yahoo.com/blogs/celeb-news/brad-pitt-finally-makes-cut-223549188.html"},
+{794,"http://omg.yahoo.com/blogs/celeb-news/fashion-faceoff-miley-cyrus-vs-rachel-mcadams-190957403.html"},
+{882,"http://omg.yahoo.com/blogs/celeb-news/justin-theroux-reveals-one-thing-jennifer-aniston-wouldn-113635271.html"},
+{882,"http://omg.yahoo.com/news/courteney-cox-david-arquette-selling-beverly-hills-mansion-184500328-us-weekly.html"},
+{232,"http://omim.org/entry/602750"},
+{3387,"http://open.login.yahoo.net/openid/yrp/hr_signin?.intl=us&idp=facebook&ts=1379461518&rpcrumb=&.src=home&appid=90376669494&spid=b9ed13cc-ddec-11de-9c83-001b784d35e1&perms=email,user_birthday,user_education_history,user_likes,user_location,user_relationships,user_subscriptions,user_work_history,friends_birthday,friends_education_history,friends_likes,friends_location,friends_work_history&.done=http%3A%2F%2Fwww.yahoo.com%2F"},
+{320,"http://openlibrary.org/authors/OL342629A"},
+{340,"http://pl.wikipedia.org/wiki/Caron_Butler"},
+{380,"http://pl.wikipedia.org/wiki/Johann_David_Wyss"},
+{428,"http://pl.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{855,"http://probasketballtalk.nbcsports.com/2010/07/21/caron-butler-used-to-work-at-a-burger-king-now-owns-six/"},
+{340,"http://pt.wikipedia.org/wiki/Caron_Butler"},
+{659,"http://ru.wikipedia.org/wiki/%D0%91%D0%B0%D1%82%D0%BB%D0%B5%D1%80,_%D0%9A%D1%8D%D1%80%D0%BE%D0%BD"},
+{917,"http://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D1%81%D1%82%D0%B8%D1%82%D1%83%D1%86%D0%B8%D1%8F_%D0%A2%D1%83%D1%80%D1%86%D0%B8%D0%B8_(1921)"},
+{204,"http://screen.yahoo.com/"},
+{453,"http://screen.yahoo.com/11-old-boy-made-9-134626064.html"},
+{738,"http://screen.yahoo.com/snl-women-skits/girl-wish-hadnt-started-conversation-000000658.html"},
+{204,"http://search.yahoo.com/"},
+{244,"http://search.yahoo.com/local"},
+{741,"http://search.yahoo.com/search?cs=bz&p=Biblical-era%20town&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{765,"http://search.yahoo.com/search?cs=bz&p=Green%20River%20Killer&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{733,"http://search.yahoo.com/search?cs=bz&p=Hostile%20takeover&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{741,"http://search.yahoo.com/search?cs=bz&p=Jennifer%20Lopez%20&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{701,"http://search.yahoo.com/search?cs=bz&p=Jessa%20Duggar&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{717,"http://search.yahoo.com/search?cs=bz&p=Kim%20Zolciak%20&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{717,"http://search.yahoo.com/search?cs=bz&p=LSU%20fraternity&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{741,"http://search.yahoo.com/search?cs=bz&p=Linda%20Ronstadt%20&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{749,"http://search.yahoo.com/search?cs=bz&p=Star%20Trek%20NSA%20&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{781,"http://search.yahoo.com/search?cs=bz&p=Walking%20Dead%20spinoff&fr=fp-tts-900&fr2=ps&woeid=23424856"},
+{188,"http://shine.yahoo.com"},
+{196,"http://shine.yahoo.com/"},
+{276,"http://shine.yahoo.com/horoscope/"},
+{548,"http://shine.yahoo.com/horoscope/virgo/extended-daily-20130917.html"},
+{548,"http://shine.yahoo.com/horoscope/virgo/overview-daily-20130917.html"},
+{754,"http://shine.yahoo.com/shine-food/5-things-didnt-know-could-pillsbury-biscuits-205500571.html"},
+{730,"http://shine.yahoo.com/shine-food/fabios-ultimate-pulled-pork-sandwich-011700797.html?vp=1"},
+{220,"http://shopping.yahoo.com/"},
+{412,"http://simple.wikipedia.org/wiki/Johann_David_Wyss"},
+{428,"http://sk.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{436,"http://smallbusiness.yahoo.com/?s_fptrough=ysb_acq_fp"},
+{402,"http://sports.espn.go.com/nba/news/story?id=3290089"},
+{400,"http://sports.espn.go.com/nba/recap?gameId=270117027"},
+{400,"http://sports.espn.go.com/nba/recap?gameId=280313027"},
+{196,"http://sports.yahoo.com"},
+{204,"http://sports.yahoo.com/"},
+{911,"http://sports.yahoo.com/blogs/mlb-big-league-stew/fan-dashes-onto-field-during-rays-game-only-192151790--mlb.html"},
+{991,"http://sports.yahoo.com/blogs/nfl-shutdown-corner/does-andy-reid-still-wish-philadelphia-jamaal-charles-180705907--nfl.html"},
+{260,"http://sports.yahoo.com/fantasy"},
+{228,"http://sports.yahoo.com/mlb"},
+{376,"http://sports.yahoo.com/mlb/preview?gid=330917104"},
+{360,"http://sports.yahoo.com/mlb/recap?gid=330917220"},
+{308,"http://sports.yahoo.com/mlb/teams/atl"},
+{939,"http://sports.yahoo.com/nba/blog/ball_dont_lie/post/More-on-Caron-Butler-s-extreme-Mountain-Dew-addi?urn=nba%2C198240"},
+{332,"http://sports.yahoo.com/nba/players/3608"},
+{647,"http://sports.yahoo.com/news/team-report-san-francisco-49ers-211200051--nfl.html"},
+{228,"http://sports.yahoo.com/nfl"},
+{383,"http://sports.yahoo.com/nfl/preview?gid=20130919021"},
+{367,"http://sports.yahoo.com/nfl/recap?gid=20130916004"},
+{308,"http://sports.yahoo.com/nfl/teams/cin"},
+{228,"http://sports.yahoo.com/nhl"},
+{308,"http://sports.yahoo.com/nhl/teams/was"},
+{684,"http://sr.wikipedia.org/wiki/%D0%92%D0%B8%D1%88%D0%BD%D0%B8_%D0%A1%D0%BB%D0%B0%D0%B2%D0%BA%D0%BE%D0%B2"},
+{832,"http://ta.wikipedia.org/wiki/%E0%AE%95%E0%AE%B0%E0%AE%BE%E0%AE%A9%E0%AF%8D_%E0%AE%AA%E0%AE%9F%E0%AF%8D%E0%AE%B2%E0%AE%B0%E0%AF%8D"},
+{931,"http://th.wikipedia.org/wiki/%E0%B9%81%E0%B8%84%E0%B8%A3%E0%B8%AD%E0%B8%99_%E0%B8%9A%E0%B8%B1%E0%B8%95%E0%B9%80%E0%B8%A5%E0%B8%AD%E0%B8%A3%E0%B9%8C"},
+{818,"http://thptbinhxuyen.edu.vn/vp/Top-200-truong-THPT-co-diem-thi-dai-hoc-cao-nhat-2011-t11736-7938.html"},
+{972,"http://tools.wmflabs.org/geohack/geohack.php?pagename=Vy%C5%A1n%C3%BD_Slavkov&params=49_04_N_20_52_E_region:SK_type:city"},
+{340,"http://tr.wikipedia.org/wiki/Caron_Butler"},
+{604,"http://tr.wikipedia.org/wiki/Te%C5%9Fkil%C3%A2t-%C4%B1_Esas%C3%AEye_Kanunu"},
+{204,"http://travel.yahoo.com/"},
+{172,"http://tv.yahoo.com/"},
+{770,"http://tv.yahoo.com/news/ncis-exclusive-sopranos-alum-eyed-zivas-successor-debut-205821229.html"},
+{684,"http://tv.yahoo.com/photos/emmys-unrecognizable-emmy-star-transformations-slideshow/"},
+{717,"http://uk.wikipedia.org/wiki/%D0%92%D0%B8%D1%88%D0%BD%D1%96%D0%B9_%D0%A1%D0%BB%D0%B0%D0%B2%D0%BA%D0%BE%D0%B2"},
+{801,"http://vi.wikipedia.org/wiki/Tr%C6%B0%E1%BB%9Dng_THPT_chuy%C3%AAn_L%C6%B0%C6%A1ng_V%C4%83n_Ch%C3%A1nh"},
+{1046,"http://vi.wikipedia.org/wiki/X%E1%BA%BFp_h%E1%BA%A1ng_tr%C6%B0%E1%BB%9Dng_trung_h%E1%BB%8Dc_ph%E1%BB%95_th%C3%B4ng_Vi%E1%BB%87t_Nam"},
+{232,"http://viaf.org/viaf/94287141"},
+{684,"http://voices.washingtonpost.com/dcsportsbog/2007/04/on_caron_butler_and_straws.html"},
+{436,"http://war.wikipedia.org/wiki/Vy%C5%A1n%C3%BD_Slavkov"},
+{505,"http://washingtontimes.com/sports/20060417-122458-4991r_page2.htm"},
+{204,"http://weather.yahoo.com"},
+{404,"http://weather.yahoo.com/forecast/JAXX0077_f.html"},
+{740,"http://web.archive.org/web/20040603025509/http://www.usabasketball.com/history/ymwc_2001.html"},
+{260,"http://wikimediafoundation.org/"},
+{412,"http://wikimediafoundation.org/wiki/Privacy_policy"},
+{396,"http://wikimediafoundation.org/wiki/Terms_of_Use"},
+{308,"http://www.anayasa.gen.tr/1921tek.htm"},
+{492,"http://www.basketball-reference.com/players/b/butleca01.html"},
+{587,"http://www.basketballreference.com/players/playerpage.htm?ilkid=BUTLECA01"},
+{380,"http://www.bilkent.edu.tr/~genckaya/1921C.html"},
+{308,"http://www.caronbutlersummercamp.com/"},
+{308,"http://www.daao.org.au/main/read/2355"},
+{386,"http://www.ebi.ac.uk/QuickGO/GProtein?ac=P30046"},
+{1416,"http://www.ebi.ac.uk/pdbe/searchResults.html?display=both&term=P30046%20or%20Q53Y51%20or%20E2RQU0%20or%20A5PK65%20or%20O35215%20or%20Q3UNI8%20or%20P80254%20or%20Q5ZMG0%20or%20Q6IQL4"},
+{574,"http://www.ensembl.org/Homo_sapiens/geneview?gene=ENSG00000099977;db=core"},
+{591,"http://www.ensembl.org/Mus_musculus/geneview?gene=ENSMUSG00000001666;db=core"},
+{188,"http://www.flickr.com/"},
+{550,"http://www.flickr.com/photos/yahooeditorspicks/galleries/72157635598104765"},
+{901,"http://www.flickr.com/photos/yahooeditorspicks/galleries/72157635598104765/with/7037921709/lightbox/?yc=www.yahoo.com"},
+{952,"http://www.fool.com/investing/general/2013/09/16/3-car-brands-that-may-disappear-before-2020.aspx?source=eogyholnk0000001"},
+{576,"http://www.genecards.org/cgi-bin/carddisp.pl?id_type=entrezgene&id=1652"},
+{456,"http://www.genenames.org/data/hgnc_data.php?hgnc_id=2732"},
+{443,"http://www.genome.jp/dbget-bin/www_bget?enzyme+4.1.1.84"},
+{404,"http://www.gutenberg.org/author/Johann_David_Wyss"},
+{597,"http://www.informatics.jax.org/searches/accession_report.cgi?id=MGI:1298381"},
+{212,"http://www.intonow.com/ci"},
+{348,"http://www.leighrayment.com/baronetage.htm"},
+{444,"http://www.london-gazette.co.uk/issues/21964/pages/379"},
+{436,"http://www.mapress.com/zootaxa/2010/f/z02583p119f.pdf"},
+{340,"http://www.mapress.com/zootaxa/index.html"},
+{212,"http://www.mediawiki.org/"},
+{544,"http://www.nba.com/allstar2007/news/allstar_reserves_070201.html"},
+{332,"http://www.nba.com/news/pow_070122.html"},
+{348,"http://www.nba.com/playerfile/caron_butler"},
+{356,"http://www.nba.com/playerfile/caron_butler/"},
+{492,"http://www.nba.com/suns/news/suns-trade-kravtsov-smith-bucks"},
+{588,"http://www.nba.com/suns/suns-complete-deal-eric-bledsoe-and-caron-butler"},
+{832,"http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=homologene&dopt=HomoloGene&list_uids=1038"},
+{812,"http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=retrieve&dopt=default&list_uids=13202&rn=1"},
+{804,"http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=gene&cmd=retrieve&dopt=default&list_uids=1652&rn=1"},
+{488,"http://www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?val=NM_001084392"},
+{478,"http://www.ncbi.nlm.nih.gov/entrez/viewer.fcgi?val=NM_010027"},
+{405,"http://www.ncbi.nlm.nih.gov/pmc/articles/PMC1219731"},
+{400,"http://www.ncbi.nlm.nih.gov/pmc/articles/PMC139241"},
+{405,"http://www.ncbi.nlm.nih.gov/pmc/articles/PMC1847948"},
+{344,"http://www.ncbi.nlm.nih.gov/pubmed/10079069"},
+{341,"http://www.ncbi.nlm.nih.gov/pubmed/1286669"},
+{341,"http://www.ncbi.nlm.nih.gov/pubmed/8267597"},
+{688,"http://www.ncbi.nlm.nih.gov/sites/entrez?Db=gene&Cmd=ShowDetailView&TermToSearch=1652"},
+{747,"http://www.ncbi.nlm.nih.gov/sites/entrez?db=gene&cmd=Link&LinkName=gene_pubmed&from_uid=13202"},
+{744,"http://www.ncbi.nlm.nih.gov/sites/entrez?db=gene&cmd=Link&LinkName=gene_pubmed&from_uid=1652"},
+{428,"http://www.oprah.com/oprahshow/Overcoming-the-Odds/8"},
+{428,"http://www.oprah.com/oprahshow/Overcoming-the-Odds/9"},
+{412,"http://www.rcsb.org/pdb/cgi/explore.cgi?pdbId=1DPT"},
+{1322,"http://www.rcsb.org/pdb/search/smartSubquery.do?smartSearchSubtype=UpAccessionIdQuery&accessionIdList=P30046,Q53Y51,E2RQU0,A5PK65,O35215,Q3UNI8,P80254,Q5ZMG0,Q6IQL4"},
+{806,"http://www.sbnation.com/golf/2013/9/17/4737628/bmw-championship-2013-tiger-woods-penalty-johnny-miller"},
+{364,"http://www.statistics.sk/mosmis/eng/run.html"},
+{188,"http://www.tbmm.gov.tr"},
+{372,"http://www.tbmm.gov.tr/english/about_tgna.htm"},
+{212,"http://www.thepeerage.com"},
+{284,"http://www.thepeerage.com/info.htm"},
+{585,"http://www.uconnhuskies.com/AllStories/MBasketball/2002/06/26/20020626.html"},
+{304,"http://www.uniprot.org/uniprot/O35215"},
+{304,"http://www.uniprot.org/uniprot/P30046"},
+{644,"http://www.washingtonpost.com/wp-dyn/content/article/2008/02/16/AR2008021600752_2.html"},
+{293,"http://www.wikidata.org/wiki/Q115822"},
+{460,"http://www.wikidata.org/wiki/Q115822#sitelinks-wikipedia"},
+{292,"http://www.wikimediafoundation.org/"},
+{172,"http://www.yahoo.com"},
+{180,"http://www.yahoo.com/"},
+{188,"http://www.yahoo.com/#"},
+{276,"http://www.yahoo.com/#suggestions"},
+{244,"http://www.yahoo.com/?hps=210"},
+{444,"http://yahoo.match.com?trackingid=526100&bannerid=673168"},
+{535,"http://zh.wikipedia.org/wiki/%E5%8D%A1%E9%9A%86%C2%B7%E5%B7%B4%E7%89%B9%E5%8B%92"},
+{1164,"https://donate.wikimedia.org/wiki/Special:FundraiserRedirector?utm_source=donate&utm_medium=sidebar&utm_campaign=C13_en.wikipedia.org&uselang=en"},
+{740,"https://edit.yahoo.com/registration?.src=fpctx&.intl=us&.done=http%3A%2F%2Fwww.yahoo.com%2F"},
+{748,"https://login.yahoo.com/config/login?.src=fpctx&.intl=us&.done=http%3A%2F%2Fwww.yahoo.com%2F"},
+{548,"https://www.mediawiki.org/wiki/Special:MyLanguage/How_to_contribute"},
+{0,NULL}
+};
diff --git a/genqrcode/tests/common.c b/genqrcode/tests/common.c
new file mode 100644
index 0000000000..696a94b3a5
--- /dev/null
+++ b/genqrcode/tests/common.c
@@ -0,0 +1,285 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "common.h"
+
+static int tests = 0;
+static int failed = 0;
+int assertionFailed = 0;
+int assertionNum = 0;
+static const char *testName = NULL;
+static const char *testFunc = NULL;
+
+const char levelChar[4] = {'L', 'M', 'Q', 'H'};
+const char *modeStr[5] = {"nm", "an", "8", "kj", "st"};
+
+int ncmpBin(char *correct, BitStream *bstream, size_t len)
+{
+ int bit;
+ size_t i;
+ char *p;
+
+ if(len != BitStream_size(bstream)) {
+ printf("Length is not match: %zu, %zu expected.\n", BitStream_size(bstream), len);
+ return -1;
+ }
+
+ p = correct;
+ i = 0;
+ while(*p != '\0') {
+ while(*p == ' ') {
+ p++;
+ }
+ bit = (*p == '1')?1:0;
+ if(bstream->data[i] != bit) return -1;
+ i++;
+ p++;
+ if(i == len) break;
+ }
+
+ return 0;
+}
+
+int cmpBin(char *correct, BitStream *bstream)
+{
+ size_t len = 0;
+ char *p;
+
+
+ for(p = correct; *p != '\0'; p++) {
+ if(*p != ' ') len++;
+ }
+ return ncmpBin(correct, bstream, len);
+}
+
+void testInit(int testnum)
+{
+ printf("1..%d\n", testnum);
+}
+
+void testStartReal(const char *func, const char *name)
+{
+ tests++;
+ testName = name;
+ testFunc = func;
+ assertionFailed = 0;
+ assertionNum = 0;
+ //printf("_____%d: %s: %s...\n", tests, func, name);
+}
+
+void testEnd(int result)
+{
+ if(result) {
+ printf("not ok %d %s: %s\n", tests, testFunc, testName);
+ failed++;
+ } else {
+ printf("ok %d %s: %s\n", tests, testFunc, testName);
+ }
+}
+
+void testFinish(void)
+{
+ if(assertionFailed) {
+ printf("not ok %d %s: %s (%d assertions failed.)\n", tests, testFunc, testName, assertionFailed);
+ failed++;
+ } else {
+ printf("ok %d %s: %s (%d assertions passed.)\n", tests, testFunc, testName, assertionNum);
+ }
+}
+
+void testReport(int expectedTests)
+{
+ printf("Total %d tests, %d fails.\n", tests, failed);
+ if(failed) exit(-1);
+ if(expectedTests != tests) {
+ printf("WARNING: the number of the executed tests (%d) is not equal to the expecetd (%d).\n", tests, expectedTests);
+ }
+}
+
+void printBinary(unsigned char *data, size_t length)
+{
+ size_t i;
+
+ for(i=0; i<length; i++) {
+ printf(data[i]?"1":"0");
+ }
+ printf("\n");
+}
+
+void printBstream(BitStream *bstream)
+{
+ printBinary(bstream->data, BitStream_size(bstream));
+}
+
+void printQRinput(QRinput *input)
+{
+ QRinput_List *list;
+ int i;
+
+ list = input->head;
+ while(list != NULL) {
+ for(i=0; i<list->size; i++) {
+ printf("0x%02x,", list->data[i]);
+ }
+ list = list->next;
+ }
+ printf("\n");
+}
+
+void printQRinputInfo(QRinput *input)
+{
+ QRinput_List *list;
+ BitStream *b;
+ int i, ret;
+
+ printf("QRinput info:\n");
+ printf(" version: %d\n", input->version);
+ printf(" level : %c\n", levelChar[input->level]);
+ list = input->head;
+ i = 0;
+ while(list != NULL) {
+ i++;
+ list = list->next;
+ }
+ printf(" chunks: %d\n", i);
+ b = BitStream_new();
+ ret = QRinput_mergeBitStream(input, b);
+ if(ret == 0) {
+ printf(" bitstream-size: %zu\n", BitStream_size(b));
+ BitStream_free(b);
+ }
+
+ list = input->head;
+ i = 0;
+ while(list != NULL) {
+ printf("\t#%d: mode = %s, size = %d\n", i, modeStr[list->mode], list->size);
+ i++;
+ list = list->next;
+ }
+}
+
+void printQRinputStruct(QRinput_Struct *s)
+{
+ QRinput_InputList *list;
+ int i = 1;
+
+ printf("Struct size: %d\n", s->size);
+ printf("Struct parity: %08x\n", s->parity);
+ for(list = s->head; list != NULL; list = list->next) {
+ printf("Symbol %d - ", i);
+ printQRinputInfo(list->input);
+ i++;
+ }
+}
+
+void printFrame(int width, unsigned char *frame)
+{
+ int x, y;
+
+ for(y=0; y<width; y++) {
+ for(x=0; x<width; x++) {
+ printf("%02x ", *frame++);
+ }
+ printf("\n");
+ }
+}
+
+void printQRcode(QRcode *code)
+{
+ printFrame(code->width, code->data);
+}
+
+void printQRRawCodeFromQRinput(QRinput *input)
+{
+ QRRawCode *raw;
+ int i;
+
+ puts("QRRawCode dump image:");
+ raw = QRraw_new(input);
+ if(raw == NULL) {
+ puts("Failed to generate QRRawCode from this input.\n");
+ return;
+ }
+ for(i=0; i<raw->dataLength; i++) {
+ printf(" %02x", raw->datacode[i]);
+ }
+ for(i=0; i<raw->eccLength; i++) {
+ printf(" %02x", raw->ecccode[i]);
+ }
+ printf("\n");
+ QRraw_free(raw);
+}
+
+#if HAVE_SDL
+/* Experimental debug function */
+/* You can call show_QRcode(QRcode *code) to display the QR Code from anywhere
+ * in test code using SDL. */
+#include <SDL.h>
+
+static void draw_QRcode(QRcode *qrcode, int ox, int oy, int margin, int size, SDL_Surface *surface)
+{
+ int x, y, width;
+ unsigned char *p;
+ SDL_Rect rect;
+ Uint32 color[2];
+
+ color[0] = SDL_MapRGBA(surface->format, 255, 255, 255, 255);
+ color[1] = SDL_MapRGBA(surface->format, 0, 0, 0, 255);
+ SDL_FillRect(surface, NULL, color[0]);
+
+ ox += margin * size;
+ oy += margin * size;
+ width = qrcode->width;
+ p = qrcode->data;
+ for(y=0; y<width; y++) {
+ for(x=0; x<width; x++) {
+ rect.x = ox + x * size;
+ rect.y = oy + y * size;
+ rect.w = size;
+ rect.h = size;
+ SDL_FillRect(surface, &rect, color[*p&1]);
+ p++;
+ }
+ }
+}
+
+void show_QRcode(QRcode *qrcode)
+{
+ SDL_Event event;
+ SDL_Window *window;
+ SDL_Renderer *renderer;
+ SDL_Surface *surface;
+ SDL_Texture *texture;
+
+ if(!SDL_WasInit(SDL_INIT_VIDEO)) {
+ SDL_Init(SDL_INIT_VIDEO);
+ atexit(SDL_Quit);
+ }
+ int width = (qrcode->width + 4 * 2) * 4; //maring = 4, size = 4
+ SDL_CreateWindowAndRenderer(width, width, SDL_WINDOW_SHOWN, &window, &renderer);
+ SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
+ SDL_RenderClear(renderer);
+ surface = SDL_CreateRGBSurface(0, width, width, 32, 0, 0, 0, 0);
+
+ draw_QRcode(qrcode, 0, 0, 4, 4, surface);
+
+ texture = SDL_CreateTextureFromSurface(renderer, surface);
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
+ fprintf(stderr, "Press any key on the QR Code window to proceed.\n");
+
+ int loop = 1;
+ while(loop) {
+ SDL_WaitEvent(&event);
+ if(event.type == SDL_KEYDOWN) {
+ loop = 0;
+ }
+ }
+
+ SDL_FreeSurface(surface);
+ SDL_DestroyTexture(texture);
+ SDL_DestroyRenderer(renderer);
+}
+#else
+void show_QRcode(QRcode *qrcode) {
+}
+#endif
diff --git a/genqrcode/tests/common.h b/genqrcode/tests/common.h
new file mode 100644
index 0000000000..ddd2e1460e
--- /dev/null
+++ b/genqrcode/tests/common.h
@@ -0,0 +1,56 @@
+/*
+ * common part of test units.
+ */
+
+#ifndef COMMON_H__
+#define COMMON_H__
+
+#include <stdlib.h>
+#if HAVE_CONFIG_H
+#include "../config.h"
+#endif
+#include "../qrencode.h"
+#include "../qrinput.h"
+#include "../bitstream.h"
+#include "../qrencode_inner.h"
+
+extern int assertionFailed;
+extern int assertionNum;
+extern const char levelChar[4];
+extern const char *modeStr[5];
+
+void testInit(int tests);
+#define testStart(__arg__) (testStartReal(__func__, __arg__))
+#define testEndExp(__arg__) (testEnd(!(__arg__)))
+void testStartReal(const char *func, const char *name);
+void testEnd(int result);
+void testFinish(void);
+void testReport(int tests);
+
+#define assert_exp(__exp__, ...) \
+{assertionNum++;if(!(__exp__)) {assertionFailed++; printf(__VA_ARGS__);}}
+
+#define assert_zero(__exp__, ...) assert_exp((__exp__) == 0, __VA_ARGS__)
+#define assert_nonzero(__exp__, ...) assert_exp((__exp__) != 0, __VA_ARGS__)
+#define assert_null(__ptr__, ...) assert_exp((__ptr__) == NULL, __VA_ARGS__)
+#define assert_nonnull(__ptr__, ...) assert_exp((__ptr__) != NULL, __VA_ARGS__)
+#define assert_equal(__e1__, __e2__, ...) assert_exp((__e1__) == (__e2__), __VA_ARGS__)
+#define assert_notequal(__e1__, __e2__, ...) assert_exp((__e1__) != (__e2__), __VA_ARGS__)
+#define assert_nothing(__exp__, ...) {printf(__VA_ARGS__); __exp__;}
+
+int ncmpBin(char *correct, BitStream *bstream, size_t len);
+int cmpBin(char *correct, BitStream *bstream);
+
+void printFrame(int width, unsigned char *frame);
+void printQRcode(QRcode *code);
+void printQRRawCodeFromQRinput(QRinput *input);
+void printQRinput(QRinput *input);
+void printQRinputInfo(QRinput *input);
+void printQRinputStruct(QRinput_Struct *s);
+
+void printBinary(unsigned char *data, size_t length);
+void printBstream(BitStream *bstream);
+
+void show_QRcode(QRcode *qrcode);
+
+#endif /* COMMON_H__ */
diff --git a/genqrcode/tests/create_frame_pattern.c b/genqrcode/tests/create_frame_pattern.c
new file mode 100644
index 0000000000..786309fe52
--- /dev/null
+++ b/genqrcode/tests/create_frame_pattern.c
@@ -0,0 +1,170 @@
+/*
+ * This tool creates a frame pattern data for debug purpose used by
+ * test_qrspec. test_qrspec and create_frame_pattern uses the same function
+ * of libqrencode. This means the test is meaningless if test_qrspec is run
+ * with a pattern data created by create_frame_pattern of the same version.
+ * In order to test it correctly, create a pattern data by the tool of the
+ * previous version, or use the frame data attached to the package.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <png.h>
+#include "common.h"
+#include "../qrspec.h"
+
+void append_pattern(int version, FILE *fp)
+{
+ int width;
+ unsigned char *frame;
+
+ frame = QRspec_newFrame(version);
+ width = QRspec_getWidth(version);
+ fwrite(frame, 1, width * width, fp);
+ free(frame);
+}
+
+static int writePNG(unsigned char *frame, int width, const char *outfile)
+{
+ static FILE *fp;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ unsigned char *row, *p, *q;
+ int x, y, xx, yy, bit;
+ int realwidth;
+ const int margin = 0;
+ const int size = 1;
+
+ realwidth = (width + margin * 2) * size;
+ row = (unsigned char *)malloc((realwidth + 7) / 8);
+ if(row == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(outfile[0] == '-' && outfile[1] == '\0') {
+ fp = stdout;
+ } else {
+ fp = fopen(outfile, "wb");
+ if(fp == NULL) {
+ fprintf(stderr, "Failed to create file: %s\n", outfile);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if(png_ptr == NULL) {
+ fclose(fp);
+ fprintf(stderr, "Failed to initialize PNG writer.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if(info_ptr == NULL) {
+ fclose(fp);
+ fprintf(stderr, "Failed to initialize PNG write.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ fclose(fp);
+ fprintf(stderr, "Failed to write PNG image.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ png_init_io(png_ptr, fp);
+ png_set_IHDR(png_ptr, info_ptr,
+ realwidth, realwidth,
+ 1,
+ PNG_COLOR_TYPE_GRAY,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+ png_write_info(png_ptr, info_ptr);
+
+ /* top margin */
+ memset(row, 0xff, (realwidth + 7) / 8);
+ for(y=0; y<margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+
+ /* data */
+ p = frame;
+ for(y=0; y<width; y++) {
+ bit = 7;
+ memset(row, 0xff, (realwidth + 7) / 8);
+ q = row;
+ q += margin * size / 8;
+ bit = 7 - (margin * size % 8);
+ for(x=0; x<width; x++) {
+ for(xx=0; xx<size; xx++) {
+ *q ^= (*p & 1) << bit;
+ bit--;
+ if(bit < 0) {
+ q++;
+ bit = 7;
+ }
+ }
+ p++;
+ }
+ for(yy=0; yy<size; yy++) {
+ png_write_row(png_ptr, row);
+ }
+ }
+ /* bottom margin */
+ memset(row, 0xff, (realwidth + 7) / 8);
+ for(y=0; y<margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ fclose(fp);
+ free(row);
+
+ return 0;
+}
+
+void write_pattern_image(int version, const char *filename)
+{
+ int width;
+ unsigned char *frame;
+ static char str[256];
+
+ frame = QRspec_newFrame(version);
+ width = QRspec_getWidth(version);
+
+ snprintf(str, 256, "%s-%d.png", filename, version);
+ writePNG(frame, width, str);
+ free(frame);
+}
+
+void write_pattern(const char *filename)
+{
+ FILE *fp;
+ int i;
+
+ fp = fopen(filename, "wb");
+ if(fp == NULL) {
+ perror("Failed to open a file to write:");
+ abort();
+ }
+ for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
+ append_pattern(i, fp);
+ write_pattern_image(i, filename);
+ }
+ fclose(fp);
+}
+
+int main(int argc, char **argv)
+{
+ if(argc < 2) {
+ printf("Create empty frame patterns.\nUsage: %s FILENAME\n", argv[0]);
+ exit(0);
+ }
+ write_pattern(argv[1]);
+ return 0;
+}
diff --git a/genqrcode/tests/create_mqr_frame_pattern.c b/genqrcode/tests/create_mqr_frame_pattern.c
new file mode 100644
index 0000000000..cad1f9c513
--- /dev/null
+++ b/genqrcode/tests/create_mqr_frame_pattern.c
@@ -0,0 +1,170 @@
+/*
+ * This tool creates a frame pattern data for debug purpose used by
+ * test_qrspec. test_qrspec and create_frame_pattern uses the same function
+ * of libqrencode. This means the test is meaningless if test_qrspec is run
+ * with a pattern data created by create_frame_pattern of the same version.
+ * In order to test it correctly, create a pattern data by the tool of the
+ * previous version, or use the frame data attached to the package.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <png.h>
+#include "common.h"
+#include "../mqrspec.h"
+
+void append_pattern(int version, FILE *fp)
+{
+ int width;
+ unsigned char *frame;
+
+ frame = MQRspec_newFrame(version);
+ width = MQRspec_getWidth(version);
+ fwrite(frame, 1, width * width, fp);
+ free(frame);
+}
+
+static int writePNG(unsigned char *frame, int width, const char *outfile)
+{
+ static FILE *fp;
+ png_structp png_ptr;
+ png_infop info_ptr;
+ unsigned char *row, *p, *q;
+ int x, y, xx, yy, bit;
+ int realwidth;
+ const int margin = 0;
+ const int size = 1;
+
+ realwidth = (width + margin * 2) * size;
+ row = (unsigned char *)malloc((realwidth + 7) / 8);
+ if(row == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(outfile[0] == '-' && outfile[1] == '\0') {
+ fp = stdout;
+ } else {
+ fp = fopen(outfile, "wb");
+ if(fp == NULL) {
+ fprintf(stderr, "Failed to create file: %s\n", outfile);
+ perror(NULL);
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if(png_ptr == NULL) {
+ fclose(fp);
+ fprintf(stderr, "Failed to initialize PNG writer.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ info_ptr = png_create_info_struct(png_ptr);
+ if(info_ptr == NULL) {
+ fclose(fp);
+ fprintf(stderr, "Failed to initialize PNG write.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(setjmp(png_jmpbuf(png_ptr))) {
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+ fclose(fp);
+ fprintf(stderr, "Failed to write PNG image.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ png_init_io(png_ptr, fp);
+ png_set_IHDR(png_ptr, info_ptr,
+ realwidth, realwidth,
+ 1,
+ PNG_COLOR_TYPE_GRAY,
+ PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_DEFAULT,
+ PNG_FILTER_TYPE_DEFAULT);
+ png_write_info(png_ptr, info_ptr);
+
+ /* top margin */
+ memset(row, 0xff, (realwidth + 7) / 8);
+ for(y=0; y<margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+
+ /* data */
+ p = frame;
+ for(y=0; y<width; y++) {
+ bit = 7;
+ memset(row, 0xff, (realwidth + 7) / 8);
+ q = row;
+ q += margin * size / 8;
+ bit = 7 - (margin * size % 8);
+ for(x=0; x<width; x++) {
+ for(xx=0; xx<size; xx++) {
+ *q ^= (*p & 1) << bit;
+ bit--;
+ if(bit < 0) {
+ q++;
+ bit = 7;
+ }
+ }
+ p++;
+ }
+ for(yy=0; yy<size; yy++) {
+ png_write_row(png_ptr, row);
+ }
+ }
+ /* bottom margin */
+ memset(row, 0xff, (realwidth + 7) / 8);
+ for(y=0; y<margin * size; y++) {
+ png_write_row(png_ptr, row);
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ png_destroy_write_struct(&png_ptr, &info_ptr);
+
+ fclose(fp);
+ free(row);
+
+ return 0;
+}
+
+void write_pattern_image(int version, const char *filename)
+{
+ int width;
+ unsigned char *frame;
+ static char str[256];
+
+ frame = MQRspec_newFrame(version);
+ width = MQRspec_getWidth(version);
+
+ snprintf(str, 256, "%s-M%d.png", filename, version);
+ writePNG(frame, width, str);
+ free(frame);
+}
+
+void write_pattern(const char *filename)
+{
+ FILE *fp;
+ int i;
+
+ fp = fopen(filename, "wb");
+ if(fp == NULL) {
+ perror("Failed to open a file to write:");
+ abort();
+ }
+ for(i=1; i<=MQRSPEC_VERSION_MAX; i++) {
+ append_pattern(i, fp);
+ write_pattern_image(i, filename);
+ }
+ fclose(fp);
+}
+
+int main(int argc, char **argv)
+{
+ if(argc < 2) {
+ printf("Create empty frame patterns.\nUsage: %s FILENAME\n", argv[0]);
+ exit(0);
+ }
+ write_pattern(argv[1]);
+ return 0;
+}
diff --git a/genqrcode/tests/datachunk.c b/genqrcode/tests/datachunk.c
new file mode 100644
index 0000000000..62bb2f964c
--- /dev/null
+++ b/genqrcode/tests/datachunk.c
@@ -0,0 +1,178 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iconv.h>
+#include "datachunk.h"
+
+DataChunk *DataChunk_new(QRencodeMode mode)
+{
+ DataChunk *chunk;
+
+ chunk = (DataChunk *)calloc(1, sizeof(DataChunk));
+ if(chunk == NULL) return NULL;
+
+ chunk->mode = mode;
+
+ return chunk;
+}
+
+void DataChunk_free(DataChunk *chunk)
+{
+ if(chunk) {
+ if(chunk->data) free(chunk->data);
+ free(chunk);
+ }
+}
+
+void DataChunk_freeList(DataChunk *list)
+{
+ DataChunk *next;
+
+ while(list != NULL) {
+ next = list->next;
+ DataChunk_free(list);
+ list = next;
+ }
+}
+
+static void dumpNum(DataChunk *chunk)
+{
+ printf("%s\n", chunk->data);
+}
+
+static void dumpAn(DataChunk *chunk)
+{
+ printf("%s\n", chunk->data);
+}
+
+static void dump8(DataChunk *chunk)
+{
+ size_t i, j;
+ unsigned char c;
+ size_t count = 0;
+ unsigned char buf[16];
+
+ for(i=0; i<chunk->size; i++) {
+ buf[count] = chunk->data[i];
+ c = chunk->data[i];
+ if(c >= ' ' && c <= '~') {
+ putchar(c);
+ } else {
+ putchar('.');
+ }
+ count++;
+
+ if(count >= 16) {
+ putchar(' ');
+ for(j=0; j<16; j++) {
+ printf(" %02x", buf[j]);
+ }
+ count = 0;
+ putchar('\n');
+ }
+ }
+ if(count > 0) {
+ for(i=0; i<16 - count; i++) {
+ putchar(' ');
+ }
+ putchar(' ');
+ for(j=0; j<count; j++) {
+ printf(" %02x", buf[j]);
+ }
+ count = 0;
+ putchar('\n');
+ }
+}
+
+static void dumpKanji(DataChunk *chunk)
+{
+ iconv_t conv;
+ char *inbuf, *outbuf, *outp;
+ size_t inbytes, outbytes, ret;
+
+ conv = iconv_open("UTF-8", "SHIFT_JIS");
+ inbytes = chunk->size;
+ inbuf = (char *)chunk->data;
+ outbytes = inbytes * 4 + 1;
+ outbuf = (char *)malloc(inbytes * 4 + 1);
+ outp = outbuf;
+ ret = iconv(conv, &inbuf, &inbytes, &outp, &outbytes);
+ if(ret == (size_t) -1) { perror(NULL); }
+ *outp = '\0';
+
+ printf("%s\n", outbuf);
+
+ iconv_close(conv);
+ free(outbuf);
+}
+
+static void dumpChunk(DataChunk *chunk)
+{
+ switch(chunk->mode) {
+ case QR_MODE_NUM:
+ printf("Numeric: %zu bytes\n", chunk->size);
+ dumpNum(chunk);
+ break;
+ case QR_MODE_AN:
+ printf("AlphaNumeric: %zu bytes\n", chunk->size);
+ dumpAn(chunk);
+ break;
+ case QR_MODE_8:
+ printf("8-bit data: %zu bytes\n", chunk->size);
+ dump8(chunk);
+ break;
+ case QR_MODE_KANJI:
+ printf("Kanji: %zu bytes\n", chunk->size);
+ dumpKanji(chunk);
+ break;
+ case QR_MODE_NUL:
+ case QR_MODE_STRUCTURE:
+ case QR_MODE_ECI:
+ case QR_MODE_FNC1FIRST:
+ case QR_MODE_FNC1SECOND:
+ printf("Invalid or reserved: %zu bytes\n", chunk->size);
+ dump8(chunk);
+ break;
+ }
+}
+
+void DataChunk_dumpChunkList(DataChunk *list)
+{
+ while(list != NULL) {
+ dumpChunk(list);
+ list = list->next;
+ }
+}
+
+int DataChunk_totalSize(DataChunk *list)
+{
+ int size = 0;
+
+ while(list != NULL) {
+ size += list->size;
+ list = list->next;
+ }
+
+ return size;
+}
+
+unsigned char *DataChunk_concatChunkList(DataChunk *list, int *retsize)
+{
+ int size, idx;
+ unsigned char *data;
+
+ size = DataChunk_totalSize(list);
+ if(size <= 0) return NULL;
+
+ data = (unsigned char *)malloc((size_t)size + 1);
+ idx = 0;
+ while(list != NULL) {
+ memcpy(&data[idx], list->data, list->size);
+ idx += list->size;
+ list = list->next;
+ }
+ data[size] = '\0';
+
+ *retsize = size;
+ return data;
+}
diff --git a/genqrcode/tests/datachunk.h b/genqrcode/tests/datachunk.h
new file mode 100644
index 0000000000..8ef076c4fa
--- /dev/null
+++ b/genqrcode/tests/datachunk.h
@@ -0,0 +1,20 @@
+#ifndef DATACHUNK_H
+#define DATACHUNK_H
+
+#include "../qrencode.h"
+
+typedef struct _DataChunk {
+ QRencodeMode mode;
+ size_t size;
+ unsigned char *data;
+ struct _DataChunk *next;
+} DataChunk;
+
+DataChunk *DataChunk_new(QRencodeMode mode);
+void DataChunk_free(DataChunk *chunk);
+void DataChunk_freeList(DataChunk *list);
+void DataChunk_dumpChunkList(DataChunk *list);
+int DataChunk_totalSize(DataChunk *list);
+unsigned char *DataChunk_concatChunkList(DataChunk *list, int *retsize);
+
+#endif /* DATACHUNK_H */
diff --git a/genqrcode/tests/decoder.c b/genqrcode/tests/decoder.c
new file mode 100644
index 0000000000..706dc31e40
--- /dev/null
+++ b/genqrcode/tests/decoder.c
@@ -0,0 +1,953 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <iconv.h>
+#if HAVE_CONFIG_H
+#include "../config.h"
+#endif
+#include "../qrspec.h"
+#include "../bitstream.h"
+#include "../mask.h"
+#include "../mqrspec.h"
+#include "../mmask.h"
+#include "common.h"
+#include "decoder.h"
+
+static unsigned int bitToInt(unsigned char *bits, int length)
+{
+ int i;
+ unsigned int val = 0;
+
+ for(i=0; i<length; i++) {
+ val = val << 1;
+ val |= (bits[i] & 1);
+ }
+
+ return val;
+}
+
+static int decodeLength(int *bits_length, unsigned char **bits, QRencodeMode mode, int version, int mqr)
+{
+ int i;
+ int length = 0;
+ int lbits;
+
+ if(mqr) {
+ lbits = MQRspec_lengthIndicator(mode, version);
+ } else {
+ lbits = QRspec_lengthIndicator(mode, version);
+ }
+
+ if(*bits_length < lbits) {
+ printf("Bit length is too short: %d\n", *bits_length);
+ return 0;
+ }
+
+ length = 0;
+ for(i=0; i<lbits; i++) {
+ length = length << 1;
+ length += (*bits)[i];
+ }
+
+ *bits_length -= lbits;
+ *bits += lbits;
+
+ return length;
+}
+
+static DataChunk *decodeNum(int *bits_length, unsigned char **bits, int version, int mqr)
+{
+ int i;
+ int size, sizeInBit, words, remain;
+ unsigned char *p;
+ char *buf, *q;
+ unsigned int val;
+ DataChunk *chunk;
+
+ size = decodeLength(bits_length, bits, QR_MODE_NUM, version, mqr);
+ if(size < 0) return NULL;
+
+ words = size / 3;
+ remain = size - words * 3;
+ sizeInBit = words * 10;
+ if(remain == 2) {
+ sizeInBit += 7;
+ } else if(remain == 1) {
+ sizeInBit += 4;
+ }
+ if(*bits_length < sizeInBit) {
+ printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
+ return NULL;
+ }
+
+ buf = (char *)malloc((size_t)size + 1);
+ p = *bits;
+ q = buf;
+ for(i=0; i<words; i++) {
+ val = bitToInt(p, 10);
+ sprintf(q, "%03d", val);
+ p += 10;
+ q += 3;
+ }
+ if(remain == 2) {
+ val = bitToInt(p, 7);
+ sprintf(q, "%02d", val);
+ } else if(remain == 1) {
+ val = bitToInt(p, 4);
+ sprintf(q, "%1d", val);
+ }
+ buf[size] = '\0';
+
+ chunk = DataChunk_new(QR_MODE_NUM);
+ chunk->size = size;
+ chunk->data = (unsigned char *)buf;
+ *bits_length -= sizeInBit;
+ *bits += sizeInBit;
+
+ return chunk;
+}
+
+static const char decodeAnTable[45] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*',
+ '+', '-', '.', '/', ':'
+};
+
+static DataChunk *decodeAn(int *bits_length, unsigned char **bits, int version, int mqr)
+{
+ int i;
+ int size, sizeInBit, words, remain;
+ unsigned char *p;
+ char *buf, *q;
+ unsigned int val;
+ int ch, cl;
+ DataChunk *chunk;
+
+ size = decodeLength(bits_length, bits, QR_MODE_AN, version, mqr);
+ if(size < 0) return NULL;
+
+ words = size / 2;
+ remain = size - words * 2;
+ sizeInBit = words * 11 + remain * 6;
+ if(*bits_length < sizeInBit) {
+ printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
+ return NULL;
+ }
+
+ buf = (char *)malloc((size_t)size + 1);
+ p = *bits;
+ q = buf;
+ for(i=0; i<words; i++) {
+ val = bitToInt(p, 11);
+ ch = (int)(val / 45);
+ cl = (int)(val % 45);
+ sprintf(q, "%c%c", decodeAnTable[ch], decodeAnTable[cl]);
+ p += 11;
+ q += 2;
+ }
+ if(remain == 1) {
+ val = bitToInt(p, 6);
+ sprintf(q, "%c", decodeAnTable[val]);
+ }
+
+ chunk = DataChunk_new(QR_MODE_AN);
+ chunk->size = size;
+ chunk->data = (unsigned char *)buf;
+ *bits_length -= sizeInBit;
+ *bits += sizeInBit;
+
+ return chunk;
+}
+
+static DataChunk *decode8(int *bits_length, unsigned char **bits, int version, int mqr)
+{
+ int i;
+ int size, sizeInBit;
+ unsigned char *p;
+ unsigned char *buf, *q;
+ DataChunk *chunk;
+
+ size = decodeLength(bits_length, bits, QR_MODE_8, version, mqr);
+ if(size < 0) return NULL;
+
+ sizeInBit = size * 8;
+ if(*bits_length < sizeInBit) {
+ printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
+ return NULL;
+ }
+
+ buf = (unsigned char *)malloc((size_t)size);
+ p = *bits;
+ q = buf;
+ for(i=0; i<size; i++) {
+ *q = (unsigned char)bitToInt(p, 8);
+ p += 8;
+ q += 1;
+ }
+
+ chunk = DataChunk_new(QR_MODE_8);
+ chunk->size = size;
+ chunk->data = buf;
+ *bits_length -= sizeInBit;
+ *bits += sizeInBit;
+
+ return chunk;
+}
+
+static DataChunk *decodeKanji(int *bits_length, unsigned char **bits, int version, int mqr)
+{
+ int i;
+ int size, sizeInBit;
+ unsigned char *p;
+ char *buf, *q;
+ unsigned int val;
+ unsigned int ch, cl;
+ DataChunk *chunk;
+
+ size = decodeLength(bits_length, bits, QR_MODE_KANJI, version, mqr);
+ if(size < 0) return NULL;
+
+ sizeInBit = size * 13;
+ if(*bits_length < sizeInBit) {
+ printf("Bit length is too short: %d, expected %d.\n", *bits_length, sizeInBit);
+ return NULL;
+ }
+
+ buf = (char *)malloc((size_t)size * 2 + 1);
+ p = *bits;
+ q = buf;
+ for(i=0; i<size; i++) {
+ val = bitToInt(p, 13);
+ ch = val / 0xc0;
+ cl = val - ch * 0xc0;
+ val = ch * 256 + cl;
+ if(val >= 0x1f00) {
+ val += 0xc140;
+ } else {
+ val += 0x8140;
+ }
+ sprintf(q, "%c%c", (val>>8) & 0xff, val & 0xff);
+ p += 13;
+ q += 2;
+ }
+
+ chunk = DataChunk_new(QR_MODE_KANJI);
+ chunk->size = size * 2;
+ chunk->data = (unsigned char *)buf;
+ *bits_length -= sizeInBit;
+ *bits += sizeInBit;
+
+ return chunk;
+}
+
+static DataChunk *decodeChunk(int *bits_length, unsigned char **bits, int version)
+{
+ unsigned int val;
+
+ if(*bits_length < 4) {
+ return NULL;
+ }
+ val = bitToInt(*bits, 4);
+ *bits_length -= 4;
+ *bits += 4;
+ switch(val) {
+ case 0:
+ return NULL;
+ case 1:
+ return decodeNum(bits_length, bits, version, 0);
+ case 2:
+ return decodeAn(bits_length, bits, version, 0);
+ case 4:
+ return decode8(bits_length, bits, version, 0);
+ case 8:
+ return decodeKanji(bits_length, bits, version, 0);
+ default:
+ break;
+ }
+
+ printf("Invalid mode in a chunk: %d\n", val);
+
+ return NULL;
+}
+
+static DataChunk *decodeChunkMQR(int *bits_length, unsigned char **bits, int version)
+{
+ int modebits, termbits;
+ unsigned int val;
+
+ modebits = version - 1;
+ termbits = version * 2 + 1;
+ if(*bits_length >= termbits) {
+ val = bitToInt(*bits, termbits);
+ if(val == 0) {
+ *bits += termbits;
+ *bits_length -= termbits;
+ return NULL;
+ }
+ } else {
+ if(*bits_length < modebits) {
+ val = bitToInt(*bits, *bits_length);
+ } else {
+ val = bitToInt(*bits, modebits);
+ }
+ if(val == 0) {
+ return NULL;
+ } else {
+ printf("Terminating bits include 1-bit.\n");
+ return NULL;
+ }
+ }
+ val = bitToInt(*bits, modebits);
+ if(version == 4 && val > 3) {
+ printf("Invalid mode number %d.\n", val);
+ }
+ *bits_length -= modebits;
+ *bits += modebits;
+ switch(val) {
+ case 0:
+ return decodeNum(bits_length, bits, version, 1);
+ case 1:
+ return decodeAn(bits_length, bits, version, 1);
+ case 2:
+ return decode8(bits_length, bits, version, 1);
+ case 3:
+ return decodeKanji(bits_length, bits, version, 1);
+ default:
+ break;
+ }
+
+ printf("Invalid mode in a chunk: %d\n", val);
+
+ return NULL;
+}
+
+static int appendChunk(QRdata *qrdata, int *bits_length, unsigned char **bits)
+{
+ DataChunk *chunk;
+
+ if(qrdata->mqr) {
+ chunk = decodeChunkMQR(bits_length, bits, qrdata->version);
+ } else {
+ chunk = decodeChunk(bits_length, bits, qrdata->version);
+ }
+ if(chunk == NULL) {
+ return 1;
+ }
+
+ if(qrdata->last == NULL) {
+ qrdata->chunks = chunk;
+ } else {
+ qrdata->last->next = chunk;
+ }
+ qrdata->last = chunk;
+
+ return 0;
+}
+
+QRdata *QRdata_new(void)
+{
+ QRdata *qrdata;
+
+ qrdata = (QRdata *)calloc(sizeof(QRdata), 1);
+ if(qrdata == NULL) return NULL;
+
+ qrdata->eccResult = 0;
+
+ return qrdata;
+}
+
+QRdata *QRdata_newMQR(void)
+{
+ QRdata *qrdata;
+
+ qrdata = QRdata_new();
+ if(qrdata == NULL) return NULL;
+
+ qrdata->mqr = 1;
+
+ return qrdata;
+}
+
+void QRdata_free(QRdata *qrdata)
+{
+ DataChunk_freeList(qrdata->chunks);
+ if(qrdata->data != NULL) {
+ free(qrdata->data);
+ }
+ free(qrdata);
+}
+
+static int QRdata_decodeBits(QRdata *qrdata, int length, unsigned char *bits)
+{
+ int ret = 0;
+
+ while(ret == 0) {
+ ret = appendChunk(qrdata, &length, &bits);
+ }
+
+ return length;
+}
+
+int QRdata_decodeBitStream(QRdata *qrdata, BitStream *bstream)
+{
+ return QRdata_decodeBits(qrdata, bstream->length, bstream->data);
+}
+
+void QRdata_dump(QRdata *data)
+{
+ DataChunk_dumpChunkList(data->chunks);
+}
+
+int QRcode_decodeVersion(QRcode *code)
+{
+ unsigned int v1, v2;
+ int x, y, width;
+ unsigned char *p;
+
+ width = code->width;
+ if(width < 45) {
+ return (width - 21)/ 4 + 1;
+ }
+
+ v1 = 0;
+ p = code->data + width * (width - 9) + 5;
+ for(x=0; x<6; x++) {
+ for(y=0; y<3; y++) {
+ v1 = v1 << 1;
+ v1 |= *(p - y * width - x) & 1;
+ }
+ }
+
+ v2 = 0;
+ p = code->data + width * 5 + width - 9;
+ for(y=0; y<6; y++) {
+ for(x=0; x<3; x++) {
+ v2 = v2 << 1;
+ v2 |= *(p - y * width - x) & 1;
+ }
+ }
+
+ if(v1 != v2) {
+ printf("Two verion patterns are different.\n");
+ return -1;
+ }
+
+ return (int)(v1 >> 12);
+}
+
+int QRcode_decodeFormat(QRcode *code, QRecLevel *level, int *mask)
+{
+ unsigned int v1, v2;
+ int i, width;
+ unsigned char *p;
+
+ width = code->width;
+
+ v1 = 0;
+ p = code->data + width * 8;
+ for(i=0; i<8; i++) {
+ v1 = v1 << 1;
+ if(i < 6) {
+ v1 |= *(p + i) & 1;
+ } else {
+ v1 |= *(p + i + 1) & 1;
+ }
+ }
+ p = code->data + width * 7 + 8;
+ for(i=0; i<7; i++) {
+ v1 = v1 << 1;
+ if(i < 1) {
+ v1 |= *(p - width * i) & 1;
+ } else {
+ v1 |= *(p - width * (i + 1)) & 1;
+ }
+ }
+
+ v2 = 0;
+ p = code->data + width * (width - 1) + 8;
+ for(i=0; i<7; i++) {
+ v2 = v2 << 1;
+ v2 |= *(p - width * i) & 1;
+ }
+ p = code->data + width * 8 + width - 8;
+ for(i=0; i<8; i++) {
+ v2 = v2 << 1;
+ v2 |= *(p + i) & 1;
+ }
+
+ if(v1 != v2) {
+ printf("Two format infos are different.\n");
+ return -1;
+ }
+ v1 = (v1 ^ 0x5412) >> 10;
+ *mask = v1 & 7;
+ switch((v1 >> 3) & 3) {
+ case 1:
+ *level = QR_ECLEVEL_L;
+ break;
+ case 0:
+ *level = QR_ECLEVEL_M;
+ break;
+ case 3:
+ *level = QR_ECLEVEL_Q;
+ break;
+ case 2:
+ *level = QR_ECLEVEL_H;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static unsigned char *unmask(QRcode *code, QRecLevel level, int mask)
+{
+ unsigned char *unmasked;
+
+ unmasked = Mask_makeMask(code->width, code->data, mask, level);
+
+ return unmasked;
+}
+
+unsigned char *QRcode_unmask(QRcode *code)
+{
+ int ret, version, mask;
+ QRecLevel level;
+
+ version = QRcode_decodeVersion(code);
+ if(version < 1) return NULL;
+ ret = QRcode_decodeFormat(code, &level, &mask);
+ if(ret < 0) return NULL;
+
+ return unmask(code, level, mask);
+}
+
+typedef struct {
+ int width;
+ unsigned char *frame;
+ int x, y;
+ int dir;
+ int bit;
+ int mqr;
+} FrameFiller;
+
+static FrameFiller *FrameFiller_new(int width, unsigned char *frame, int mqr)
+{
+ FrameFiller *filler;
+
+ filler = (FrameFiller *)malloc(sizeof(FrameFiller));
+ if(filler == NULL) return NULL;
+ filler->width = width;
+ filler->frame = frame;
+ filler->x = width - 1;
+ filler->y = width - 1;
+ filler->dir = -1;
+ filler->bit = -1;
+ filler->mqr = mqr;
+
+ return filler;
+}
+
+static unsigned char *FrameFiller_next(FrameFiller *filler)
+{
+ unsigned char *p;
+ int x, y, w;
+
+ if(filler->bit == -1) {
+ filler->bit = 0;
+ return filler->frame + filler->y * filler->width + filler->x;
+ }
+
+ x = filler->x;
+ y = filler->y;
+ p = filler->frame;
+ w = filler->width;
+
+ if(filler->bit == 0) {
+ x--;
+ filler->bit++;
+ } else {
+ x++;
+ y += filler->dir;
+ filler->bit--;
+ }
+
+ if(filler->dir < 0) {
+ if(y < 0) {
+ y = 0;
+ x -= 2;
+ filler->dir = 1;
+ if(!filler->mqr && x == 6) {
+ x--;
+ y = 9;
+ }
+ }
+ } else {
+ if(y == w) {
+ y = w - 1;
+ x -= 2;
+ filler->dir = -1;
+ if(!filler->mqr && x == 6) {
+ x--;
+ y -= 8;
+ }
+ }
+ }
+ if(x < 0 || y < 0) return NULL;
+
+ filler->x = x;
+ filler->y = y;
+
+ if(p[y * w + x] & 0x80) {
+ // This tail recursion could be optimized.
+ return FrameFiller_next(filler);
+ }
+ return &p[y * w + x];
+}
+
+static BitStream *extractBits(int width, unsigned char *frame, int spec[5])
+{
+ BitStream *bstream;
+ unsigned char *bits, *p, *q;
+ FrameFiller *filler;
+ int i, j;
+ int col, row, d1, b1, blocks, idx, words;
+
+ blocks = QRspec_rsBlockNum(spec);
+ words = QRspec_rsDataLength(spec);
+ d1 = QRspec_rsDataCodes1(spec);
+ b1 = QRspec_rsBlockNum1(spec);
+ bits = (unsigned char *)malloc((size_t)words * 8);
+ /*
+ * 00 01 02 03 04 05 06 07 08 09
+ * 10 11 12 13 14 15 16 17 18 19
+ * 20 21 22 23 24 25 26 27 28 29 30
+ * 31 32 33 34 35 36 37 38 39 40 41
+ * 42 43 44 45 46 47 48 49 50 51 52
+ */
+
+ row = col = 0;
+ filler = FrameFiller_new(width, frame, 0);
+ for(i=0; i<words; i++) {
+ col = i / blocks;
+ row = i % blocks + ((col >= d1)?b1:0);
+ idx = d1 * row + col + ((row > b1)?(row-b1):0);
+ q = bits + idx * 8;
+ for(j=0; j<8; j++) {
+ p = FrameFiller_next(filler);
+ q[j] = *p & 1;
+ }
+ }
+ free(filler);
+
+ bstream = BitStream_newWithBits((size_t)words * 8, bits);
+ free(bits);
+
+ return bstream;
+}
+
+BitStream *QRcode_extractBits(QRcode *code, int *dataLength, int *eccLength)
+{
+ BitStream *bstream;
+ unsigned char *unmasked;
+ int spec[5];
+ int ret, version, mask;
+ QRecLevel level;
+
+ version = QRcode_decodeVersion(code);
+ if(version < 1) return NULL;
+ ret = QRcode_decodeFormat(code, &level, &mask);
+ if(ret < 0) return NULL;
+
+ QRspec_getEccSpec(version, level, spec);
+
+ unmasked = unmask(code, level, mask);
+ if(unmasked == NULL) return NULL;
+
+ bstream = extractBits(code->width, unmasked, spec);
+ free(unmasked);
+
+ *dataLength = QRspec_rsDataLength(spec) * 8;
+ *eccLength = QRspec_rsEccLength(spec) * 8;
+
+ return bstream;
+}
+
+static int checkRemainderWords(int length, unsigned char *bits, int remainder)
+{
+ int rbits, words;
+ unsigned char *p, v;
+ int i;
+
+ words = remainder / 8;
+ rbits = remainder - words * 8;
+ bits += (length - remainder);
+ for(i=0; i<rbits; i++) {
+ if((bits[i]&1) != 0) {
+ printf("Terminating code includes 1-bit.\n");
+ printBinary(bits, remainder);
+ return -1;
+ }
+ }
+ p = bits + rbits;
+ for(i=0; i<words; i++) {
+ v = (unsigned char)bitToInt(p, 8);
+ if(v != ((i&1)?0x11:0xec)) {
+ printf("Remainder codewords wrong.\n");
+ printBinary(bits, remainder);
+ return -1;
+ }
+ p += 8;
+ }
+
+ return 0;
+}
+
+QRdata *QRcode_decodeBits(QRcode *code)
+{
+ BitStream *bstream;
+ unsigned char *unmasked;
+ int spec[5];
+ int ret, version, mask;
+ int length;
+ QRecLevel level;
+ QRdata *qrdata;
+
+ version = QRcode_decodeVersion(code);
+ if(version < 1) return NULL;
+ ret = QRcode_decodeFormat(code, &level, &mask);
+ if(ret < 0) return NULL;
+
+ QRspec_getEccSpec(version, level, spec);
+ length = QRspec_rsDataLength(spec) * 8;
+
+ unmasked = unmask(code, level, mask);
+ if(unmasked == NULL) return NULL;
+
+ bstream = extractBits(code->width, unmasked, spec);
+ free(unmasked);
+
+ qrdata = QRdata_new();
+ qrdata->version = version;
+ qrdata->level = level;
+ ret = QRdata_decodeBitStream(qrdata, bstream);
+ if(ret > 0) {
+ checkRemainderWords(length, bstream->data, ret);
+ }
+
+ BitStream_free(bstream);
+
+ return qrdata;
+}
+
+void QRdata_concatChunks(QRdata *qrdata)
+{
+ qrdata->data = DataChunk_concatChunkList(qrdata->chunks, &qrdata->size);
+}
+
+QRdata *QRcode_decode(QRcode *code)
+{
+ QRdata *qrdata;
+
+ qrdata = QRcode_decodeBits(code);
+ QRdata_concatChunks(qrdata);
+
+ return qrdata;
+}
+
+/*
+ * Micro QR Code decoder
+ */
+
+struct FormatInfo MQRformat[] = {
+ {1, QR_ECLEVEL_L},
+ {2, QR_ECLEVEL_L},
+ {2, QR_ECLEVEL_M},
+ {3, QR_ECLEVEL_L},
+ {3, QR_ECLEVEL_M},
+ {4, QR_ECLEVEL_L},
+ {4, QR_ECLEVEL_M},
+ {4, QR_ECLEVEL_Q}
+};
+
+int QRcode_decodeFormatMQR(QRcode *code, int *version, QRecLevel *level, int *mask)
+{
+ unsigned int v, t;
+ int i, width;
+ unsigned char *p;
+
+ width = code->width;
+
+ v = 0;
+ p = code->data + width * 8 + 1;
+ for(i=0; i<8; i++) {
+ v = v << 1;
+ v |= p[i] & 1;
+ }
+ p = code->data + width * 7 + 8;
+ for(i=0; i<7; i++) {
+ v = v << 1;
+ v |= *(p - width * i) & 1;
+ }
+ v ^= 0x4445;
+ *mask = (v >> 10) & 3;
+ t = (v >> 12) & 7;
+ *version = MQRformat[t].version;
+ *level = MQRformat[t].level;
+ if(*version * 2 + 9 != width) {
+ printf("Decoded version number does not match to the size.\n");
+ return -1;
+ }
+ return 0;
+}
+
+static unsigned char *unmaskMQR(QRcode *code, QRecLevel level, int mask)
+{
+ unsigned char *unmasked;
+
+ unmasked = MMask_makeMask(code->version, code->data, mask, level);
+
+ return unmasked;
+}
+
+unsigned char *QRcode_unmaskMQR(QRcode *code)
+{
+ int ret, version, mask;
+ QRecLevel level;
+
+ ret = QRcode_decodeFormatMQR(code, &version, &level, &mask);
+ if(ret < 0) return NULL;
+
+ return unmaskMQR(code, level, mask);
+}
+
+static BitStream *extractBitsMQR(int width, unsigned char *frame, int version, QRecLevel level)
+{
+ BitStream *bstream;
+ unsigned char *bits;
+ FrameFiller *filler;
+ int i;
+ int size;
+
+ size = MQRspec_getDataLengthBit(version, level) + MQRspec_getECCLength(version, level) * 8;
+ bits = (unsigned char *)malloc((size_t)size);
+ filler = FrameFiller_new(width, frame, 1);
+ for(i=0; i<size; i++) {
+ bits[i] = *(FrameFiller_next(filler)) & 1;
+ }
+ free(filler);
+
+ bstream = BitStream_newWithBits((size_t)size, bits);
+ free(bits);
+
+ return bstream;
+}
+
+BitStream *QRcode_extractBitsMQR(QRcode *code, int *dataLength, int *eccLength, int *version, QRecLevel *level)
+{
+ BitStream *bstream;
+ unsigned char *unmasked;
+ int ret, mask;
+
+ ret = QRcode_decodeFormatMQR(code, version, level, &mask);
+ if(ret < 0) return NULL;
+
+ unmasked = unmaskMQR(code, *level, mask);
+ if(unmasked == NULL) return NULL;
+
+ *dataLength = MQRspec_getDataLengthBit(*version, *level);
+ *eccLength = MQRspec_getECCLength(*version, *level) * 8;
+ bstream = extractBitsMQR(code->width, unmasked, *version, *level);
+ free(unmasked);
+
+ return bstream;
+}
+
+static int checkRemainderWordsMQR(int length, unsigned char *bits, int remainder, int version)
+{
+ int rbits, words, paddings;
+ unsigned char *p, v;
+ int i, decoded;
+
+ decoded = length - remainder;
+ bits += decoded;
+ words = (decoded + 7) / 8;
+ rbits = words * 8 - decoded;
+ for(i=0; i<rbits; i++) {
+ if((bits[i]&1) != 0) {
+ printf("Terminating code includes 1-bit.\n");
+ printBinary(bits, remainder);
+ return -1;
+ }
+ }
+
+ paddings = (length - words * 8) / 8;
+ p = bits + rbits;
+ for(i=0; i<paddings; i++) {
+ v = (unsigned char)bitToInt(p, 8);
+ if(v != ((i&1)?0x11:0xec)) {
+ printf("Remainder codewords wrong.\n");
+ printBinary(bits, remainder);
+ return -1;
+ }
+ p += 8;
+ }
+ rbits = length - (paddings + words)* 8;
+ if(rbits > 0) {
+ if((version == 1 || version == 3) && rbits == 4) {
+ v = (unsigned char)bitToInt(p, 4);
+ if(v != 0) {
+ printf("Last padding bits include 1-bit.\n");
+ return -1;
+ }
+ } else {
+ printf("The length of the last padding bits is %d, not %d.\n", rbits, (version == 1 || version == 3)?4:0);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+QRdata *QRcode_decodeBitsMQR(QRcode *code)
+{
+ BitStream *bstream;
+ int ret, version, dataLength, eccLength;
+ QRecLevel level;
+ QRdata *qrdata;
+
+ bstream = QRcode_extractBitsMQR(code, &dataLength, &eccLength, &version, &level);
+ if(bstream == NULL) {
+ return NULL;
+ }
+
+ qrdata = QRdata_newMQR();
+ qrdata->version = version;
+ qrdata->level = level;
+ ret = QRdata_decodeBits(qrdata, dataLength, bstream->data);
+ if(ret > 0) {
+ ret = checkRemainderWordsMQR(dataLength, bstream->data, ret, version);
+ if(ret < 0) {
+ QRdata_free(qrdata);
+ qrdata = NULL;
+ }
+ }
+
+ BitStream_free(bstream);
+
+ return qrdata;
+}
+
+QRdata *QRcode_decodeMQR(QRcode *code)
+{
+ QRdata *qrdata;
+ qrdata = QRcode_decodeBitsMQR(code);
+ if(qrdata != NULL) {
+ QRdata_concatChunks(qrdata);
+ }
+
+ return qrdata;
+}
diff --git a/genqrcode/tests/decoder.h b/genqrcode/tests/decoder.h
new file mode 100644
index 0000000000..087ec6f108
--- /dev/null
+++ b/genqrcode/tests/decoder.h
@@ -0,0 +1,43 @@
+#ifndef DECODER_H
+#define DECODER_H
+
+#include "../qrencode.h"
+#include "datachunk.h"
+
+typedef struct {
+ unsigned char *data;
+ int size;
+ int mqr;
+ int version;
+ QRecLevel level;
+ DataChunk *chunks, *last;
+ int eccResult;
+} QRdata;
+
+struct FormatInfo {
+ int version;
+ QRecLevel level;
+};
+
+extern struct FormatInfo MQRformat[];
+
+QRdata *QRdata_new(void);
+QRdata *QRdata_newMQR(void);
+int QRdata_decodeBitStream(QRdata *qrdata, BitStream *bstream);
+void QRdata_dump(QRdata *data);
+void QRdata_free(QRdata *data);
+
+int QRcode_decodeVersion(QRcode *code);
+int QRcode_decodeFormat(QRcode *code, QRecLevel *level, int *mask);
+unsigned char *QRcode_unmask(QRcode *code);
+BitStream *QRcode_extractBits(QRcode *code, int *dataLength, int *eccLength);
+QRdata *QRcode_decodeBits(QRcode *code);
+QRdata *QRcode_decode(QRcode *code);
+
+int QRcode_decodeFormatMQR(QRcode *code, int *vesion, QRecLevel *level, int *mask);
+unsigned char *QRcode_unmaskMQR(QRcode *code);
+BitStream *QRcode_extractBitsMQR(QRcode *code, int *dataLength, int *eccLength, int *version, QRecLevel *level);
+QRdata *QRcode_decodeBitsMQR(QRcode *code);
+QRdata *QRcode_decodeMQR(QRcode *code);
+
+#endif /* DECODER_H */
diff --git a/genqrcode/tests/frame b/genqrcode/tests/frame
new file mode 100644
index 0000000000..fda4eaaa8a
--- /dev/null
+++ b/genqrcode/tests/frame
Binary files differ
diff --git a/genqrcode/tests/prof_qrencode.c b/genqrcode/tests/prof_qrencode.c
new file mode 100644
index 0000000000..8aa9a98b95
--- /dev/null
+++ b/genqrcode/tests/prof_qrencode.c
@@ -0,0 +1,102 @@
+#include <stdio.h>
+#include <stdlib.h>
+#if HAVE_CONFIG_H
+#include "../config.h"
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <errno.h>
+#include "../qrencode.h"
+
+#ifdef _MSC_VER
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+static LARGE_INTEGER startTime;
+static LARGE_INTEGER frequency = { .QuadPart = 0 };
+#else
+static struct timeval tv;
+#endif
+
+static void timerStart(const char *str)
+{
+ printf("%s: START\n", str);
+#ifdef _MSC_VER
+ (void) QueryPerformanceCounter(&startTime);
+#else
+ gettimeofday(&tv, NULL);
+#endif
+}
+
+static void timerStop(void)
+{
+#ifdef _MSC_VER
+ LARGE_INTEGER endTime, elapsed;
+ (void) QueryPerformanceCounter(&endTime);
+ if (frequency.QuadPart == 0) {
+ (void) QueryPerformanceFrequency(&frequency);
+ }
+
+ elapsed.QuadPart = endTime.QuadPart - startTime.QuadPart;
+ elapsed.QuadPart *= 1000;
+ elapsed.QuadPart /= frequency.QuadPart;
+
+ printf("STOP: %lld msec\n", elapsed.QuadPart);
+#else
+ struct timeval tc;
+
+ gettimeofday(&tc, NULL);
+ printf("STOP: %ld msec\n", (tc.tv_sec - tv.tv_sec) * 1000
+ + (tc.tv_usec - tv.tv_usec) / 1000);
+#endif
+}
+
+static void prof_ver1to10(void)
+{
+ QRcode *code;
+ int i;
+ int version;
+ static const char *data = "This is test.";
+
+ timerStart("Version 1 - 10 (5000 symbols for each)");
+ for(i=0; i<5000; i++) {
+ for(version = 0; version < 11; version++) {
+ code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0);
+ if(code == NULL) {
+ perror("Failed to encode:");
+ } else {
+ QRcode_free(code);
+ }
+ }
+ }
+ timerStop();
+}
+
+static void prof_ver31to40(void)
+{
+ QRcode *code;
+ int i;
+ int version;
+ static const char *data = "This is test.";
+
+ timerStart("Version 31 - 40 (500 symbols for each)");
+ for(i=0; i<500; i++) {
+ for(version = 31; version < 41; version++) {
+ code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0);
+ if(code == NULL) {
+ perror("Failed to encode:");
+ } else {
+ QRcode_free(code);
+ }
+ }
+ }
+ timerStop();
+}
+
+int main()
+{
+ prof_ver1to10();
+ prof_ver31to40();
+
+ return 0;
+}
diff --git a/genqrcode/tests/pthread_qrencode.c b/genqrcode/tests/pthread_qrencode.c
new file mode 100644
index 0000000000..a450e59aa4
--- /dev/null
+++ b/genqrcode/tests/pthread_qrencode.c
@@ -0,0 +1,135 @@
+#include <stdio.h>
+#include <stdlib.h>
+#if HAVE_CONFIG_H
+#include "../config.h"
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <pthread.h>
+#include <errno.h>
+#include "../qrencode.h"
+
+#define THREADS (10)
+
+static pthread_t threads[THREADS];
+
+#ifdef _MSC_VER
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+static LARGE_INTEGER startTime;
+static LARGE_INTEGER frequency = { .QuadPart = 0 };
+#else
+static struct timeval tv;
+#endif
+
+static void timerStart(const char *str)
+{
+ printf("%s: START\n", str);
+#ifdef _MSC_VER
+ (void) QueryPerformanceCounter(&startTime);
+#else
+ gettimeofday(&tv, NULL);
+#endif
+}
+
+static void timerStop(void)
+{
+#ifdef _MSC_VER
+ LARGE_INTEGER endTime, elapsed;
+ (void) QueryPerformanceCounter(&endTime);
+ if (frequency.QuadPart == 0) {
+ (void) QueryPerformanceFrequency(&frequency);
+ }
+
+ elapsed.QuadPart = endTime.QuadPart - startTime.QuadPart;
+ elapsed.QuadPart *= 1000;
+ elapsed.QuadPart /= frequency.QuadPart;
+
+ printf("STOP: %lld msec\n", elapsed.QuadPart);
+#else
+ struct timeval tc;
+
+ gettimeofday(&tc, NULL);
+ printf("STOP: %ld msec\n", (tc.tv_sec - tv.tv_sec) * 1000
+ + (tc.tv_usec - tv.tv_usec) / 1000);
+#endif
+}
+
+static void *encode_ver1to10(void *arg)
+{
+ QRcode *code;
+ int i;
+ int version;
+ static const char *data = "This is test.";
+
+ for(i=0; i<500; i++) {
+ for(version = 0; version < 11; version++) {
+ code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0);
+ if(code == NULL) {
+ perror("Failed to encode:");
+ } else {
+ QRcode_free(code);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void prof_ver1to10(void)
+{
+ int i;
+
+ timerStart("Version 1 - 10 (500 symbols for each)");
+ for(i=0; i<THREADS; i++) {
+ pthread_create(&threads[i], NULL, encode_ver1to10, NULL);
+ }
+ for(i=0; i<THREADS; i++) {
+ pthread_join(threads[i], NULL);
+ }
+ timerStop();
+}
+
+static void *encode_ver31to40(void *arg)
+{
+ QRcode *code;
+ int i;
+ int version;
+ static const char *data = "This is test.";
+
+ for(i=0; i<50; i++) {
+ for(version = 31; version < 41; version++) {
+ code = QRcode_encodeString(data, version, QR_ECLEVEL_L, QR_MODE_8, 0);
+ if(code == NULL) {
+ perror("Failed to encode:");
+ } else {
+ QRcode_free(code);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static void prof_ver31to40(void)
+{
+ int i;
+
+ timerStart("Version 31 - 40 (50 symbols for each)");
+ for(i=0; i<THREADS; i++) {
+ pthread_create(&threads[i], NULL, encode_ver31to40, NULL);
+ }
+ for(i=0; i<THREADS; i++) {
+ pthread_join(threads[i], NULL);
+ }
+ timerStop();
+}
+
+int main()
+{
+ prof_ver1to10();
+ prof_ver31to40();
+
+ return 0;
+}
diff --git a/genqrcode/tests/release_check.sh b/genqrcode/tests/release_check.sh
new file mode 100755
index 0000000000..8c52f07e04
--- /dev/null
+++ b/genqrcode/tests/release_check.sh
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+# check version numbers between configure.ac and CMakeLists.txt.
+
+Configure_major_version=`sed -e '1{s/^.*\[\([0-9]\+\)\].*$/\1/};1!d' ../configure.ac`
+Configure_minor_version=`sed -e '2{s/^.*\[\([0-9]\+\)\].*$/\1/};2!d' ../configure.ac`
+Configure_micro_version=`sed -e '3{s/^.*\[\([0-9]\+\)\].*$/\1/};3!d' ../configure.ac`
+
+Configure_version_string="$Configure_major_version.$Configure_minor_version.$Configure_micro_version"
+
+Cmake_version_string=`grep project ../CMakeLists.txt | sed 's/^.*VERSION \([^ ]\+\) .*$/\1/'`
+
+if [ "$Configure_version_string" != "$Cmake_version_string" ]; then
+ echo "ERROR: Version number defined in configure.ac is not equal to the number defined in CMakeLists.txt."
+ echo "configure.ac: $Configure_version_string"
+ echo "CMakeLists.txt: $Cmake_version_string"
+fi
+
+NEWS_version_string=`grep -m 1 Version ../NEWS | sed 's/^Version \([^ ]\+\) (.*$/\1/'`
+
+if [ "$Configure_version_string" != "$NEWS_version_string" ]; then
+ echo "ERROR: Version number defined in configure.ac is not equal to the newest number described in NEWS."
+ echo "configure.ac: $Configure_version_string"
+ echo "NEWS: $NEWS_version_string"
+fi
+
+README_version_string=`grep -m 1 Attention ../README.md | sed 's/^.*version \([^ ]\+\)\.$/\1/'`
+
+if [ "$Configure_version_string" != "$README_version_string" ]; then
+ echo "ERROR: Version number defined in configure.ac is not equal to the newest number described in README.md."
+ echo "configure.ac: $Configure_version_string"
+ echo "README.md: $README_version_string"
+fi
diff --git a/genqrcode/tests/rscode.c b/genqrcode/tests/rscode.c
new file mode 100644
index 0000000000..2d4c47e15a
--- /dev/null
+++ b/genqrcode/tests/rscode.c
@@ -0,0 +1,274 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Reed solomon encoder. This code is taken from Phil Karn's libfec then
+ * editted and packed into a pair of .c and .h files.
+ *
+ * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
+ * (libfec is released under the GNU Lesser General Public License.)
+ *
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "rscode.h"
+
+/* Stuff specific to the 8-bit symbol version of the general purpose RS codecs
+ *
+ */
+typedef unsigned char data_t;
+
+
+/**
+ * Reed-Solomon codec control block
+ */
+struct _RS {
+ int mm; /* Bits per symbol */
+ int nn; /* Symbols per block (= (1<<mm)-1) */
+ data_t *alpha_to; /* log lookup table */
+ data_t *index_of; /* Antilog lookup table */
+ data_t *genpoly; /* Generator polynomial */
+ int nroots; /* Number of generator roots = number of parity symbols */
+ int fcr; /* First consecutive root, index form */
+ int prim; /* Primitive element, index form */
+ int iprim; /* prim-th root of 1, index form */
+ int pad; /* Padding bytes in shortened block */
+ int gfpoly;
+};
+
+static inline int modnn(RS *rs, int x){
+ while (x >= rs->nn) {
+ x -= rs->nn;
+ x = (x >> rs->mm) + (x & rs->nn);
+ }
+ return x;
+}
+
+
+#define MODNN(x) modnn(rs,x)
+
+#define MM (rs->mm)
+#define NN (rs->nn)
+#define ALPHA_TO (rs->alpha_to)
+#define INDEX_OF (rs->index_of)
+#define GENPOLY (rs->genpoly)
+#define NROOTS (rs->nroots)
+#define FCR (rs->fcr)
+#define PRIM (rs->prim)
+#define IPRIM (rs->iprim)
+#define PAD (rs->pad)
+#define A0 (NN)
+
+
+/* Initialize a Reed-Solomon codec
+ * symsize = symbol size, bits
+ * gfpoly = Field generator polynomial coefficients
+ * fcr = first root of RS code generator polynomial, index form
+ * prim = primitive element to generate polynomial roots
+ * nroots = RS code generator polynomial degree (number of roots)
+ * pad = padding bytes at front of shortened block
+ */
+static RS *init_rs_char(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad)
+{
+ RS *rs;
+
+
+/* Common code for intializing a Reed-Solomon control block (char or int symbols)
+ * Copyright 2004 Phil Karn, KA9Q
+ * May be used under the terms of the GNU Lesser General Public License (LGPL)
+ */
+//#undef NULL
+//#define NULL ((void *)0)
+
+ int i, j, sr,root,iprim;
+
+ rs = NULL;
+ /* Check parameter ranges */
+ if(symsize < 0 || symsize > (int)(8*sizeof(data_t))){
+ goto done;
+ }
+
+ if(fcr < 0 || fcr >= (1<<symsize))
+ goto done;
+ if(prim <= 0 || prim >= (1<<symsize))
+ goto done;
+ if(nroots < 0 || nroots >= (1<<symsize))
+ goto done; /* Can't have more roots than symbol values! */
+ if(pad < 0 || pad >= ((1<<symsize) -1 - nroots))
+ goto done; /* Too much padding */
+
+ rs = (RS *)calloc(1,sizeof(RS));
+ if(rs == NULL)
+ goto done;
+
+ rs->mm = symsize;
+ rs->nn = (1<<symsize)-1;
+ rs->pad = pad;
+
+ rs->alpha_to = (data_t *)malloc(sizeof(data_t)*(rs->nn+1));
+ if(rs->alpha_to == NULL){
+ free(rs);
+ rs = NULL;
+ goto done;
+ }
+ rs->index_of = (data_t *)malloc(sizeof(data_t)*(rs->nn+1));
+ if(rs->index_of == NULL){
+ free(rs->alpha_to);
+ free(rs);
+ rs = NULL;
+ goto done;
+ }
+
+ /* Generate Galois field lookup tables */
+ rs->index_of[0] = A0; /* log(zero) = -inf */
+ rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */
+ sr = 1;
+ for(i=0;i<rs->nn;i++){
+ rs->index_of[sr] = i;
+ rs->alpha_to[i] = sr;
+ sr <<= 1;
+ if(sr & (1<<symsize))
+ sr ^= gfpoly;
+ sr &= rs->nn;
+ }
+ if(sr != 1){
+ /* field generator polynomial is not primitive! */
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs);
+ rs = NULL;
+ goto done;
+ }
+
+ /* Form RS code generator polynomial from its roots */
+ rs->genpoly = (data_t *)malloc(sizeof(data_t)*(nroots+1));
+ if(rs->genpoly == NULL){
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs);
+ rs = NULL;
+ goto done;
+ }
+ rs->fcr = fcr;
+ rs->prim = prim;
+ rs->nroots = nroots;
+ rs->gfpoly = gfpoly;
+
+ /* Find prim-th root of 1, used in decoding */
+ for(iprim=1;(iprim % prim) != 0;iprim += rs->nn)
+ ;
+ rs->iprim = iprim / prim;
+
+ rs->genpoly[0] = 1;
+ for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) {
+ rs->genpoly[i+1] = 1;
+
+ /* Multiply rs->genpoly[] by @**(root + x) */
+ for (j = i; j > 0; j--){
+ if (rs->genpoly[j] != 0)
+ rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)];
+ else
+ rs->genpoly[j] = rs->genpoly[j-1];
+ }
+ /* rs->genpoly[0] can never be zero */
+ rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)];
+ }
+ /* convert rs->genpoly[] to index form for quicker encoding */
+ for (i = 0; i <= nroots; i++)
+ rs->genpoly[i] = rs->index_of[rs->genpoly[i]];
+ done:;
+
+ return rs;
+}
+
+RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad)
+{
+ return init_rs_char(symsize, gfpoly, fcr, prim, nroots, pad);
+}
+
+
+void free_rs_char(RS *rs)
+{
+ free(rs->alpha_to);
+ free(rs->index_of);
+ free(rs->genpoly);
+ free(rs);
+}
+
+/* The guts of the Reed-Solomon encoder, meant to be #included
+ * into a function body with the following typedefs, macros and variables supplied
+ * according to the code parameters:
+
+ * data_t - a typedef for the data symbol
+ * data_t data[] - array of NN-NROOTS-PAD and type data_t to be encoded
+ * data_t parity[] - an array of NROOTS and type data_t to be written with parity symbols
+ * NROOTS - the number of roots in the RS code generator polynomial,
+ * which is the same as the number of parity symbols in a block.
+ Integer variable or literal.
+ *
+ * NN - the total number of symbols in a RS block. Integer variable or literal.
+ * PAD - the number of pad symbols in a block. Integer variable or literal.
+ * ALPHA_TO - The address of an array of NN elements to convert Galois field
+ * elements in index (log) form to polynomial form. Read only.
+ * INDEX_OF - The address of an array of NN elements to convert Galois field
+ * elements in polynomial form to index (log) form. Read only.
+ * MODNN - a function to reduce its argument modulo NN. May be inline or a macro.
+ * GENPOLY - an array of NROOTS+1 elements containing the generator polynomial in index form
+
+ * The memset() and memmove() functions are used. The appropriate header
+ * file declaring these functions (usually <string.h>) must be included by the calling
+ * program.
+
+ * Copyright 2004, Phil Karn, KA9Q
+ * May be used under the terms of the GNU Lesser General Public License (LGPL)
+ */
+
+#undef A0
+#define A0 (NN) /* Special reserved value encoding zero in index form */
+
+void encode_rs_char(RS *rs, const data_t *data, data_t *parity)
+{
+ int i, j;
+ data_t feedback;
+
+ memset(parity,0,NROOTS*sizeof(data_t));
+
+ for(i=0;i<NN-NROOTS-PAD;i++){
+ feedback = INDEX_OF[data[i] ^ parity[0]];
+ if(feedback != A0){ /* feedback term is non-zero */
+#ifdef UNNORMALIZED
+ /* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
+ * always be for the polynomials constructed by init_rs()
+ */
+ feedback = MODNN(NN - GENPOLY[NROOTS] + feedback);
+#endif
+ for(j=1;j<NROOTS;j++)
+ parity[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])];
+ }
+ /* Shift */
+ memmove(&parity[0],&parity[1],sizeof(data_t)*(NROOTS-1));
+ if(feedback != A0)
+ parity[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])];
+ else
+ parity[NROOTS-1] = 0;
+ }
+}
diff --git a/genqrcode/tests/rscode.h b/genqrcode/tests/rscode.h
new file mode 100644
index 0000000000..d4a07c9bae
--- /dev/null
+++ b/genqrcode/tests/rscode.h
@@ -0,0 +1,40 @@
+/*
+ * qrencode - QR Code encoder
+ *
+ * Reed solomon encoder. This code is taken from Phil Karn's libfec then
+ * editted and packed into a pair of .c and .h files.
+ *
+ * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
+ * (libfec is released under the GNU Lesser General Public License.)
+ *
+ * Copyright (C) 2006-2011 Kentaro Fukuchi <kentaro@fukuchi.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef RSCODE_H
+#define RSCODE_H
+
+/*
+ * General purpose RS codec, 8-bit symbols.
+ */
+
+typedef struct _RS RS;
+
+extern RS *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots, int pad);
+extern void encode_rs_char(RS *rs, const unsigned char *data, unsigned char *parity);
+extern void free_rs_char(RS *rs);
+
+#endif /* RSCODE_H */
diff --git a/genqrcode/tests/rsecc_decoder.c b/genqrcode/tests/rsecc_decoder.c
new file mode 100644
index 0000000000..982742142b
--- /dev/null
+++ b/genqrcode/tests/rsecc_decoder.c
@@ -0,0 +1,64 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../qrspec.h"
+#include "rsecc_decoder.h"
+
+#define SYMBOL_SIZE (8)
+#define symbols ((1 << SYMBOL_SIZE) - 1)
+static const int proot = 0x11d; /* stands for x^8+x^4+x^3+x^2+1 (see pp.37 of JIS X0510:2004) */
+
+/* min/max codeword length of ECC, calculated from the specification. */
+#define min_length (2)
+#define max_length (30)
+#define max_generatorSize (max_length)
+
+static unsigned char alpha[symbols + 1];
+static unsigned char aindex[symbols + 1];
+
+void RSECC_decoder_init() {
+ int i, b;
+
+ alpha[symbols] = 0;
+ aindex[0] = symbols;
+
+ b = 1;
+ for(i = 0; i < symbols; i++) {
+ alpha[i] = (unsigned char)b;
+ aindex[b] = (unsigned char)i;
+ b <<= 1;
+ if(b & (symbols + 1)) {
+ b ^= proot;
+ }
+ b &= symbols;
+ }
+}
+
+int RSECC_decoder_checkSyndrome(int dl, unsigned char *data, int el, unsigned char *ecc)
+{
+ int i, j;
+ int s;
+
+ for(i=0; i<el; i++) {
+ s = data[0];
+ for(j=1; j<dl; j++) {
+ if(s == 0) {
+ s = data[j];
+ } else {
+ s = data[j] ^ alpha[(aindex[s] + i) % symbols];
+ }
+ }
+ for(j=0; j<el; j++) {
+ if(s == 0) {
+ s = ecc[j];
+ } else {
+ s = ecc[j] ^ alpha[(aindex[s] + i) % symbols];
+ }
+ }
+ if(s != 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/genqrcode/tests/rsecc_decoder.h b/genqrcode/tests/rsecc_decoder.h
new file mode 100644
index 0000000000..6390433872
--- /dev/null
+++ b/genqrcode/tests/rsecc_decoder.h
@@ -0,0 +1,7 @@
+#ifndef RSECC_DECODER_H
+#define RSECC_DECODER_H
+
+void RSECC_decoder_init(void);
+int RSECC_decoder_checkSyndrome(int dl, unsigned char *data, int el, unsigned char *ecc);
+
+#endif /* RSECC_DECODER_H */
diff --git a/genqrcode/tests/test_all.sh b/genqrcode/tests/test_all.sh
new file mode 100755
index 0000000000..9ba040ae77
--- /dev/null
+++ b/genqrcode/tests/test_all.sh
@@ -0,0 +1,3 @@
+#!/bin/sh -e
+. ./test_basic.sh
+./test_configure.sh
diff --git a/genqrcode/tests/test_basic.sh b/genqrcode/tests/test_basic.sh
new file mode 100755
index 0000000000..6d90180ee3
--- /dev/null
+++ b/genqrcode/tests/test_basic.sh
@@ -0,0 +1,13 @@
+#!/bin/sh -e
+./test_bitstream
+./test_estimatebit
+./test_qrencode
+./test_qrinput
+./test_qrspec
+./test_rs
+./test_split
+./test_split_urls
+./test_mask
+./test_mqrspec
+./test_mmask
+./test_monkey
diff --git a/genqrcode/tests/test_bitstream.c b/genqrcode/tests/test_bitstream.c
new file mode 100644
index 0000000000..64b1e86d92
--- /dev/null
+++ b/genqrcode/tests/test_bitstream.c
@@ -0,0 +1,257 @@
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+#include "../bitstream.h"
+
+static void test_null(void)
+{
+ BitStream *bstream;
+
+ testStart("Empty stream");
+ bstream = BitStream_new();
+ assert_zero(BitStream_size(bstream), "Size of empty BitStream is not 0.\n");
+ assert_null(BitStream_toByte(bstream), "BitStream_toByte returned non-NULL.\n");
+ assert_nothing(BitStream_free(NULL), "Checking BitStream_free(NULL).\n");
+ testFinish();
+
+ BitStream_free(bstream);
+}
+
+static void test_num(void)
+{
+ BitStream *bstream;
+ unsigned int data = 0x13579bdf;
+ char correct[] = "0010011010101111001101111011111";
+
+ testStart("New from num");
+ bstream = BitStream_new();
+ BitStream_appendNum(bstream, 31, data);
+ testEnd(cmpBin(correct, bstream));
+
+ BitStream_free(bstream);
+}
+
+static void test_bytes(void)
+{
+ BitStream *bstream;
+ unsigned char data[1] = {0x3a};
+ char correct[] = "00111010";
+
+ testStart("New from bytes");
+ bstream = BitStream_new();
+ BitStream_appendBytes(bstream, 1, data);
+ testEnd(cmpBin(correct, bstream));
+ BitStream_free(bstream);
+}
+
+static void test_appendNum(void)
+{
+ BitStream *bstream;
+ char correct[] = "10001010 11111111 11111111 00010010001101000101011001111000";
+
+ testStart("Append Num");
+ bstream = BitStream_new();
+
+ BitStream_appendNum(bstream, 8, 0x0000008a);
+ assert_zero(ncmpBin(correct, bstream, 8), "Internal data is incorrect.\n");
+
+ BitStream_appendNum(bstream, 16, 0x0000ffff);
+ assert_zero(ncmpBin(correct, bstream, 24), "Internal data is incorrect.\n");
+
+ BitStream_appendNum(bstream, 32, 0x12345678);
+
+ assert_zero(cmpBin(correct, bstream), "Internal data is incorrect.\n");
+ testFinish();
+
+ BitStream_free(bstream);
+}
+
+static void test_appendBytes(void)
+{
+ BitStream *bstream;
+ unsigned char data[8];
+ char correct[] = "10001010111111111111111100010010001101000101011001111000";
+
+ testStart("Append Bytes");
+ bstream = BitStream_new();
+
+ data[0] = 0x8a;
+ BitStream_appendBytes(bstream, 1, data);
+ assert_zero(ncmpBin(correct, bstream, 8), "Internal data is incorrect.");
+
+ data[0] = 0xff;
+ data[1] = 0xff;
+ BitStream_appendBytes(bstream, 2, data);
+ assert_zero(ncmpBin(correct, bstream, 24), "Internal data is incorrect.\n");
+
+ data[0] = 0x12;
+ data[1] = 0x34;
+ data[2] = 0x56;
+ data[3] = 0x78;
+ BitStream_appendBytes(bstream, 4, data);
+
+ assert_zero(cmpBin(correct, bstream), "Internal data is incorrect.\n");
+ testFinish();
+
+ BitStream_free(bstream);
+}
+
+static void test_toByte(void)
+{
+ BitStream *bstream;
+ unsigned char correct[] = {
+ 0x8a, 0xff, 0xff, 0x12, 0x34, 0x56, 0x78
+ };
+ unsigned char *result;
+
+ testStart("Convert to a byte array");
+ bstream = BitStream_new();
+
+ BitStream_appendBytes(bstream, 1, &correct[0]);
+ BitStream_appendBytes(bstream, 2, &correct[1]);
+ BitStream_appendBytes(bstream, 4, &correct[3]);
+
+ result = BitStream_toByte(bstream);
+ testEnd(memcmp(correct, result, 7));
+
+ BitStream_free(bstream);
+ free(result);
+}
+
+static void test_toByte_4bitpadding(void)
+{
+ BitStream *bstream;
+ unsigned char *result;
+
+ testStart("Convert to a byte array");
+
+ bstream = BitStream_new();
+ BitStream_appendNum(bstream, 4, 0xb);
+ result = BitStream_toByte(bstream);
+ assert_equal(result[0], 0xb0, "incorrect paddings\n");
+ BitStream_free(bstream);
+ free(result);
+
+ bstream = BitStream_new();
+ BitStream_appendNum(bstream, 12, 0x335);
+ result = BitStream_toByte(bstream);
+ assert_equal(result[0], 0x33, "incorrect paddings\n");
+ assert_equal(result[1], 0x50, "incorrect paddings\n");
+ BitStream_free(bstream);
+ free(result);
+
+ testFinish();
+
+}
+
+static void test_size(void)
+{
+ BitStream *bstream;
+
+ testStart("size check");
+ bstream = BitStream_new();
+ assert_equal(BitStream_size(bstream), 0, "Initialized BitStream is not 0 length");
+ BitStream_appendNum(bstream, 1, 0);
+ assert_equal(BitStream_size(bstream), 1, "Size incorrect. (first append)");
+ BitStream_appendNum(bstream, 2, 0);
+ assert_equal(BitStream_size(bstream), 3, "Size incorrect. (second append)");
+ testFinish();
+
+ BitStream_free(bstream);
+}
+
+static void test_append(void)
+{
+ BitStream *bs1, *bs2;
+ char c1[] = "00";
+ char c2[] = "0011";
+ char c3[] = "01111111111111111";
+ char c4[] = "001101111111111111111";
+ char c5[] = "0011011111111111111111111111111111";
+ int ret;
+
+ testStart("Append two BitStreams");
+
+ bs1 = BitStream_new();
+ bs2 = BitStream_new();
+ ret = BitStream_appendNum(bs1, 1, 0);
+ ret = BitStream_appendNum(bs2, 1, 0);
+
+ ret = BitStream_append(bs1, bs2);
+ assert_zero(ret, "Failed to append.");
+ assert_zero(cmpBin(c1, bs1), "Internal data is incorrect.");
+
+ ret = BitStream_appendNum(bs1, 2, 3);
+ assert_zero(ret, "Failed to append.");
+ assert_zero(cmpBin(c2, bs1), "Internal data is incorrect.");
+
+ ret = BitStream_appendNum(bs2, 16, 65535);
+ assert_zero(ret, "Failed to append.");
+ assert_zero(cmpBin(c3, bs2), "Internal data is incorrect.");
+
+ ret = BitStream_append(bs1, bs2);
+ assert_zero(ret, "Failed to append.");
+ assert_zero(cmpBin(c4, bs1), "Internal data is incorrect.");
+
+ ret = BitStream_appendNum(bs1, 13, 16383);
+ assert_zero(ret, "Failed to append.");
+ assert_zero(cmpBin(c5, bs1), "Internal data is incorrect.");
+
+ testFinish();
+
+ BitStream_free(bs1);
+ BitStream_free(bs2);
+}
+
+static void test_newWithBits(void)
+{
+ BitStream *bstream;
+ unsigned char data[4] = {0, 1, 0, 1};
+
+ testStart("New with bits");
+
+ bstream = BitStream_newWithBits(4, data);
+ assert_equal(bstream->length, 4, "Internal bit length is incorrect.\n");
+ assert_equal(bstream->datasize, 4, "Internal buffer size is incorrect.\n");
+ assert_zero(cmpBin("0101", bstream), "Internal data is incorrect.\n");
+
+ testFinish();
+
+ BitStream_free(bstream);
+}
+
+static void test_newWithBits_size0(void)
+{
+ BitStream *bstream;
+
+ testStart("New with bits (size = 0)");
+
+ bstream = BitStream_newWithBits(0, NULL);
+ assert_equal(bstream->length, 0, "Internal bit length is incorrect.\n");
+ assert_nonzero(bstream->datasize, "Internal buffer size is incorrect.\n");
+ assert_nonnull(bstream->data, "Internal buffer not allocated.\n");
+
+ testFinish();
+
+ BitStream_free(bstream);
+}
+
+int main()
+{
+ int tests = 11;
+ testInit(tests);
+ test_null();
+ test_num();
+ test_bytes();
+ test_appendNum();
+ test_appendBytes();
+ test_toByte();
+ test_toByte_4bitpadding();
+ test_size();
+ test_append();
+ test_newWithBits();
+ test_newWithBits_size0();
+ testReport(tests);
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_configure.sh b/genqrcode/tests/test_configure.sh
new file mode 100755
index 0000000000..4a301259a0
--- /dev/null
+++ b/genqrcode/tests/test_configure.sh
@@ -0,0 +1,61 @@
+#!/bin/sh
+
+BASEDIR=..
+
+CONFIG_H_IN="$BASEDIR/config.h.in"
+CONFIG_H="$BASEDIR/config.h"
+LIBQRENCODE_PC_IN="$BASEDIR/libqrencode.pc.in"
+LIBQRENCODE_PC="$BASEDIR/libqrencode.pc"
+
+echo "Testing configure scripts..."
+
+(cd $BASEDIR; ./autogen.sh)
+
+# test config.h.in
+grep "#undef HAVE_LIBPTHREAD" $CONFIG_H_IN > /dev/null
+if test ! $? -eq 0; then
+ echo "HAVE_LIBPTHREAD undefined in config.h.in."
+ exit 1
+fi
+
+# test libqrencode.pc.in
+grep "Libs.private: @LIBPTHREAD@" $LIBQRENCODE_PC_IN > /dev/null
+if test ! $? -eq 0; then
+ echo "Pthread is not handled in libqrencode.pc.in."
+ exit 1
+fi
+
+# test pthread checks in configure
+(cd $BASEDIR; ./configure --with-tests --enable-thread-safety > /dev/null)
+grep "#define HAVE_LIBPTHREAD 1" $CONFIG_H > /dev/null
+if test ! $? -eq 0; then
+ echo "HAVE_LIBPTHREAD undefined in config.h."
+ exit 1
+fi
+
+grep "Libs.private: -lpthread" $LIBQRENCODE_PC > /dev/null
+if test ! $? -eq 0; then
+ echo "Pthread is not handled in libqrencode.pc."
+ exit 1
+fi
+
+(cd $BASEDIR; ./configure --with-tests --disable-thread-safety > /dev/null)
+grep "#define HAVE_LIBPTHREAD 1" $CONFIG_H > /dev/null
+if test ! $? -eq 1; then
+ echo "HAVE_LIBPTHREAD incorrectly defined in config.h."
+ exit 1
+fi
+
+grep "Libs.private: -lpthread" $LIBQRENCODE_PC > /dev/null
+if test ! $? -eq 1; then
+ echo "Pthread is incorrectly handled in libqrencode.pc."
+ exit 1
+fi
+
+echo "All tests of configure script passed. Now reconfiguring..."
+
+(cd $BASEDIR; ./configure --with-tests > /dev/null)
+
+echo "Done."
+
+exit 0
diff --git a/genqrcode/tests/test_estimatebit.c b/genqrcode/tests/test_estimatebit.c
new file mode 100644
index 0000000000..8392ed813a
--- /dev/null
+++ b/genqrcode/tests/test_estimatebit.c
@@ -0,0 +1,183 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "common.h"
+#include "../qrinput.h"
+
+static QRinput *gstream;
+
+static void test_numbit(void)
+{
+ QRinput *stream;
+ char num[9]="01234567";
+ int bits;
+
+ testStart("Estimation of Numeric stream (8 digits)");
+ stream = QRinput_new();
+ QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num);
+ bits = QRinput_estimateBitStreamSize(stream, 0);
+ testEndExp(bits == 41);
+
+ QRinput_append(gstream, QR_MODE_NUM, 8, (unsigned char *)num);
+ QRinput_free(stream);
+}
+
+static void test_numbit2(void)
+{
+ QRinput *stream;
+ char num[17]="0123456789012345";
+ int bits;
+
+ testStart("Estimation of Numeric stream (16 digits)");
+ stream = QRinput_new();
+ QRinput_append(stream, QR_MODE_NUM, 16, (unsigned char *)num);
+ bits = QRinput_estimateBitStreamSize(stream, 0);
+ testEndExp(bits == 68);
+
+ QRinput_append(gstream, QR_MODE_NUM, 16, (unsigned char *)num);
+ QRinput_free(stream);
+}
+
+static void test_numbit3(void)
+{
+ QRinput *stream;
+ char *num;
+ int bits;
+
+ testStart("Estimation of Numeric stream (400 digits)");
+ stream = QRinput_new();
+ num = (char *)malloc(401);
+ memset(num, '1', 400);
+ num[400] = '\0';
+ QRinput_append(stream, QR_MODE_NUM, 400, (unsigned char *)num);
+ bits = QRinput_estimateBitStreamSize(stream, 0);
+ /* 4 + 10 + 133*10 + 4 = 1348 */
+ testEndExp(bits == 1348);
+
+ QRinput_append(gstream, QR_MODE_NUM, 400, (unsigned char *)num);
+ QRinput_free(stream);
+ free(num);
+}
+
+static void test_an(void)
+{
+ QRinput *stream;
+ char str[6]="AC-42";
+ int bits;
+
+ testStart("Estimation of Alphabet-Numeric stream (5 chars)");
+ stream = QRinput_new();
+ QRinput_append(stream, QR_MODE_AN, 5, (unsigned char *)str);
+ bits = QRinput_estimateBitStreamSize(stream, 0);
+ testEndExp(bits == 41);
+
+ QRinput_append(gstream, QR_MODE_AN, 5, (unsigned char *)str);
+ QRinput_free(stream);
+}
+
+static void test_8(void)
+{
+ QRinput *stream;
+ char str[9]="12345678";
+ int bits;
+
+ testStart("Estimation of 8 bit data stream (8 bytes)");
+ stream = QRinput_new();
+ QRinput_append(stream, QR_MODE_8, 8, (unsigned char *)str);
+ bits = QRinput_estimateBitStreamSize(stream, 0);
+ testEndExp(bits == 76);
+
+ QRinput_append(gstream, QR_MODE_8, 8, (unsigned char *)str);
+ QRinput_free(stream);
+}
+
+static void test_structure(void)
+{
+ QRinput *stream;
+ int bits;
+
+ testStart("Estimation of a structure-append header");
+ stream = QRinput_new();
+ QRinput_insertStructuredAppendHeader(stream, 10, 1, 0);
+ bits = QRinput_estimateBitStreamSize(stream, 1);
+ testEndExp(bits == 20);
+
+ QRinput_insertStructuredAppendHeader(gstream, 10, 1, 0);
+ QRinput_free(stream);
+}
+
+static void test_kanji(void)
+{
+ int res;
+
+ QRinput *stream;
+ unsigned char str[4]= {0x93, 0x5f,0xe4, 0xaa};
+ int bits;
+
+ testStart("Estimation of Kanji stream (2 chars)");
+ stream = QRinput_new();
+ res = QRinput_append(stream, QR_MODE_KANJI, 4, (unsigned char *)str);
+ if(res < 0) {
+ printf("Failed to add.\n");
+ testEnd(1);
+ } else {
+ bits = QRinput_estimateBitStreamSize(stream, 0);
+ testEndExp(bits == 38);
+ QRinput_append(gstream, QR_MODE_KANJI, 4, (unsigned char *)str);
+ }
+
+ QRinput_free(stream);
+}
+
+static void test_mix(void)
+{
+ int bits;
+
+ testStart("Estimation of Mixed stream");
+ bits = QRinput_estimateBitStreamSize(gstream, 0);
+ testEndExp(bits == (41 + 68 + 1348 + 41 + 76 + 38 + 20));
+ QRinput_free(gstream);
+}
+
+/* Taken from JISX 0510:2018, p.23 */
+static void test_numbit1_mqr(void)
+{
+ QRinput *stream;
+ char *str = "0123456789012345";
+ int bits;
+
+ testStart("Estimation of Numeric stream for Micro QR Code (16 digits)");
+ stream = QRinput_newMQR(3, QR_ECLEVEL_M);
+ QRinput_append(stream, QR_MODE_NUM, 16, (const unsigned char *)str);
+ bits = QRinput_estimateBitStreamSize(stream, QRinput_getVersion(stream));
+ assert_equal(bits, 61, "Estimated bit length is wrong: %d, expected: %d.\n", bits, 61);
+ QRinput_free(stream);
+
+ stream = QRinput_newMQR(4, QR_ECLEVEL_M);
+ QRinput_append(stream, QR_MODE_NUM, 16, (const unsigned char *)str);
+ bits = QRinput_estimateBitStreamSize(stream, QRinput_getVersion(stream));
+ assert_equal(bits, 63, "Estimated bit length is wrong: %d, expected: %d.\n", bits, 63);
+ QRinput_free(stream);
+
+ testFinish();
+}
+
+int main()
+{
+ gstream = QRinput_new();
+
+ int tests = 9;
+ testInit(tests);
+ test_numbit();
+ test_numbit2();
+ test_numbit3();
+ test_an();
+ test_8();
+ test_kanji();
+ test_structure();
+ test_mix();
+ test_numbit1_mqr();
+ testReport(tests);
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_mask.c b/genqrcode/tests/test_mask.c
new file mode 100644
index 0000000000..7ef7123251
--- /dev/null
+++ b/genqrcode/tests/test_mask.c
@@ -0,0 +1,411 @@
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+#include "../mask.h"
+#include "../qrspec.h"
+#include "decoder.h"
+
+static char dot[2] = {'_', '#'};
+static char *maskPatterns[8] = {
+ /* (i + j) mod 2 = 0 */
+ "#_#_#_"
+ "_#_#_#"
+ "#_#_#_"
+ "_#_#_#"
+ "#_#_#_"
+ "_#_#_#",
+ /* i mod 2 = 0 */
+ "######"
+ "______"
+ "######"
+ "______"
+ "######"
+ "______",
+ /* j mod 3 = 0 */
+ "#__#__"
+ "#__#__"
+ "#__#__"
+ "#__#__"
+ "#__#__"
+ "#__#__",
+ /* (i + j) mod 3 = 0 */
+ "#__#__"
+ "__#__#"
+ "_#__#_"
+ "#__#__"
+ "__#__#"
+ "_#__#_",
+ /* ((i div 2) + (j div 3)) mod 2 = 0 */
+ "###___"
+ "###___"
+ "___###"
+ "___###"
+ "###___"
+ "###___",
+ /* (ij) mod 2 + (ij) mod 3 = 0 */
+ "######"
+ "#_____"
+ "#__#__"
+ "#_#_#_"
+ "#__#__"
+ "#_____",
+ /* ((ij) mod 2 + (ij) mod 3) mod 2 = 0 */
+ "######"
+ "###___"
+ "##_##_"
+ "#_#_#_"
+ "#_##_#"
+ "#___##",
+ /* ((ij) mod 3 + (i+j) mod 2) mod 2 = 0 */
+ "#_#_#_"
+ "___###"
+ "#___##"
+ "_#_#_#"
+ "###___"
+ "_###__"
+};
+
+static void print_mask(int mask)
+{
+ const unsigned int w = 6;
+ unsigned char frame[w * w], *masked, *p;
+ int x, y;
+
+ memset(frame, 0, w * w);
+ masked = Mask_makeMaskedFrame(w, frame, mask);
+ p = masked;
+ for(y=0; y<w; y++) {
+ for(x=0; x<w; x++) {
+ putchar(dot[*p&1]);
+ p++;
+ }
+ printf("\n");
+ }
+ printf("\n");
+
+ free(masked);
+}
+
+static void print_masks(void)
+{
+ int i;
+
+ puts("\nPrinting mask patterns.");
+ for(i=0; i<8; i++) {
+ print_mask(i);
+ }
+}
+
+static int test_mask(int mask)
+{
+ const int w = 6;
+ unsigned char frame[w * w], *masked, *p;
+ char *q;
+ int x, y;
+ int err = 0;
+
+ memset(frame, 0, w * w);
+ masked = Mask_makeMaskedFrame(w, frame, mask);
+ p = masked;
+ q = maskPatterns[mask];
+ for(y=0; y<w; y++) {
+ for(x=0; x<w; x++) {
+ if(dot[*p&1] != *q) {
+ err++;
+ }
+ p++;
+ q++;
+ }
+ }
+
+ free(masked);
+ return err;
+}
+
+static void test_masks(void)
+{
+ int i;
+
+ testStart("Mask pattern checks");
+ for(i=0; i<8; i++) {
+ assert_zero(test_mask(i), "Mask pattern %d incorrect.\n", i);
+ }
+ testFinish();
+}
+
+#define N1 (3)
+#define N2 (3)
+#define N3 (40)
+#define N4 (10)
+
+static void test_eval(void)
+{
+ unsigned char *frame;
+ unsigned int w = 6;
+ int penalty;
+
+ frame = (unsigned char *)malloc(w * w);
+
+ testStart("Test mask evaluation (all white)");
+ memset(frame, 0, w * w);
+ penalty = Mask_evaluateSymbol(w, frame);
+ testEndExp(penalty == ((N1 + 1)*w*2 + N2 * (w - 1) * (w - 1)));
+
+ testStart("Test mask evaluation (all black)");
+ memset(frame, 1, w * w);
+ penalty = Mask_evaluateSymbol(w, frame);
+ testEndExp(penalty == ((N1 + 1)*w*2 + N2 * (w - 1) * (w - 1)));
+
+ free(frame);
+}
+
+/* .#.#.#.#.#
+ * #.#.#.#.#.
+ * ..##..##..
+ * ##..##..##
+ * ...###...#
+ * ###...###.
+ * ....####..
+ * ####....##
+ * .....#####
+ * #####.....
+ */
+static void test_eval2(void)
+{
+ unsigned char *frame;
+ unsigned int w = 10;
+ int penalty;
+ unsigned int x;
+
+ frame = (unsigned char *)malloc(w * w);
+
+ testStart("Test mask evaluation (run length penalty check)");
+ for(x=0; x<w; x++) {
+ frame[ x] = x & 1;
+ frame[w + x] = (x & 1) ^ 1;
+ frame[w*2 + x] = (x / 2) & 1;
+ frame[w*3 + x] = ((x / 2) & 1) ^ 1;
+ frame[w*4 + x] = (x / 3) & 1;
+ frame[w*5 + x] = ((x / 3) & 1) ^ 1;
+ frame[w*6 + x] = (x / 4) & 1;
+ frame[w*7 + x] = ((x / 4) & 1) ^ 1;
+ frame[w*8 + x] = (x / 5) & 1;
+ frame[w*9 + x] = ((x / 5) & 1) ^ 1;
+ }
+ penalty = Mask_evaluateSymbol(w, frame);
+ testEndExp(penalty == N1 * 4 + N2 * 4);
+
+ free(frame);
+}
+
+static void test_calcN2(void)
+{
+ unsigned char frame[64];
+ int width;
+ int penalty;
+ int x, y;
+
+ testStart("Test mask evaluation (2x2 block check)");
+ width = 4;
+ for(y = 0; y < width; y++) {
+ for(x = 0; x < width; x++) {
+ frame[y * width + x] = ((x & 2) ^ (y & 2)) >> 1;
+ }
+ }
+ penalty = Mask_calcN2(width, frame);
+ assert_equal(penalty, N2 * 4, "Calculation of N2 penalty is wrong: %d, expected %d", penalty, N2 * 4);
+
+ width = 4;
+ for(y = 0; y < width; y++) {
+ for(x = 0; x < width; x++) {
+ frame[y * width + x] = (((x + 1) & 2) ^ (y & 2)) >> 1;
+ }
+ }
+ penalty = Mask_calcN2(width, frame);
+ assert_equal(penalty, N2 * 2, "Calculation of N2 penalty is wrong: %d, expected %d", penalty, N2 * 2);
+
+ width = 6;
+ for(y = 0; y < width; y++) {
+ for(x = 0; x < width; x++) {
+ frame[y * width + x] = (x / 3) ^ (y / 3);
+ }
+ }
+ penalty = Mask_calcN2(width, frame);
+ assert_equal(penalty, N2 * 16, "Calculation of N2 penalty is wrong: %d, expected %d", penalty, N2 * 16);
+
+ testFinish();
+}
+
+static void test_eval3(void)
+{
+ unsigned char *frame;
+ int w = 15;
+ int penalty;
+ int x, y;
+ static unsigned char pattern[7][15] = {
+ {0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0}, // N3x1
+ {1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1}, // N3x1
+ {1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1}, // N3x1
+ {1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0}, // 0
+ {1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1}, // N3x2
+ {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0}, // N3 + (N1+1)
+ {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1} // (N1+1)
+ };
+
+ frame = (unsigned char *)malloc(w * w);
+
+ testStart("Test mask evaluation (1:1:3:1:1 check)");
+
+ for(y=0; y<5; y++) {
+ for(x=0; x<w; x++) {
+ frame[w*y*2 + x] = pattern[y][x];
+ frame[w*(y*2+1) + x] = pattern[y][x]^1;
+ }
+ }
+ for(x=0; x<w; x++) {
+ frame[w*10 + x] = x & 1;
+ }
+ for(y=5; y<7; y++) {
+ for(x=0; x<w; x++) {
+ frame[w*(y*2+1) + x] = pattern[y][x];
+ frame[w*(y*2+2) + x] = pattern[y][x]^1;
+ }
+ }
+ /*
+ for(y=0; y<w; y++) {
+ for(x=0; x<w; x++) {
+ printf("%s", frame[w*y+x]?"##":"..");
+ }
+ printf("\n");
+ }
+ */
+ penalty = Mask_evaluateSymbol(w, frame);
+ testEndExp(penalty == N3 * 10 + (N1 + 1) * 4);
+
+ free(frame);
+}
+
+static void test_format(void)
+{
+ unsigned char *frame, *masked;
+ int version, mask, width, dmask;
+ QRecLevel level, dlevel;
+ QRcode *code;
+ int ret;
+
+ testStart("Checking format info.");
+ for(version=1; version<=QRSPEC_VERSION_MAX; version++) {
+ frame = QRspec_newFrame(version);
+ width = QRspec_getWidth(version);
+ for(level=QR_ECLEVEL_L; level<=QR_ECLEVEL_H; level++) {
+ for(mask=0; mask<8; mask++) {
+ masked = Mask_makeMask(width, frame, mask, level);
+ code = QRcode_new(version, width, masked);
+ ret = QRcode_decodeFormat(code, &dlevel, &dmask);
+ assert_zero(ret, "Something wrong in format info.\n");
+ assert_equal(dlevel, level, "Decoded level is wrong: %d, expected %d", dlevel, level);
+ assert_equal(dmask, mask, "Decoded mask is wrong: %d, expected %d", dlevel, level);
+ QRcode_free(code);
+ }
+ }
+ free(frame);
+ }
+ testFinish();
+}
+
+static void test_calcRunLength(void)
+{
+ int width = 5;
+ unsigned char frame[width * width];
+ int runLength[width + 1];
+ int i, j;
+ int length;
+ static unsigned char pattern[6][5] = {
+ {0, 1, 0, 1, 0},
+ {1, 0, 1, 0, 1},
+ {0, 0, 0, 0, 0},
+ {1, 1, 1, 1, 1},
+ {0, 0, 1, 1, 1},
+ {1, 1, 0, 0, 0}
+ };
+ static int expected[6][7] = {
+ { 1, 1, 1, 1, 1, 0, 5},
+ {-1, 1, 1, 1, 1, 1, 6},
+ { 5, 0, 0, 0, 0, 0, 1},
+ {-1, 5, 0, 0, 0, 0, 2},
+ { 2, 3, 0, 0, 0, 0, 2},
+ {-1, 2, 3, 0, 0, 0, 3}
+ };
+
+ testStart("Test runlength calc function");
+ for(i=0; i<6; i++) {
+ length = Mask_calcRunLengthH(width, pattern[i], runLength);
+ assert_equal(expected[i][6], length, "Length incorrect: %d, expected %d.\n", length, expected[i][6]);
+ assert_zero(memcmp(runLength, expected[i], sizeof(int) * expected[i][6]), "Run length does not match: pattern %d, horizontal access.\n", i);
+ for(j=0; j<width; j++) {
+ frame[j * width] = pattern[i][j];
+ }
+ length = Mask_calcRunLengthV(width, frame, runLength);
+ assert_equal(expected[i][6], length, "Length incorrect: %d, expected %d.\n", length, expected[i][6]);
+ assert_zero(memcmp(runLength, expected[i], sizeof(int) * expected[i][6]), "Run length does not match: pattern %d, vertical access.\n", i);
+ }
+ testFinish();
+}
+
+static void test_calcN1N3(void)
+{
+ int runLength[26];
+ int length;
+ int penalty;
+ int i;
+ static unsigned char pattern[][16] = {
+ {1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, N3},
+ {0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, N3},
+ {1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0},
+ {1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, N3},
+ {1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, N3},
+ {1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, N3 * 2},
+ };
+
+ static unsigned char pattern2[][19] = {
+ {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, N3 + N1 + 1},
+ {0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, N3 + N1 + 1},
+ {1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, N1 + 1},
+ {1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, N3 + N1 + 1},
+ {1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, N3 + N1 + 1}
+ };
+
+ testStart("Test N3 penalty calculation");
+ for(i=0; i<6; i++) {
+ length = Mask_calcRunLengthH(15, pattern[i], runLength);
+ penalty = Mask_calcN1N3(length, runLength);
+ assert_equal(pattern[i][15], penalty, "N3 penalty is wrong: %d, expected %d\n", penalty, pattern[i][15]);
+ }
+ for(i=0; i<5; i++) {
+ length = Mask_calcRunLengthH(18, pattern2[i], runLength);
+ penalty = Mask_calcN1N3(length, runLength);
+ assert_equal(pattern2[i][18], penalty, "N3 penalty is wrong: %d, expected %d\n", penalty, pattern2[i][18]);
+ }
+ testFinish();
+}
+
+int main(int argc, char **argv)
+{
+ int tests = 9;
+ testInit(tests);
+ test_masks();
+ test_eval();
+ test_eval2();
+ test_eval3();
+ test_format();
+ test_calcN2();
+ test_calcRunLength();
+ test_calcN1N3();
+ testReport(tests);
+
+ if(argc > 1) {
+ print_masks();
+ }
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_mmask.c b/genqrcode/tests/test_mmask.c
new file mode 100644
index 0000000000..c6cab14a6e
--- /dev/null
+++ b/genqrcode/tests/test_mmask.c
@@ -0,0 +1,155 @@
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+#include "../mmask.h"
+#include "../mqrspec.h"
+
+static char dot[2] = {'_', '#'};
+static char *maskPatterns[4] = {
+ /* i mod 2 = 0 */
+ "######"
+ "______"
+ "######"
+ "______"
+ "######"
+ "______",
+ /* ((i div 2) + (j div 3)) mod 2 = 0 */
+ "###___"
+ "###___"
+ "___###"
+ "___###"
+ "###___"
+ "###___",
+ /* ((ij) mod 2 + (ij) mod 3) mod 2 = 0 */
+ "######"
+ "###___"
+ "##_##_"
+ "#_#_#_"
+ "#_##_#"
+ "#___##",
+ /* ((ij) mod 3 + (i+j) mod 2) mod 2 = 0 */
+ "#_#_#_"
+ "___###"
+ "#___##"
+ "_#_#_#"
+ "###___"
+ "_###__"
+};
+
+static void print_mask(int mask)
+{
+ const int w = 6;
+ unsigned char frame[w * w], *masked, *p;
+ int x, y;
+
+ memset(frame, 0, w * w);
+ masked = MMask_makeMaskedFrame(w, frame, mask);
+ p = masked;
+ for(y=0; y<w; y++) {
+ for(x=0; x<w; x++) {
+ putchar(dot[*p&1]);
+ p++;
+ }
+ printf("\n");
+ }
+ printf("\n");
+
+ free(masked);
+}
+
+static void print_masks(void)
+{
+ int i;
+
+ puts("\nPrinting mask patterns.");
+ for(i=0; i<4; i++) {
+ print_mask(i);
+ }
+}
+
+static int test_mask(int mask)
+{
+ const int w = 6;
+ unsigned char frame[w * w], *masked, *p;
+ char *q;
+ int x, y;
+ int err = 0;
+
+ memset(frame, 0, w * w);
+ masked = MMask_makeMaskedFrame(w, frame, mask);
+ p = masked;
+ q = maskPatterns[mask];
+ for(y=0; y<w; y++) {
+ for(x=0; x<w; x++) {
+ if(dot[*p&1] != *q) {
+ err++;
+ }
+ p++;
+ q++;
+ }
+ }
+
+ free(masked);
+ return err;
+}
+
+static void test_masks(void)
+{
+ int i;
+
+ testStart("Mask pattern checks");
+ for(i=0; i<4; i++) {
+ assert_zero(test_mask(i), "Mask pattern %d incorrect.\n", i);
+ }
+ testFinish();
+}
+
+static void test_maskEvaluation(void)
+{
+ static const int w = 11;
+ unsigned char pattern[w * w];
+ int i, score;
+
+ memset(pattern, 0, w * w);
+
+ testStart("Test mask evaluation");
+ score = MMask_evaluateSymbol(w, pattern);
+ assert_equal(score, 0, "Mask score caluculation is incorrect. (score=%d (%d expected)\n", score, 0);
+
+ for(i=0; i<w; i++) {
+ pattern[(w-1) * w + i] = 1;
+ }
+ score = MMask_evaluateSymbol(w, pattern);
+ assert_equal(score, 16 + w - 1, "Mask score caluculation is incorrect. (score=%d) (%d expected)\n", score, 16 + w - 1);
+
+ for(i=0; i<w; i++) {
+ pattern[(w-1) * w + i] = 0;
+ pattern[i * w + w - 1] = 1;
+ }
+ score = MMask_evaluateSymbol(w, pattern);
+ assert_equal(score, 16 + w - 1, "Mask score caluculation is incorrect. (score=%d) (%d expected)\n", score, 16 + w - 1);
+
+ for(i=0; i<w; i++) {
+ pattern[(w-1) * w + i] = 1;
+ pattern[i * w + w - 1] = 1;
+ }
+ score = MMask_evaluateSymbol(w, pattern);
+ assert_equal(score, 16 * (w - 1) + w - 1, "Mask score caluculation is incorrect. (score=%d) (%d expected)\n", score, 16 * (w - 1) + w - 1);
+
+ testFinish();
+}
+
+int main(int argc, char **argv)
+{
+ int tests = 2;
+ testInit(tests);
+ test_masks();
+ test_maskEvaluation();
+ testReport(tests);
+
+ if(argc > 1) {
+ print_masks();
+ }
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_monkey.c b/genqrcode/tests/test_monkey.c
new file mode 100644
index 0000000000..f50fdca1dd
--- /dev/null
+++ b/genqrcode/tests/test_monkey.c
@@ -0,0 +1,582 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "common.h"
+#include "../qrinput.h"
+#include "../split.h"
+#include "../qrspec.h"
+#include "decoder.h"
+
+#define MAX_LENGTH 7091
+static unsigned char data[MAX_LENGTH];
+static unsigned char check[MAX_LENGTH];
+
+static const char *AN = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:";
+
+#define drand(__scale__) ((__scale__) * (double)rand() / ((double)RAND_MAX + 1.0))
+
+static int fill8bitString(void)
+{
+ int len, i;
+
+ len = 1 + (int)drand((MAX_LENGTH - 2));
+ for(i=0; i<len; i++) {
+ data[i] = (unsigned char)drand(255) + 1;
+ }
+ data[len] = '\0';
+
+ return len;
+}
+
+static int fill8bitData(void)
+{
+ int len, i;
+
+ len = 1 + (int)drand((MAX_LENGTH - 2));
+ for(i=0; i<len; i++) {
+ data[i] = (unsigned char)drand(256);
+ }
+ data[len] = '\0';
+
+ return len;
+}
+
+static int fillANData(void)
+{
+ int len, i;
+
+ len = 1 + (int)drand((MAX_LENGTH - 2));
+ for(i=0; i<len; i++) {
+ data[i] = AN[(int)drand(45)];
+ }
+ data[len] = '\0';
+
+ return len;
+}
+
+static void test_encode_an(int num)
+{
+ int ret;
+ int len;
+ len = fillANData();
+ QRcode *qrcode;
+ QRdata *qrdata;
+ FILE *fp;
+ char buf[256];
+
+ qrcode = QRcode_encodeString((char *)data, 0, num % 4, QR_MODE_8, num % 2);
+ if(qrcode == NULL) {
+ if(errno == ERANGE) return;
+ perror("test_encode_an aborted at QRcode_encodeString():");
+ printf("Length: %d\n", len);
+ printf("Level: %d\n", num % 4);
+ return;
+ }
+ qrdata = QRcode_decode(qrcode);
+ if(qrdata == NULL) {
+ printf("#%d: Failed to decode this code.\n", num);
+ QRcode_free(qrcode);
+ return;
+ }
+ if(qrdata->size != len) {
+ printf("#%d: length mismatched (orig: %d, decoded: %d)\n", num, len, qrdata->size);
+ }
+ ret = memcmp(qrdata->data, data, len);
+ if(ret != 0) {
+ unsigned char *frame, *p;
+ unsigned int x;
+ int y,c;
+ int dataLength, eccLength;
+ QRinput *input;
+ QRcode *origcode;
+ BitStream *bstream;
+ int spec[5];
+
+ printf("#%d: data mismatched.\n", num);
+ printf("Version: %d\n", qrcode->version);
+ QRspec_getEccSpec(qrcode->version, num%4, spec);
+ printf("DataLength: %d\n", QRspec_rsDataLength(spec));
+ printf("BlockNum1: %d\n", QRspec_rsBlockNum1(spec));
+ printf("BlockNum: %d\n", QRspec_rsBlockNum(spec));
+ printf("DataCodes1: %d\n", QRspec_rsDataCodes1(spec));
+
+ snprintf(buf, 256, "monkey-orig-%d.dat", num);
+ fp = fopen(buf, "w");
+ fputs((char *)data, fp);
+ fclose(fp);
+
+ snprintf(buf, 256, "monkey-result-%d.dat", num);
+ fp = fopen(buf, "w");
+ fputs((char *)qrdata->data, fp);
+ fclose(fp);
+
+ snprintf(buf, 256, "monkey-result-unmasked-%d.dat", num);
+ fp = fopen(buf, "w");
+ frame = QRcode_unmask(qrcode);
+ p = frame;
+ for(y=0; y<qrcode->width; y++) {
+ for(x=0; x<qrcode->width; x++) {
+ fputc((*p&1)?'1':'0', fp);
+ p++;
+ }
+ fputc('\n', fp);
+ }
+ fclose(fp);
+ free(frame);
+
+ snprintf(buf, 256, "monkey-orig-unmasked-%d.dat", num);
+ fp = fopen(buf, "w");
+ input = QRinput_new2(0, num % 4);
+ Split_splitStringToQRinput((char *)data, input, QR_MODE_8, num % 2);
+ origcode = QRcode_encodeMask(input, -2);
+ p = origcode->data;
+ for(y=0; y<origcode->width; y++) {
+ for(x=0; x<origcode->width; x++) {
+ fputc((*p&1)?'1':'0', fp);
+ p++;
+ }
+ fputc('\n', fp);
+ }
+ fclose(fp);
+ QRcode_free(origcode);
+
+ snprintf(buf, 256, "monkey-orig-bits-%d.dat", num);
+ fp = fopen(buf, "w");
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ c = 0;
+ for(x=0; x<bstream->length; x++) {
+ fputc((bstream->data[x]&1)?'1':'0', fp);
+ if((x & 7) == 7) {
+ fputc(' ', fp);
+ c++;
+ }
+ if((x & 63) == 63) {
+ fprintf(fp, "%d\n", c);
+ }
+ }
+ fclose(fp);
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ snprintf(buf, 256, "monkey-result-bits-%d.dat", num);
+ fp = fopen(buf, "w");
+ bstream = QRcode_extractBits(qrcode, &dataLength, &eccLength);
+ y = bstream->length;
+ p = bstream->data;
+ c = 0;
+ for(x=0; x<y; x++) {
+ fputc((p[x]&1)?'1':'0', fp);
+ if((x & 7) == 7) {
+ fputc(' ', fp);
+ c++;
+ }
+ if((x & 63) == 63) {
+ fprintf(fp, "%d\n", c);
+ }
+ }
+ fclose(fp);
+ BitStream_free(bstream);
+ }
+ QRdata_free(qrdata);
+ QRcode_free(qrcode);
+}
+
+static void monkey_encode_an(int loop)
+{
+ int i;
+
+ testStart("Monkey test: QRcode_encodeString() - AlphaNumeric string.");
+ srand(0);
+ for(i=0; i<loop; i++) {
+ test_encode_an(i);
+ }
+ testEnd(0);
+}
+
+
+static void test_split_an(int num)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int len, i, ret;
+
+ len = fillANData();
+
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ if(input == NULL) {
+ perror("test_split_an aborted at QRinput_new2():");
+ return;
+ }
+ ret = Split_splitStringToQRinput((char *)data, input, QR_MODE_8, 1);
+ if(ret < 0) {
+ perror("test_split_an aborted at Split_splitStringToQRinput():");
+ QRinput_free(input);
+ return;
+ }
+ list = input->head;
+ i = 0;
+ while(list != NULL) {
+ memcpy(check + i, list->data, list->size);
+ i += list->size;
+ list = list->next;
+ }
+ if(i != len) {
+ printf("#%d: length is not correct. (%d should be %d)\n", num, i, len);
+ }
+
+ check[i] = '\0';
+ ret = memcmp(data, check, len);
+ if(ret != 0) {
+ printf("#%d: data mismatched.\n", num);
+ list = input->head;
+ i = 0;
+ while(list != NULL) {
+ ret = memcmp(data + i, list->data, list->size);
+ printf("wrong chunk:\n");
+ printf(" position: %d\n", i);
+ printf(" mode : %d\n", list->mode);
+ printf(" size : %d\n", list->size);
+ printf(" data : %.*s\n", list->size, list->data);
+ i += list->size;
+ list = list->next;
+ }
+ exit(1);
+ }
+ QRinput_free(input);
+}
+
+static void monkey_split_an(int loop)
+{
+ int i;
+
+ testStart("Monkey test: Split_splitStringToQRinput() - AlphaNumeric string.");
+ srand(0);
+ for(i=0; i<loop; i++) {
+ test_split_an(i);
+ }
+ testEnd(0);
+}
+
+static void test_encode_8(int num)
+{
+ QRcode *qrcode;
+ QRdata *qrdata;
+ int len, ret;
+
+ len = fill8bitData();
+
+ qrcode = QRcode_encodeData(len, data, 0, num % 4);
+ if(qrcode == NULL) {
+ if(errno == ERANGE) return;
+ perror("test_encdoe_8 aborted at QRcode_encodeData():");
+ return;
+ }
+ qrdata = QRcode_decode(qrcode);
+ if(qrdata == NULL) {
+ printf("#%d: Failed to decode this code.\n", num);
+ QRcode_free(qrcode);
+ return;
+ }
+ if(qrdata->size != len) {
+ printf("#%d: length mismatched (orig: %d, decoded: %d)\n", num, len, qrdata->size);
+ }
+ ret = memcmp(qrdata->data, data, len);
+ if(ret != 0) {
+ printf("#%d: data mismatched.\n", num);
+ }
+ QRdata_free(qrdata);
+ QRcode_free(qrcode);
+}
+
+static void monkey_encode_8(int loop)
+{
+ int i;
+
+ testStart("Monkey test: QRcode_encodeData() - 8bit char string.");
+ srand(0);
+ for(i=0; i<loop; i++) {
+ test_encode_8(i);
+ }
+ testEnd(0);
+}
+
+static void test_split_8(int num)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int len, i, ret;
+
+ len = fill8bitString();
+
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ if(input == NULL) {
+ perror("test_split_8 aborted at QRinput_new2():");
+ return;
+ }
+ ret = Split_splitStringToQRinput((char *)data, input, QR_MODE_8, 1);
+ if(ret < 0) {
+ perror("test_split_8 aborted at Split_splitStringToQRinput():");
+ QRinput_free(input);
+ return;
+ }
+ list = input->head;
+ i = 0;
+ while(list != NULL) {
+ memcpy(check + i, list->data, list->size);
+ i += list->size;
+ list = list->next;
+ }
+ if(i != len) {
+ printf("#%d: length is not correct. (%d should be %d)\n", num, i, len);
+ }
+
+ check[i] = '\0';
+ ret = memcmp(data, check, len);
+ if(ret != 0) {
+ printf("#%d: data mismatched.\n", num);
+ list = input->head;
+ i = 0;
+ while(list != NULL) {
+ ret = memcmp(data + i, list->data, list->size);
+ printf("wrong chunk:\n");
+ printf(" position: %d\n", i);
+ printf(" mode : %d\n", list->mode);
+ printf(" size : %d\n", list->size);
+ printf(" data : %.*s\n", list->size, list->data);
+ i += list->size;
+ list = list->next;
+ }
+ exit(1);
+ }
+ QRinput_free(input);
+}
+
+static void monkey_split_8(int loop)
+{
+ int i;
+
+ testStart("Monkey test: Split_splitStringToQRinput() - 8bit char string.");
+ srand(0);
+ for(i=0; i<loop; i++) {
+ test_split_8(i);
+ }
+ testEnd(0);
+}
+
+static void test_encode_kanji(int num)
+{
+ QRcode *qrcode;
+ QRdata *qrdata;
+ int len, ret;
+
+ len = fill8bitString();
+
+ qrcode = QRcode_encodeString((char *)data, 0, num % 4, QR_MODE_8, 1);
+ if(qrcode == NULL) {
+ if(errno == ERANGE) return;
+ perror("test_encdoe_kanji aborted at QRcode_encodeString():");
+ return;
+ }
+ qrdata = QRcode_decode(qrcode);
+ if(qrdata == NULL) {
+ printf("#%d: Failed to decode this code.\n", num);
+ QRcode_free(qrcode);
+ return;
+ }
+ if(qrdata->size != len) {
+ printf("#%d: length mismatched (orig: %d, decoded: %d)\n", num, len, qrdata->size);
+ }
+ ret = memcmp(qrdata->data, data, len);
+ if(ret != 0) {
+ printf("#%d: data mismatched.\n", num);
+ }
+ QRdata_free(qrdata);
+ QRcode_free(qrcode);
+}
+
+static void monkey_encode_kanji(int loop)
+{
+ int i;
+
+ testStart("Monkey test: QRcode_encodeString() - kanji string.");
+ srand(0);
+ for(i=0; i<loop; i++) {
+ test_encode_kanji(i);
+ }
+ testEnd(0);
+}
+
+static void test_split_kanji(int num)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int len, i, ret;
+
+ len = fill8bitString();
+
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ if(input == NULL) {
+ perror("test_split_kanji aborted at QRinput_new2():");
+ return;
+ }
+ ret = Split_splitStringToQRinput((char *)data, input, QR_MODE_KANJI, 1);
+ if(ret < 0) {
+ perror("test_split_kanji aborted at Split_splitStringToQRinput():");
+ QRinput_free(input);
+ return;
+ }
+ list = input->head;
+ i = 0;
+ while(list != NULL) {
+ memcpy(check + i, list->data, list->size);
+ i += list->size;
+ list = list->next;
+ }
+ if(i != len) {
+ printf("#%d: length is not correct. (%d should be %d)\n", num, i, len);
+ }
+
+ check[i] = '\0';
+ ret = memcmp(data, check, len);
+ if(ret != 0) {
+ printf("#%d: data mismatched.\n", num);
+ list = input->head;
+ i = 0;
+ while(list != NULL) {
+ ret = memcmp(data + i, list->data, list->size);
+ printf("wrong chunk:\n");
+ printf(" position: %d\n", i);
+ printf(" mode : %d\n", list->mode);
+ printf(" size : %d\n", list->size);
+ printf(" data : %.*s\n", list->size, list->data);
+ i += list->size;
+ list = list->next;
+ }
+ exit(1);
+ }
+ QRinput_free(input);
+}
+
+static void monkey_split_kanji(int loop)
+{
+ int i;
+
+ testStart("Monkey test: Split_splitStringToQRinput() - kanji string.");
+ srand(0);
+ for(i=0; i<loop; i++) {
+ test_split_kanji(i);
+ }
+ testEnd(0);
+}
+
+static void test_split_structure(int num)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ QRcode_List *codes, *list;
+ QRinput_InputList *il;
+ int version;
+ QRecLevel level;
+ int c, i, ret;
+
+ version = (int)drand(40) + 1;
+ level = (QRecLevel)drand(4);
+
+ fill8bitString();
+
+ input = QRinput_new2(version, level);
+ if(input == NULL) {
+ perror("test_split_structure aborted at QRinput_new2():");
+ return;
+ }
+ ret = Split_splitStringToQRinput((char *)data, input, QR_MODE_KANJI, 1);
+ if(ret < 0) {
+ perror("test_split_structure aborted at Split_splitStringToQRinput():");
+ QRinput_free(input);
+ return;
+ }
+ s = QRinput_splitQRinputToStruct(input);
+ if(s == NULL) {
+ if(errno != 0 && errno != ERANGE) {
+ perror("test_split_structure aborted at QRinput_splitQRinputToStruct():");
+ }
+ QRinput_free(input);
+ return;
+ }
+ il = s->head;
+ i = 0;
+ while(il != NULL) {
+ if(il->input->version != version) {
+ printf("Test: version %d, level %c\n", version, levelChar[level]);
+ printf("wrong version number.\n");
+ printQRinputInfo(il->input);
+ exit(1);
+ }
+ i++;
+ il = il->next;
+ }
+ codes = QRcode_encodeInputStructured(s);
+ if(codes == NULL) {
+ perror("test_split_structure aborted at QRcode_encodeInputStructured():");
+ QRinput_free(input);
+ QRinput_Struct_free(s);
+ return;
+ }
+ list = codes;
+ il = s->head;
+ c = 0;
+ while(list != NULL) {
+ if(list->code->version != version) {
+ printf("#%d: data mismatched.\n", num);
+ printf("Test: version %d, level %c\n", version, levelChar[level]);
+ printf("code #%d\n", c);
+ printf("Version mismatch: %d should be %d\n", list->code->version, version);
+ printf("max bits: %d\n", QRspec_getDataLength(version, level) * 8 - 20);
+ printQRinputInfo(il->input);
+ printQRinput(input);
+ exit(1);
+ }
+ list = list->next;
+ il = il->next;
+ c++;
+ }
+
+ QRinput_free(input);
+ QRinput_Struct_free(s);
+ QRcode_List_free(codes);
+
+ return;
+}
+
+static void monkey_split_structure(int loop)
+{
+ int i;
+
+ testStart("Monkey test: QRinput_splitQRinputToStruct.");
+ srand(0);
+ for(i=0; i<loop; i++) {
+ test_split_structure(i);
+ }
+ testEnd(0);
+}
+
+int main(int argc, char **argv)
+{
+ int loop = 1000;
+ if(argc == 2) {
+ loop = atoi(argv[1]);
+ }
+ int tests = 7;
+ testInit(tests);
+ monkey_split_an(loop);
+ monkey_encode_an(loop);
+ monkey_split_8(loop);
+ monkey_encode_8(loop);
+ monkey_split_kanji(loop);
+ monkey_encode_kanji(loop);
+ monkey_split_structure(loop);
+ testReport(tests);
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_mqrspec.c b/genqrcode/tests/test_mqrspec.c
new file mode 100644
index 0000000000..3a4b18950b
--- /dev/null
+++ b/genqrcode/tests/test_mqrspec.c
@@ -0,0 +1,181 @@
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+#include "../mqrspec.h"
+
+static unsigned char v4frame[] = {
+ 0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc0,0x91,0x90,0x91,0x90,0x91,0x90,0x91,0x90,0x91,
+ 0xc1,0xc0,0xc0,0xc0,0xc0,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xc1,0xc0,0xc1,0xc1,0xc1,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xc1,0xc0,0xc1,0xc1,0xc1,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xc1,0xc0,0xc1,0xc1,0xc1,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xc1,0xc0,0xc0,0xc0,0xc0,0xc0,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc1,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0xc0,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x91,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x84,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+static void test_newFrame(void)
+{
+ int width, i, y;
+ unsigned char *frame;
+
+ testStart("Test empty frames");
+ for(i=1; i<MQRSPEC_VERSION_MAX; i++) {
+ frame = MQRspec_newFrame(i);
+ width = MQRspec_getWidth(i);
+ for(y=0; y<width; y++) {
+ assert_zero(memcmp(&frame[y * width], &v4frame[y * MQRSPEC_WIDTH_MAX], width), "Mismatch found in version %d, line %d.\n", i, y);
+ }
+ free(frame);
+ }
+ testFinish();
+}
+
+static void test_newframe_invalid(void)
+{
+ unsigned char *frame;
+
+ testStart("Checking MQRspec_newFrame with invalid version.");
+ frame = MQRspec_newFrame(0);
+ assert_null(frame, "MQRspec_newFrame(0) returns non-NULL.");
+ frame = MQRspec_newFrame(MQRSPEC_VERSION_MAX+1);
+ assert_null(frame, "MQRspec_newFrame(0) returns non-NULL.");
+ testFinish();
+}
+
+/* See Table 10 (pp.115) of Appendix 1, JIS X0510:2004 */
+static unsigned int calcFormatInfo(int type, int mask)
+{
+ unsigned int data, ecc, b, code;
+ int i, c;
+
+ data = (type << 12) | (mask << 10);
+ ecc = data;
+ b = 1 << 14;
+ for(i=0; b != 0; i++) {
+ if(ecc & b) break;
+ b = b >> 1;
+ }
+ c = 4 - i;
+ code = 0x537 << c ; //10100110111
+ b = 1 << (10 + c);
+ for(i=0; i<=c; i++) {
+ if(b & ecc) {
+ ecc ^= code;
+ }
+ code = code >> 1;
+ b = b >> 1;
+ }
+
+ return (data | ecc) ^ 0x4445;
+}
+
+/* See Table 10 of Appendix 1. (pp.115) */
+static const int typeTable[4][3] = {
+ { 0, -1, -1},
+ { 1, 2, -1},
+ { 3, 4, -1},
+ { 5, 6, 7}
+};
+
+static void test_format(void)
+{
+ unsigned int format;
+ int version, l, mask;
+ int type;
+ int err = 0;
+
+ testStart("Format info test");
+ for(version=1; version<=MQRSPEC_VERSION_MAX; version++) {
+ for(l=QR_ECLEVEL_L; l<=QR_ECLEVEL_Q; l++) {
+ for(mask=0; mask<4; mask++) {
+ format = MQRspec_getFormatInfo(mask, version, (QRecLevel)l);
+ type = typeTable[version - 1][l];
+ if(type == -1) {
+ if(format != 0) {
+ printf("Error in version %d, level %d, mask %d\n",
+ version, l, mask);
+ err++;
+ }
+ } else {
+ if(format != calcFormatInfo(type, mask)) {
+ printf("Error in version %d, level %d, mask %d\n",
+ version, l, mask);
+ err++;
+ }
+ }
+ }
+ }
+ }
+ testEnd(err);
+}
+
+static void print_format(void)
+{
+ unsigned int format;
+ int i, j;
+
+ puts("\nPrinting hex strings of format information.");
+ for(i=0; i<4; i++) {
+ for(j=0; j<8; j++) {
+ format = calcFormatInfo(j, i);
+ printf("0x%04x, ", format);
+ }
+ printf("\n");
+ }
+}
+
+/**
+ * See Table 7 of Appendix 1.
+ */
+static int datalen[4][3] = {
+ { 20, 0, 0},
+ { 40, 32, 0},
+ { 84, 68, 0},
+ {128, 112, 80},
+};
+
+static void test_dataLength(void)
+{
+ int v, l;
+ int bits;
+ int err = 0;
+
+ testStart("Test dataLength");
+ for(v=0; v<4; v++) {
+ for(l=0; l<3; l++) {
+ bits = MQRspec_getDataLengthBit(v+1, (QRecLevel)l);
+ if(bits != datalen[v][l]) {
+ printf("Error in version %d, level %d.\n", v, l);
+ err++;
+ }
+ }
+ }
+ testEnd(err);
+}
+
+int main(int argc, char **argv)
+{
+ int tests = 4;
+ testInit(tests);
+ test_newFrame();
+ test_newframe_invalid();
+ test_format();
+ test_dataLength();
+ testReport(tests);
+
+ if(argc > 1) {
+ print_format();
+ }
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_qrenc.sh b/genqrcode/tests/test_qrenc.sh
new file mode 100755
index 0000000000..8c39c6a9aa
--- /dev/null
+++ b/genqrcode/tests/test_qrenc.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+COMMAND=../qrencode
+VALGRIND_COMMAND="libtool --mode=execute valgrind"
+VALGRIND_OPTIONS="--leak-check=full --show-reachable=yes"
+
+if [ "x$1" = 'xvalgrind' ]; then
+ COMMAND="$VALGRIND_COMMAND $VALGRIND_OPTIONS $COMMAND"
+fi
+
+repeatchar()
+{
+ printf %${2}s | tr ' ' ${1}
+}
+
+test_command_success()
+{
+ repeatchar ${1} ${2} | $COMMAND -o - -l L ${3} > /dev/null
+ if [ $? -ne 0 ]; then
+ echo "Failed to encode $fn.txt"
+ exit 1
+ fi
+}
+
+test_command_fail()
+{
+ repeatchar ${1} ${2} | $COMMAND -o - -l L ${3} > /dev/null
+ if [ $? -eq 0 ]; then
+ echo "Unexpectedly successed to encode '${1}'x'${2}' with '${3}'."
+ exit 1
+ else
+ echo "^^^this is the expected error. Everything OK."
+ fi
+}
+
+test_command_success '1' 7089
+test_command_success 'A' 4296
+test_command_success 'a' 2953
+test_command_success '\211' 3634 '-k'
+
+test_command_fail '1' 7090
+test_command_fail 'A' 4297
+test_command_fail 'a' 2954
+test_command_fail '\211' 3636 '-k'
+test_command_fail '1' 15000
diff --git a/genqrcode/tests/test_qrencode.c b/genqrcode/tests/test_qrencode.c
new file mode 100644
index 0000000000..589b9b18ef
--- /dev/null
+++ b/genqrcode/tests/test_qrencode.c
@@ -0,0 +1,1073 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "common.h"
+#include "../qrencode_inner.h"
+#include "../qrspec.h"
+#include "../mqrspec.h"
+#include "../qrinput.h"
+#include "../mask.h"
+#include "../rsecc.h"
+#include "../split.h"
+#include "decoder.h"
+
+static const char decodeAnTable[45] = {
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
+ 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
+ 'U', 'V', 'W', 'X', 'Y', 'Z', ' ', '$', '%', '*',
+ '+', '-', '.', '/', ':'
+};
+
+typedef struct {
+ char *str;
+ int version;
+ QRecLevel level;
+ QRencodeMode hint;
+ int casesensitive;
+} TestString;
+#define _countof(_Array) (sizeof(_Array) / sizeof(_Array[0]))
+
+#define drand(__scale__) ((__scale__) * (double)rand() / ((double)RAND_MAX + 1.0))
+
+static void test_qrraw_new(void)
+{
+ int i;
+ QRinput *stream;
+ char num[9] = "01234567";
+ QRRawCode *raw;
+
+ testStart("Test QRraw_new()");
+ stream = QRinput_new();
+ QRinput_setVersion(stream, 10);
+ QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_Q);
+ QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num);
+
+ raw = QRraw_new(stream);
+ assert_nonnull(raw, "Failed QRraw_new().\n");
+ assert_zero(raw->count, "QRraw.count = %d != 0\n", raw->count);
+ assert_equal(raw->version, 10, "QRraw.version was not as expected. (%d)\n", raw->version);
+ assert_equal(raw->dataLength, 19 * 6 + 20 * 2, "QRraw.dataLength was not as expected.\n");
+ assert_equal(raw->eccLength, 24 * 8, "QRraw.eccLength was not as expected.\n");
+ assert_equal(raw->b1, 6, "QRraw.b1 was not as expected.\n");
+ assert_equal(raw->blocks, 8, "QRraw.blocks was not as expected.\n");
+
+ for(i=0; i<raw->b1; i++) {
+ assert_equal(raw->rsblock[i].dataLength, 19, "QRraw.rsblock[%d].dataLength was not as expected. (%d)\n", i, raw->rsblock[i].dataLength);
+ }
+ for(i=raw->b1; i<raw->blocks; i++) {
+ assert_equal(raw->rsblock[i].dataLength, 20, "QRraw.rsblock[%d].dataLength was not as expected. (%d)\n", i, raw->rsblock[i].dataLength);
+ }
+ for(i=0; i<raw->blocks; i++) {
+ assert_equal(raw->rsblock[i].eccLength, 24, "QRraw.rsblock[%d].eccLength was not as expected. (%d)\n", i, raw->rsblock[i].eccLength);
+ }
+
+ QRinput_free(stream);
+ QRraw_free(raw);
+ testFinish();
+}
+
+static void test_iterate()
+{
+ int i;
+ QRinput *stream;
+ char num[9] = "01234567";
+ unsigned char *data;
+ QRRawCode *raw;
+ int err = 0;
+
+ testStart("Test getCode (1-L)");
+ stream = QRinput_new();
+ QRinput_setVersion(stream, 1);
+ QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_L);
+ QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num);
+
+ raw = QRraw_new(stream);
+ data = raw->datacode;
+ for(i=0; i<raw->dataLength; i++) {
+ if(data[i] != QRraw_getCode(raw)) {
+ err++;
+ }
+ }
+
+ QRinput_free(stream);
+ QRraw_free(raw);
+ testEnd(err);
+}
+
+static void test_iterate2()
+{
+ int i;
+ QRinput *stream;
+ char num[9] = "01234567";
+ QRRawCode *raw;
+ int err = 0;
+ unsigned char correct[] = {
+ 0x10, 0x11, 0xec, 0xec, 0x20, 0xec, 0x11, 0x11,
+ 0x0c, 0x11, 0xec, 0xec, 0x56, 0xec, 0x11, 0x11,
+ 0x61, 0x11, 0xec, 0xec, 0x80, 0xec, 0x11, 0x11,
+ 0xec, 0x11, 0xec, 0xec, 0x11, 0xec, 0x11, 0x11,
+ 0xec, 0x11, 0xec, 0xec, 0x11, 0xec, 0x11, 0x11,
+ 0xec, 0x11, 0xec, 0xec, 0x11, 0x11,
+ 0x5c, 0xde, 0x68, 0x68, 0x4d, 0xb3, 0xdb, 0xdb,
+ 0xd5, 0x14, 0xe1, 0xe1, 0x5b, 0x2a, 0x1f, 0x1f,
+ 0x49, 0xc4, 0x78, 0x78, 0xf7, 0xe0, 0x5b, 0x5b,
+ 0xc3, 0xa7, 0xc1, 0xc1, 0x5d, 0x9a, 0xea, 0xea,
+ 0x48, 0xad, 0x9d, 0x9d, 0x58, 0xb3, 0x3f, 0x3f,
+ 0x10, 0xdb, 0xbf, 0xbf, 0xeb, 0xec, 0x05, 0x05,
+ 0x98, 0x35, 0x83, 0x83, 0xa9, 0x95, 0xa6, 0xa6,
+ 0xea, 0x7b, 0x8d, 0x8d, 0x04, 0x3c, 0x08, 0x08,
+ 0x64, 0xce, 0x3e, 0x3e, 0x4d, 0x9b, 0x30, 0x30,
+ 0x4e, 0x65, 0xd6, 0xd6, 0xe4, 0x53, 0x2c, 0x2c,
+ 0x46, 0x1d, 0x2e, 0x2e, 0x29, 0x16, 0x27, 0x27
+ };
+
+ testStart("Test getCode (5-H)");
+ stream = QRinput_new();
+ QRinput_setVersion(stream, 5);
+ QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_H);
+ QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num);
+
+ raw = QRraw_new(stream);
+ for(i=0; i<raw->dataLength; i++) {
+ if(correct[i] != QRraw_getCode(raw)) {
+ err++;
+ }
+ }
+
+ QRinput_free(stream);
+ QRraw_free(raw);
+ testEnd(err);
+}
+
+static void print_filler(void)
+{
+ int width;
+ int version = 7;
+ unsigned char *frame;
+
+ puts("\nPrinting debug info of FrameFiller.");
+ width = QRspec_getWidth(version);
+ frame = FrameFiller_test(version);
+ if(frame == NULL) abort();
+
+ printFrame(width, frame);
+ free(frame);
+}
+
+static void test_filler(void)
+{
+ unsigned char *frame;
+ int i, j, w, e, length;
+
+ testStart("Frame filler test");
+ for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
+ length = QRspec_getDataLength(i, QR_ECLEVEL_L) * 8
+ + QRspec_getECCLength(i, QR_ECLEVEL_L) * 8
+ + QRspec_getRemainder(i);
+ frame = FrameFiller_test(i);
+ if(frame == NULL) {
+ assert_nonnull(frame, "Something wrong in version %d\n", i);
+ } else {
+ w = QRspec_getWidth(i);
+ e = 0;
+ for(j=0; j<w*w; j++) {
+ if(frame[j] == 0) e++;
+ }
+ assert_zero(e, "Not filled bit is found. (%d,%d)\n", j%w,j/w);
+ e = w * (w - 9 - ((i > 6)?3:0));
+ assert_equal(frame[e], (unsigned char)((length - 1) & 127) | 0x80,
+ "Number of cell does not match.\n");
+ free(frame);
+ }
+ }
+ testFinish();
+}
+
+static void print_fillerMQR(void)
+{
+ int width;
+ int version = 3;
+ unsigned char *frame;
+
+ puts("\nPrinting debug info of FrameFiller for Micro QR.");
+ for(version = 1; version <= MQRSPEC_VERSION_MAX; version++) {
+ width = MQRspec_getWidth(version);
+ frame = FrameFiller_testMQR(version);
+ if(frame == NULL) abort();
+
+ printFrame(width, frame);
+ }
+}
+
+static void test_fillerMQR(void)
+{
+ unsigned char *frame;
+ int i, j, w, e, length;
+
+ testStart("Micro QR Code Frame filler test");
+ for(i=1; i<=MQRSPEC_VERSION_MAX; i++) {
+ length = MQRspec_getDataLengthBit(i, QR_ECLEVEL_L)
+ + MQRspec_getECCLength(i, QR_ECLEVEL_L) * 8;
+ frame = FrameFiller_testMQR(i);
+ if(frame == NULL) {
+ assert_nonnull(frame, "Something wrong in version %d\n", i);
+ } else {
+ w = MQRspec_getWidth(i);
+ e = 0;
+ for(j=0; j<w*w; j++) {
+ if(frame[j] == 0) e++;
+ }
+ assert_zero(e, "Not filled bit is found. (%d,%d)\n", j%w,j/w);
+ if(i & 1) {
+ e = w * 9 + 1;
+ } else {
+ e = w * (w - 1) + 1;
+ }
+ assert_equal(frame[e], (unsigned char)((length - 1) & 127) | 0x80,
+ "Number of cell does not match in version %d.\n", i);
+ free(frame);
+ }
+ }
+ testFinish();
+}
+
+static void test_format(void)
+{
+ unsigned char *frame;
+ unsigned int format;
+ int width;
+ int i;
+ unsigned int decode;
+ int blacks, b1 = 0, b2 = 0;
+
+ testStart("Test format information(level L,mask 0)");
+ width = QRspec_getWidth(1);
+ frame = QRspec_newFrame(1);
+ if(frame == NULL) goto ABORT;
+ format = QRspec_getFormatInfo(1, QR_ECLEVEL_L);
+ blacks = Mask_writeFormatInformation(width, frame, 1, QR_ECLEVEL_L);
+ decode = 0;
+ for(i=0; i<15; i++) {
+ if((1<<i) & format) b2 += 2;
+ }
+ for(i=0; i<8; i++) {
+ decode = decode << 1;
+ decode |= frame[width * 8 + i + (i > 5)] & 1;
+ if(decode & 1) b1++;
+ }
+ for(i=0; i<7; i++) {
+ decode = decode << 1;
+ decode |= frame[width * ((6 - i) + (i < 1)) + 8] & 1;
+ if(decode & 1) b1++;
+ }
+ if(decode != format) {
+ printf("Upper-left format information is invalid.\n");
+ printf("%08x, %08x\n", format, decode);
+ testEnd(1);
+ return;
+ }
+ decode = 0;
+ for(i=0; i<7; i++) {
+ decode = decode << 1;
+ decode |= frame[width * (width - 1 - i) + 8] & 1;
+ if(decode & 1) b1++;
+ }
+ for(i=0; i<8; i++) {
+ decode = decode << 1;
+ decode |= frame[width * 8 + width - 8 + i] & 1;
+ if(decode & 1) b1++;
+ }
+ if(decode != format) {
+ printf("Bottom and right format information is invalid.\n");
+ printf("%08x, %08x\n", format, decode);
+ testEnd(1);
+ return;
+ }
+
+ if(b2 != blacks || b1 != b2) {
+ printf("Number of dark modules is incorrect.\n");
+ printf("Return value: %d, dark modules in frame: %d, should be: %d\n", blacks, b1, b2);
+ testEnd(1);
+ return;
+ }
+
+ free(frame);
+
+ABORT:
+ testEnd(0);
+}
+
+unsigned int m1pat[8][21] = {
+ {0x1fc77f, 0x105c41, 0x174c5d, 0x174b5d, 0x175b5d, 0x104241, 0x1fd57f,
+ 0x000000, 0x154512, 0x1a16a2, 0x0376ee, 0x19abb2, 0x04eee1, 0x001442,
+ 0x1fc111, 0x10444b, 0x175d5d, 0x174aae, 0x175ae5, 0x1043b8, 0x1fd2e5},
+ {0x1fdd7f, 0x104641, 0x17565d, 0x17415d, 0x17415d, 0x105841, 0x1fd57f,
+ 0x000a00, 0x146f25, 0x10bc08, 0x09dc44, 0x130118, 0x0e444b, 0x001ee8,
+ 0x1fdbbb, 0x104ee1, 0x1747f7, 0x174004, 0x17504f, 0x104912, 0x1fd84f},
+ {0x1fcb7f, 0x104f41, 0x17505d, 0x17585d, 0x17575d, 0x105141, 0x1fd57f,
+ 0x001300, 0x17c97c, 0x02b52c, 0x046a9f, 0x01083c, 0x03f290, 0x0017cc,
+ 0x1fcd60, 0x1057c5, 0x17512c, 0x175920, 0x175694, 0x104036, 0x1fde94},
+ {0x1fdb7f, 0x105441, 0x174d5d, 0x17585d, 0x174c5d, 0x104c41, 0x1fd57f,
+ 0x001800, 0x16e44b, 0x02b52c, 0x12f1f2, 0x1a258a, 0x03f290, 0x001ca1,
+ 0x1fd0d6, 0x1057c5, 0x174a41, 0x175496, 0x175694, 0x104b5b, 0x1fd322},
+ {0x1fd37f, 0x104741, 0x17475d, 0x175f5d, 0x175f5d, 0x105941, 0x1fd57f,
+ 0x001400, 0x1171f9, 0x0c8dcf, 0x15ed83, 0x108f20, 0x0dca73, 0x001f2f,
+ 0x1fda7c, 0x1040d9, 0x1759cf, 0x1741c3, 0x174188, 0x10472a, 0x1fd677},
+ {0x1fcd7f, 0x105741, 0x17505d, 0x17545d, 0x17475d, 0x104941, 0x1fd57f,
+ 0x001b00, 0x1059ce, 0x05a95d, 0x046a9f, 0x03001c, 0x0e444b, 0x001fec,
+ 0x1fcd60, 0x104bb4, 0x17412c, 0x174100, 0x17404f, 0x104816, 0x1fde94},
+ {0x1fdd7f, 0x105741, 0x17545d, 0x17445d, 0x17555d, 0x104f41, 0x1fd57f,
+ 0x000b00, 0x13fd97, 0x05a95d, 0x00f8d6, 0x028604, 0x0e444b, 0x001f2f,
+ 0x1fd9f2, 0x105bb4, 0x175365, 0x175718, 0x17404f, 0x1048d5, 0x1fda06},
+ {0x1fc77f, 0x104841, 0x174e5d, 0x174b5d, 0x174f5d, 0x105041, 0x1fd57f,
+ 0x000400, 0x12d7a0, 0x1a16a2, 0x0a527c, 0x1d39fb, 0x04eee1, 0x0010d0,
+ 0x1fc358, 0x10544b, 0x1749cf, 0x1758e7, 0x174ae5, 0x10472a, 0x1fd0ac}
+};
+
+static void test_encode(void)
+{
+ QRinput *stream;
+ char num[9] = "01234567";
+ unsigned char *frame;
+ int err = 0;
+ int x, y, w;
+ int mask;
+ QRcode *qrcode;
+
+ testStart("Test encode (1-M)");
+ stream = QRinput_new();
+ if(stream == NULL) goto ABORT;
+ QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num);
+ for(mask=0; mask<8; mask++) {
+ QRinput_setVersion(stream, 1);
+ QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_M);
+ qrcode = QRcode_encodeMask(stream, mask);
+ if(qrcode == NULL) goto ABORT;
+ w = qrcode->width;
+ frame = qrcode->data;
+ for(y=0; y<w; y++) {
+ for(x=0; x<w; x++) {
+ if(((m1pat[mask][y] >> (20-x)) & 1) != (frame[y*w+x]&1)) {
+ printf("Diff in mask=%d (%d,%d)\n", mask, x, y);
+ err++;
+ }
+ }
+ }
+ QRcode_free(qrcode);
+ }
+ QRinput_free(stream);
+ABORT:
+ testEnd(err);
+}
+
+static void test_encode2(void)
+{
+ QRcode *qrcode;
+
+ testStart("Test encode (2-H) (no padding test)");
+ qrcode = QRcode_encodeString("abcdefghijk123456789012", 0, QR_ECLEVEL_H, QR_MODE_8, 0);
+ testEndExp(qrcode->version == 2);
+ QRcode_free(qrcode);
+}
+
+static void test_encode3(void)
+{
+ QRcode *code1, *code2;
+ QRinput *input;
+
+ testStart("Compare encodeString and encodeInput");
+ code1 = QRcode_encodeString("0123456", 0, QR_ECLEVEL_L, QR_MODE_8, 0);
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_NUM, 7, (unsigned char *)"0123456");
+ code2 = QRcode_encodeInput(input);
+ testEnd(memcmp(code1->data, code2->data, code1->width * code1->width));
+
+ QRcode_free(code1);
+ QRcode_free(code2);
+ QRinput_free(input);
+}
+
+static void test_encodeNull(void)
+{
+ QRcode *qrcode;
+
+ testStart("Test encode NULL.");
+ qrcode = QRcode_encodeString(NULL, 0, QR_ECLEVEL_H, QR_MODE_8, 0);
+ assert_null(qrcode, "QRcode_encodeString() returned something.\n");
+ testFinish();
+ if(qrcode != NULL) QRcode_free(qrcode);
+}
+
+
+static void test_encodeEmpty(void)
+{
+ QRcode *qrcode;
+
+ testStart("Test encode an empty string.");
+ qrcode = QRcode_encodeString("", 0, QR_ECLEVEL_H, QR_MODE_8, 0);
+ assert_null(qrcode, "QRcode_encodeString() returned something.\n");
+ testFinish();
+ if(qrcode != NULL) QRcode_free(qrcode);
+}
+
+static void test_encodeNull8(void)
+{
+ QRcode *qrcode;
+
+ testStart("Test encode NULL.");
+ qrcode = QRcode_encodeString8bit(NULL, 0, QR_ECLEVEL_H);
+ assert_null(qrcode, "QRcode_encodeString8bit() returned something.\n");
+ testFinish();
+ if(qrcode != NULL) QRcode_free(qrcode);
+}
+
+
+static void test_encodeEmpty8(void)
+{
+ QRcode *qrcode;
+
+ testStart("Test encode an empty string.");
+ qrcode = QRcode_encodeString8bit("", 0, QR_ECLEVEL_H);
+ assert_null(qrcode, "QRcode_encodeString8bit() returned something.\n");
+ testFinish();
+ if(qrcode != NULL) QRcode_free(qrcode);
+}
+
+static void test_encodeLongData(void)
+{
+ QRinput *stream;
+ unsigned char data[7090];
+ int maxlength[4][4] = {{7089,5596,3993,3057},
+ {4296,3391,2420,1852},
+ {2953,2331,1663,1273},
+ {1817*2,1435*2,1024*2, 784*2}};
+ int i, l, len, ret;
+ QRcode *qrcode;
+
+ testStart("Encoding long data.");
+
+ for(i=QR_MODE_NUM; i<=QR_MODE_KANJI; i++) {
+ if(i != QR_MODE_KANJI) {
+ memset(data, '0', maxlength[i][0] + 1);
+ } else {
+ for(l=0; l<=maxlength[i][0]/2+1; l++) {
+ data[l*2] = 0x93; data[l*2+1] = 0x5f;
+ }
+ }
+ for(l=QR_ECLEVEL_L; l<=QR_ECLEVEL_H; l++) {
+ stream = QRinput_new2(0, l);
+ ret = QRinput_append(stream, i, maxlength[i][l], data);
+ assert_zero(ret, "Failed to add %d-byte %s to a QRinput\n", maxlength[i][l], modeStr[i]);
+ qrcode = QRcode_encodeInput(stream);
+ assert_nonnull(qrcode, "(QRcode_encodeInput) failed to encode %d-byte %s in level %d.\n", maxlength[i][l], modeStr[i], l);
+ if(qrcode != NULL) {
+ QRcode_free(qrcode);
+ }
+ QRinput_free(stream);
+
+ stream = QRinput_new2(0, l);
+ len = maxlength[i][l];
+ if(i == QR_MODE_KANJI) {
+ len += 2;
+ } else {
+ len += 1;
+ }
+ ret = QRinput_append(stream, i, len, data);
+ if(ret == 0) {
+ qrcode = QRcode_encodeInput(stream);
+ assert_null(qrcode, "(QRcode_encodeInput) incorrectly succeeded to encode %d-byte %s in level %d.\n", len, modeStr[i], l);
+ if(qrcode != NULL) {
+ printf("version: %d\n", qrcode->version);
+ QRcode_free(qrcode);
+ }
+ }
+ QRinput_free(stream);
+ }
+ }
+
+ testFinish();
+}
+
+static void test_encodeVer26Num(void)
+{
+ char data[3284];
+ QRcode *qrcode;
+
+ testStart("Encoding 3283 digits number. (issue #160)");
+
+ memset(data, '0', 3283);
+ data[3283] = '\0';
+ qrcode = QRcode_encodeString(data, 0, QR_ECLEVEL_L, QR_MODE_8, 0);
+ assert_nonnull(qrcode, "(QRcode_encodeString) failed to encode 3283 digits number in level L.\n");
+ assert_equal(qrcode->version, 26, "version number is %d (26 expected)\n", qrcode->version);
+ if(qrcode != NULL) {
+ QRcode_free(qrcode);
+ }
+
+ QRinput *input;
+ QRinput_List *list;
+
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(data, input, QR_MODE_8, 0);
+ list = input->head;
+ assert_equal(list->size, 3283, "chunk size is wrong. (%d, 3283 expected)\n", list->size);
+ QRinput_free(input);
+
+ testFinish();
+}
+
+static void test_01234567(void)
+{
+ QRinput *stream;
+ char num[9] = "01234567";
+ int i, err = 0;
+ QRcode *qrcode;
+ unsigned char correct[] = {
+0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x84, 0x03, 0x02, 0x03, 0x03, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x84, 0x03, 0x03, 0x03, 0x03, 0xc0, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x02, 0x02, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x02, 0x02, 0x02, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x01, 0x01, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1,
+0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x00, 0x01, 0xc0, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1,
+0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x91, 0x90, 0x91, 0x90, 0x91, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x85, 0x02, 0x02, 0x01, 0x01, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+0x85, 0x84, 0x85, 0x85, 0x85, 0x85, 0x91, 0x84, 0x84, 0x03, 0x02, 0x00, 0x01, 0x84, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84,
+0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x90, 0x03, 0x03, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
+0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x91, 0x03, 0x02, 0x03, 0x02, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x90, 0x02, 0x02, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,
+0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x91, 0x03, 0x03, 0x02, 0x02, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x81, 0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00,
+0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x84, 0x03, 0x03, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
+0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00,
+0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x02, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
+0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x84, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00,
+0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x85, 0x03, 0x03, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00};
+
+ testStart("Encode 01234567 in 1-M");
+ stream = QRinput_new2(1, QR_ECLEVEL_M);
+ QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num);
+ qrcode = QRcode_encodeInput(stream);
+ for(i=0; i<qrcode->width * qrcode->width; i++) {
+ if(qrcode->data[i] != correct[i]) {
+ err++;
+ }
+ }
+ testEnd(err);
+ QRinput_free(stream);
+ QRcode_free(qrcode);
+}
+
+static void print_01234567(void)
+{
+ QRinput *stream;
+ char num[9] = "01234567";
+ QRcode *qrcode;
+
+ puts("\nPrinting QR code of '01234567'.");
+ stream = QRinput_new2(1, QR_ECLEVEL_M);
+ QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)num);
+ qrcode = QRcode_encodeInput(stream);
+ printQRcode(qrcode);
+ QRinput_free(stream);
+ QRcode_free(qrcode);
+}
+
+static void test_invalid_input(void)
+{
+ QRinput *input;
+ QRcode *code;
+
+ testStart("Testing invalid input.");
+ input = QRinput_new();
+ QRinput_append(input, QR_MODE_AN, 5, (unsigned char *)"TEST1");
+ input->version = -1;
+ input->level = QR_ECLEVEL_L;
+ code = QRcode_encodeInput(input);
+ assert_null(code, "invalid version(-1) was not checked.\n");
+ if(code != NULL) QRcode_free(code);
+
+ input->version = 41;
+ input->level = QR_ECLEVEL_L;
+ code = QRcode_encodeInput(input);
+ assert_null(code, "invalid version(41) access was not checked.\n");
+ if(code != NULL) QRcode_free(code);
+
+ input->version = 1;
+ input->level = (QRecLevel)(QR_ECLEVEL_H + 1);
+ code = QRcode_encodeInput(input);
+ assert_null(code, "invalid level(H+1) access was not checked.\n");
+ if(code != NULL) QRcode_free(code);
+
+ input->version = 1;
+ input->level = (QRecLevel)-1;
+ code = QRcode_encodeInput(input);
+ assert_null(code, "invalid level(-1) access was not checked.\n");
+ if(code != NULL) QRcode_free(code);
+
+ QRinput_free(input);
+
+ testFinish();
+}
+
+static void test_struct_semilong(void)
+{
+ QRcode_List *codes, *list;
+ const char *str = "asdfasdfasdfasdfasdfASDFASDASDFASDFAsdfasdfasdfasdASDFASDFADSADadsfasdf";
+ int num, size;
+
+ testStart("Testing semi-long structured-append symbols");
+ codes = QRcode_encodeString8bitStructured(str, 1, QR_ECLEVEL_L);
+ list = codes;
+ num = 0;
+ while(list != NULL) {
+ num++;
+ assert_equal(list->code->version, 1, "version number is %d (1 expected)\n", list->code->version);
+ list = list->next;
+ }
+ size = QRcode_List_size(codes);
+ assert_equal(num, size, "QRcode_List_size returns wrong size?");
+ QRcode_List_free(codes);
+
+ codes = QRcode_encodeStringStructured(str, 1, QR_ECLEVEL_L, QR_MODE_8, 1);
+ list = codes;
+ num = 0;
+ while(list != NULL) {
+ num++;
+ assert_equal(list->code->version, 1, "version number is %d (1 expected)\n", list->code->version);
+ list = list->next;
+ }
+ size = QRcode_List_size(codes);
+ assert_equal(num, size, "QRcode_List_size returns wrong size?");
+ QRcode_List_free(codes);
+
+ testFinish();
+}
+
+static void test_struct_example(void)
+{
+ QRcode_List *codes, *list;
+ const char *str = "an example of four Structured Append symbols,";
+ int num;
+
+ testStart("Testing the example of structured-append symbols");
+ codes = QRcode_encodeString8bitStructured(str, 1, QR_ECLEVEL_M);
+ list = codes;
+ num = 0;
+ while(list != NULL) {
+ num++;
+ assert_equal(list->code->version, 1, "version number is %d (1 expected)\n", list->code->version);
+ list = list->next;
+ }
+ assert_equal(num, 4, "number of symbols is %d (4 expected).", num);
+ testFinish();
+ QRcode_List_free(codes);
+}
+
+static void test_null_free(void)
+{
+ testStart("Testing free NULL pointers");
+ assert_nothing(QRcode_free(NULL), "Check QRcode_free(NULL).\n");
+ assert_nothing(QRcode_List_free(NULL), "Check QRcode_List_free(NULL).\n");
+ assert_nothing(QRraw_free(NULL), "Check QRraw_free(NULL).\n");
+ testFinish();
+}
+
+static void test_encodeTooLongMQR(void)
+{
+ QRcode *code;
+ char *data[] = {"012345", "ABC0EFG", "0123456789", "0123456789ABCDEFG"};
+
+ testStart("Encode too large data for MQR.");
+
+ code = QRcode_encodeStringMQR(data[0], 1, QR_ECLEVEL_L, QR_MODE_8, 0);
+ assert_nonnull(code, "6 byte length numeric string should be accepted to version 2 or larger.\n");
+ assert_equal(code->version, 2, "6 byte length numeric string should be accepted to version 2.\n");
+ if(code != NULL) {
+ QRcode_free(code);
+ }
+
+ code = QRcode_encodeStringMQR(data[1], 2, QR_ECLEVEL_L, QR_MODE_8, 0);
+ assert_nonnull(code, "7 byte length alphanumeric string should be accepted to version 3 or larger.\n");
+ assert_equal(code->version, 3, "7 byte length alphanumeric string should be accepted to version 3.\n");
+ if(code != NULL) {
+ QRcode_free(code);
+ }
+
+ code = QRcode_encodeString8bitMQR(data[2], 3, QR_ECLEVEL_L);
+ assert_nonnull(code, "9 byte length 8bit string should be accepted to version 4.\n");
+ assert_equal(code->version, 4, "9 byte length 8bit string should be accepted to version 4.\n");
+ if(code != NULL) {
+ QRcode_free(code);
+ }
+
+ code = QRcode_encodeString8bitMQR(data[3], 4, QR_ECLEVEL_L);
+ assert_null(code, "16 byte length 8bit string was accepted to version 4.\n");
+ assert_equal(errno, ERANGE, "errno != ERANGE\n");
+ testFinish();
+
+ if(code != NULL) {
+ printQRcode(code);
+ QRcode_free(code);
+ }
+}
+
+static void test_mqrraw_new(void)
+{
+ QRinput *stream;
+ char *num = "01234";
+ unsigned char datacode[] = {0xa0, 0x62, 0x20};
+ MQRRawCode *raw;
+
+ testStart("Test MQRRaw_new()");
+ stream = QRinput_newMQR(1, QR_ECLEVEL_L);
+ QRinput_append(stream, QR_MODE_NUM, 5, (unsigned char *)num);
+
+ raw = MQRraw_new(stream);
+ assert_nonnull(raw, "Failed MQRraw_new().\n");
+ assert_zero(raw->count, "MQRraw.count = %d != 0\n", raw->count);
+ assert_equal(raw->version, 1, "MQRraw.version was not as expected. (%d)\n", raw->version);
+ assert_equal(raw->dataLength, 3, "MQRraw.dataLength was not as expected.\n");
+ assert_equal(raw->eccLength, 2, "MQRraw.eccLength was not as expected.\n");
+ assert_zero(memcmp(raw->datacode, datacode, 3), "Datacode doesn't match.\n");
+
+
+ QRinput_free(stream);
+ MQRraw_free(raw);
+ testFinish();
+}
+
+static void test_encodeData(void)
+{
+ QRcode *qrcode;
+
+ testStart("Test QRencode_encodeData.");
+ qrcode = QRcode_encodeData(0, NULL, 0, QR_ECLEVEL_H);
+ assert_null(qrcode, "QRcode_encodeData(NULL, 0) returned something.\n");
+ if(qrcode != NULL) QRcode_free(qrcode);
+
+ qrcode = QRcode_encodeData(10, (unsigned char*)"test\0\0test", 0, QR_ECLEVEL_H);
+ assert_nonnull(qrcode, "QRcode_encodeData() failed.\n");
+ if(qrcode != NULL) QRcode_free(qrcode);
+
+ testFinish();
+}
+
+static void test_formatInfo(void)
+{
+ QRcode *qrcode;
+ QRecLevel level;
+ int mask;
+ int ret;
+
+ testStart("Test format info in QR code.");
+ qrcode = QRcode_encodeString("AC-42", 1, QR_ECLEVEL_H, QR_MODE_8, 1);
+ ret = QRcode_decodeFormat(qrcode, &level, &mask);
+ assert_zero(ret, "Failed to decode.\n");
+ assert_equal(level, QR_ECLEVEL_H, "Decoded format is wrong.\n");
+
+ if(qrcode != NULL) QRcode_free(qrcode);
+
+ testFinish();
+}
+
+static void test_formatInfoMQR(void)
+{
+ QRcode *qrcode;
+ QRecLevel level;
+ int version, mask;
+ int i, ret;
+
+ testStart("Test format info in Micro QR code.");
+ for(i=0; i<8; i++) {
+ qrcode = QRcode_encodeStringMQR("1",
+ MQRformat[i].version,
+ MQRformat[i].level,
+ QR_MODE_8, 1);
+ ret = QRcode_decodeFormatMQR(qrcode, &version, &level, &mask);
+ assert_zero(ret, "Failed to decode.\n");
+ assert_equal(MQRformat[i].version, version, "Decoded verion is wrong.\n");
+ assert_equal(MQRformat[i].level, level, "Decoded level is wrong.\n");
+ QRcode_free(qrcode);
+ }
+
+ testFinish();
+}
+
+static void test_decodeSimple(void)
+{
+ char *str = "AC-42";
+ QRcode *qrcode;
+ QRdata *qrdata;
+
+ testStart("Test code words.");
+ qrcode = QRcode_encodeString(str, 1, QR_ECLEVEL_H, QR_MODE_8, 1);
+ qrdata = QRcode_decode(qrcode);
+
+ assert_nonnull(qrdata, "Failed to decode.\n");
+ if(qrdata != NULL) {
+ assert_equal(strlen(str), qrdata->size, "Lengths of input/output mismatched: %d, expected %d.\n", qrdata->size, (int)strlen(str));
+ assert_zero(strncmp(str, (char *)(qrdata->data), qrdata->size), "Decoded data %s is different from the original %s\n", qrdata->data, str);
+ }
+ if(qrdata != NULL) QRdata_free(qrdata);
+ if(qrcode != NULL) QRcode_free(qrcode);
+
+ testFinish();
+}
+
+
+static void test_decodeLong(void)
+{
+ char *str = "12345678901234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ?????????????";
+ QRcode *qrcode;
+ QRdata *qrdata;
+
+ testStart("Test code words (long, splitted).");
+ qrcode = QRcode_encodeString(str, 0, QR_ECLEVEL_H, QR_MODE_8, 1);
+ qrdata = QRcode_decode(qrcode);
+
+ assert_nonnull(qrdata, "Failed to decode.\n");
+ if(qrdata != NULL) {
+ assert_equal(strlen(str), qrdata->size, "Lengths of input/output mismatched.\n");
+ assert_zero(strncmp(str, (char *)(qrdata->data), qrdata->size), "Decoded data %s is different from the original %s\n", qrdata->data, str);
+ }
+ if(qrdata != NULL) QRdata_free(qrdata);
+ if(qrcode != NULL) QRcode_free(qrcode);
+
+ testFinish();
+}
+
+static void test_decodeVeryLong(void)
+{
+ char str[4000];
+ int i;
+ QRcode *qrcode;
+ QRdata *qrdata;
+
+ testStart("Test code words (very long string).");
+
+ for(i=0; i<3999; i++) {
+ str[i] = decodeAnTable[(int)drand(45)];
+ }
+ str[3999] = '\0';
+
+ qrcode = QRcode_encodeString(str, 0, QR_ECLEVEL_L, QR_MODE_8, 0);
+ qrdata = QRcode_decode(qrcode);
+
+ assert_nonnull(qrdata, "Failed to decode.\n");
+ if(qrdata != NULL) {
+ assert_equal(strlen(str), qrdata->size, "Lengths of input/output mismatched.\n");
+ assert_zero(strncmp(str, (char *)(qrdata->data), qrdata->size), "Decoded data %s is different from the original %s\n", qrdata->data, str);
+ }
+ if(qrdata != NULL) QRdata_free(qrdata);
+ if(qrcode != NULL) QRcode_free(qrcode);
+
+ testFinish();
+}
+
+static void test_decodeShortMQR(void)
+{
+ char str[]="55";
+ QRcode *qrcode;
+ QRdata *qrdata;
+ int i;
+
+ testStart("Test code words (MQR).");
+ for(i=0; i<8; i++) {
+ qrcode = QRcode_encodeStringMQR(str,
+ MQRformat[i].version,
+ MQRformat[i].level,
+ QR_MODE_8, 1);
+ qrdata = QRcode_decodeMQR(qrcode);
+
+ assert_nonnull(qrdata, "Failed to decode.\n");
+ assert_zero(strcmp((char *)qrdata->data, str), "Decoded data (%s) mismatched (%s)\n", (char *)qrdata->data, str);
+ if(qrdata != NULL) QRdata_free(qrdata);
+ if(qrcode != NULL) QRcode_free(qrcode);
+ }
+
+ testFinish();
+}
+
+static void test_oddBitCalcMQR(void)
+{
+ /* test issue #25 (odd bits calculation bug) */
+ /* test pattern contributed by vlad417 */
+ TestString tests[] = {
+ {"46194", 1, QR_ECLEVEL_L, QR_MODE_8, 1},
+ {"WBA5Y47YPQQ", 3, QR_ECLEVEL_L, QR_MODE_8, 1}
+ };
+ QRcode *qrcode;
+ QRdata *qrdata;
+ int i;
+
+ testStart("Odd bits calculation bug checking (MQR).");
+
+ for(i=0; i<_countof(tests); i++) {
+ qrcode = QRcode_encodeStringMQR(tests[i].str,
+ tests[i].version,
+ tests[i].level,
+ tests[i].hint,
+ tests[i].casesensitive);
+ assert_nonnull(qrcode, "Failed to encode: %s\n", tests[i].str);
+ if(qrcode == NULL) continue;
+ qrdata = QRcode_decodeMQR(qrcode);
+ assert_nonnull(qrdata, "Failed to decode.\n");
+ assert_zero(strcmp((char *)qrdata->data, tests[i].str), "Decoded data (%s) mismatched (%s)\n", (char *)qrdata->data, tests[i].str);
+ if(qrdata != NULL) QRdata_free(qrdata);
+ QRcode_free(qrcode);
+ }
+
+ testFinish();
+}
+
+static void test_invalid_inputMQR(void)
+{
+ QRinput *input;
+ QRcode *code;
+
+ testStart("Testing invalid input (MQR).");
+ input = QRinput_newMQR(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_AN, 5, (unsigned char *)"TEST1");
+ input->version = -1;
+ input->level = QR_ECLEVEL_L;
+ code = QRcode_encodeInput(input);
+ assert_null(code, "invalid version(-1) was not checked.\n");
+ if(code != NULL) QRcode_free(code);
+
+ input->version = 5;
+ input->level = QR_ECLEVEL_L;
+ code = QRcode_encodeInput(input);
+ assert_null(code, "invalid version(5) access was not checked.\n");
+ if(code != NULL) QRcode_free(code);
+
+ input->version = 1;
+ input->level = (QRecLevel)(QR_ECLEVEL_H);
+ code = QRcode_encodeInput(input);
+ assert_null(code, "invalid level(H) access was not checked.\n");
+ if(code != NULL) QRcode_free(code);
+
+ input->version = 1;
+ input->level = (QRecLevel)-1;
+ code = QRcode_encodeInput(input);
+ assert_null(code, "invalid level(-1) access was not checked.\n");
+ if(code != NULL) QRcode_free(code);
+
+ QRinput_free(input);
+
+ testFinish();
+}
+
+static void test_mqrencode(void)
+{
+ char *str = "MICROQR";
+ char pattern[] = {
+ "#######_#_#_#_#"
+ "#_____#_#__####"
+ "#_###_#_#_####_"
+ "#_###_#_#__##_#"
+ "#_###_#___#__##"
+ "#_____#____#_#_"
+ "#######__##_#_#"
+ "_________#__#__"
+ "#___#__####_#_#"
+ "_#######_#_##_#"
+ "##___#_#____#__"
+ "_##_#_####____#"
+ "#__###___#__##_"
+ "_###_#_###_#_#_"
+ "##____####_###_"
+ };
+ QRcode qrcode;
+ QRdata *qrdata;
+ unsigned char *frame;
+ int i;
+
+ testStart("Encoding test (MQR).");
+
+ qrcode.width = 15;
+ qrcode.version = 3;
+
+ frame = MQRspec_newFrame(qrcode.version);
+ for(i=0; i<225; i++) {
+ frame[i] ^= (pattern[i] == '#')?1:0;
+ }
+
+ qrcode.data = frame;
+ qrdata = QRcode_decodeMQR(&qrcode);
+ assert_equal(qrdata->version, 3, "Format info decoder returns wrong version number: %d (%d expected)\n", qrdata->version, 3);
+ assert_equal(qrdata->level, 1, "Format info decoder returns wrong level: %d (%d expected)\n", qrdata->level, 1);
+ assert_zero(strcmp((char *)qrdata->data, str), "Decoded data (%s) mismatched (%s)\n", (char *)qrdata->data, str);
+
+ QRdata_free(qrdata);
+ free(frame);
+
+ testFinish();
+}
+
+static void test_apiversion(void)
+{
+ int major_version, minor_version, micro_version;
+ char *str, *str2;
+
+ testStart("API Version check");
+ QRcode_APIVersion(&major_version, &minor_version, &micro_version);
+ assert_equal(major_version, MAJOR_VERSION, "Major version number mismatched: %d (%d expected)\n", major_version, MAJOR_VERSION);
+ assert_equal(minor_version, MINOR_VERSION, "Minor version number mismatched: %d (%d expected)\n", minor_version, MINOR_VERSION);
+ assert_equal(micro_version, MICRO_VERSION, "Micro version number mismatched: %d (%d expected)\n", micro_version, MICRO_VERSION);
+ str = QRcode_APIVersionString();
+ str2 = QRcode_APIVersionString();
+ assert_zero(strcmp(VERSION, str), "Version string mismatched: %s (%s expected)\n", str, VERSION);
+ assert_equal(str, str2, "Version strings are not identical.");
+ testFinish();
+}
+
+int main(int argc, char **argv)
+{
+ int tests = 33;
+ testInit(tests);
+ test_iterate();
+ test_iterate2();
+ test_filler();
+ test_format();
+ test_encode();
+ test_encode2();
+ test_encode3();
+ test_encodeNull();
+ test_encodeEmpty();
+ test_encodeNull8();
+ test_encodeEmpty8();
+ test_encodeLongData();
+ test_encodeVer26Num();
+ test_01234567();
+ test_invalid_input();
+ test_struct_example();
+ test_struct_semilong();
+ test_null_free();
+ test_qrraw_new();
+ test_mqrraw_new();
+ test_encodeData();
+ test_formatInfo();
+ test_decodeSimple();
+ test_decodeLong();
+ test_decodeVeryLong();
+ test_fillerMQR();
+ test_formatInfoMQR();
+ test_encodeTooLongMQR();
+ test_decodeShortMQR();
+ test_oddBitCalcMQR();
+ test_invalid_inputMQR();
+ test_mqrencode();
+ test_apiversion();
+ testReport(tests);
+
+ if(argc > 1) {
+ print_filler();
+ print_01234567();
+ print_fillerMQR();
+ }
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_qrinput.c b/genqrcode/tests/test_qrinput.c
new file mode 100644
index 0000000000..2aab36a8b6
--- /dev/null
+++ b/genqrcode/tests/test_qrinput.c
@@ -0,0 +1,1130 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "common.h"
+#include "../qrinput.h"
+#include "../qrencode_inner.h"
+#include "../split.h"
+#include "decoder.h"
+
+/* taken from the Table 7 of JIS X0510:2018 (pp. 31-34) */
+static int maxCharacterLengths[40][4] = {
+ { 41, 25, 17, 10}, /* ver 1 */
+ { 77, 47, 32, 20}, /* ver 2 */
+ { 127, 77, 53, 32}, /* ver 3 */
+ { 187, 114, 78, 48}, /* ver 4 */
+ { 255, 154, 106, 65}, /* ver 5 */
+ { 322, 195, 134, 82}, /* ver 6 */
+ { 370, 224, 154, 95}, /* ver 7 */
+ { 461, 279, 192, 118}, /* ver 8 */
+ { 552, 335, 230, 141}, /* ver 9 */
+ { 652, 395, 271, 167}, /* ver 10 */
+ { 772, 468, 321, 198}, /* ver 11 */
+ { 883, 535, 367, 226}, /* ver 12 */
+ {1022, 619, 425, 262}, /* ver 13 */
+ {1101, 667, 458, 282}, /* ver 14 */
+ {1250, 758, 520, 320}, /* ver 15 */
+ {1408, 854, 586, 361}, /* ver 16 */
+ {1548, 938, 644, 397}, /* ver 17 */
+ {1725, 1046, 718, 442}, /* ver 18 */
+ {1903, 1153, 792, 488}, /* ver 19 */
+ {2061, 1249, 858, 528}, /* ver 20 */
+ {2232, 1352, 929, 572}, /* ver 21 */
+ {2409, 1460, 1003, 618}, /* ver 22 */
+ {2620, 1588, 1091, 672}, /* ver 23 */
+ {2812, 1704, 1171, 721}, /* ver 24 */
+ {3057, 1853, 1273, 784}, /* ver 25 */
+ {3283, 1990, 1367, 842}, /* ver 26 */
+ {3517, 2132, 1465, 902}, /* ver 27 */
+ {3669, 2223, 1528, 940}, /* ver 28 */
+ {3909, 2369, 1628, 1002}, /* ver 29 */
+ {4158, 2520, 1732, 1066}, /* ver 30 */
+ {4417, 2677, 1840, 1132}, /* ver 31 */
+ {4686, 2840, 1952, 1201}, /* ver 32 */
+ {4965, 3009, 2068, 1273}, /* ver 33 */
+ {5253, 3183, 2188, 1347}, /* ver 34 */
+ {5529, 3351, 2303, 1417}, /* ver 35 */
+ {5836, 3537, 2431, 1496}, /* ver 36 */
+ {6153, 3729, 2563, 1577}, /* ver 37 */
+ {6479, 3927, 2699, 1661}, /* ver 38 */
+ {6743, 4087, 2809, 1729}, /* ver 39 */
+ {7089, 4296, 2953, 1817} /* ver 40 */
+};
+
+static int encodeAndCheckBStream(int mqr, int version, QRecLevel level, QRencodeMode mode, char *data, char *correct)
+{
+ QRinput *input;
+ BitStream *bstream;
+ int ret;
+
+ if(mqr) {
+ input = QRinput_newMQR(version, level);
+ } else {
+ input = QRinput_new2(version, level);
+ }
+ QRinput_append(input, mode, strlen(data), (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_getBitStream(input, bstream);
+ ret = cmpBin(correct, bstream);
+ if(ret) {
+ printf("result : ");
+ printBstream(bstream);
+ printf("correct: %s\n", correct);
+ }
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ return ret;
+}
+
+static int mergeAndCheckBStream(int mqr, QRencodeMode mode, char *data, char *correct)
+{
+ QRinput *input;
+ BitStream *bstream;
+ int ret;
+
+ if(mqr) {
+ input = QRinput_newMQR(1, QR_ECLEVEL_L);
+ } else {
+ input = QRinput_new();
+ }
+ QRinput_append(input, mode, strlen(data), (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ ret = cmpBin(correct, bstream);
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ return ret;
+}
+
+static void test_encodeKanji(void)
+{
+ char str[5]= {0x93, 0x5f, 0xe4, 0xaa, 0x00};
+ char *correct = "10000000001001101100111111101010101010";
+
+ testStart("Encoding kanji stream.");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_KANJI, str, correct));
+}
+
+static void test_encode8(void)
+{
+ char str[] = "AC-42";
+ char correct[] = "0100000001010100000101000011001011010011010000110010";
+
+ testStart("Encoding 8bit stream.");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_8, str, correct));
+}
+
+static void test_encode8_versionup(void)
+{
+ QRinput *stream;
+ BitStream *bstream;
+ char *str;
+ int version;
+
+ testStart("Encoding 8bit stream. (auto-version up test)");
+ str = (char *)malloc(2900);
+ memset(str, 0xff, 2900);
+ stream = QRinput_new();
+ bstream = BitStream_new();
+ QRinput_append(stream, QR_MODE_8, 2900, (unsigned char *)str);
+ QRinput_mergeBitStream(stream, bstream);
+ version = QRinput_getVersion(stream);
+ assert_equal(version, 40, "Version is %d (40 expected).\n", version);
+ testFinish();
+ QRinput_free(stream);
+ BitStream_free(bstream);
+ free(str);
+}
+
+static void test_encodeAn(void)
+{
+ char *str = "AC-42";
+ char correct[] = "00100000001010011100111011100111001000010";
+
+ testStart("Encoding alphabet-numeric stream.");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_AN, str, correct));
+}
+
+static void test_encodeAn2(void)
+{
+ QRinput *stream;
+ char str[] = "!,;$%";
+ int ret;
+
+ testStart("Encoding INVALID alphabet-numeric stream.");
+ stream = QRinput_new();
+ ret = QRinput_append(stream, QR_MODE_AN, 5, (unsigned char *)str);
+ testEnd(!ret);
+ QRinput_free(stream);
+}
+
+static void test_encodeNumeric(void)
+{
+ char *str = "01234567";
+ char correct[] = "00010000001000000000110001010110011000011";
+
+ testStart("Encoding numeric stream. (8 digits)");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_NUM, str, correct));
+}
+
+static void test_encodeNumeric_versionup(void)
+{
+ QRinput *stream;
+ BitStream *bstream;
+ char *str;
+ int version;
+
+ testStart("Encoding numeric stream. (auto-version up test)");
+ str = (char *)malloc(1050);
+ memset(str, '1', 1050);
+ stream = QRinput_new2(0, QR_ECLEVEL_L);
+ bstream = BitStream_new();
+ QRinput_append(stream, QR_MODE_NUM, 1050, (unsigned char *)str);
+ QRinput_mergeBitStream(stream, bstream);
+ version = QRinput_getVersion(stream);
+ assert_equal(version, 14, "Version is %d (14 expected).", version);
+ testFinish();
+ QRinput_free(stream);
+ BitStream_free(bstream);
+ free(str);
+}
+
+static void test_encodeNumericPadded(void)
+{
+ char *str = "01234567";
+ char *correct;
+ char *correctHead = "000100000010000000001100010101100110000110000000";
+ int i, ret;
+
+ testStart("Encoding numeric stream. (8 digits)(padded)");
+ correct = (char *)malloc(19 * 8 + 1);
+ correct[0] = '\0';
+ strcat(correct, correctHead);
+ for(i=0; i<13; i++) {
+ strcat(correct, (i&1)?"00010001":"11101100");
+ }
+ ret = encodeAndCheckBStream(0, 0, QR_ECLEVEL_L, QR_MODE_NUM, str, correct);
+ testEnd(ret);
+
+ free(correct);
+}
+
+static void test_encodeNumericPadded2(void)
+{
+ char *str = "0123456";
+ char *correct;
+ char *correctHead = "000100000001110000001100010101100101100000000000";
+ int i, ret;
+
+ testStart("Encoding numeric stream. (7 digits)(padded)");
+ correct = (char *)malloc(19 * 8 + 1);
+ correct[0] = '\0';
+ strcat(correct, correctHead);
+ for(i=0; i<13; i++) {
+ strcat(correct, (i&1)?"00010001":"11101100");
+ }
+ ret = encodeAndCheckBStream(0, 0, QR_ECLEVEL_L, QR_MODE_NUM, str, correct);
+ testEnd(ret);
+
+ free(correct);
+}
+
+static void test_padding(void)
+{
+ QRinput *input;
+ BitStream *bstream;
+ int i, size;
+ char data[] = "0123456789ABCDeFG";
+ unsigned char c;
+
+ testStart("Padding bit check. (less than 5 bits)");
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, 17, (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_getBitStream(input, bstream);
+ size = BitStream_size(bstream);
+ assert_equal(size, 152, "# of bit is incorrect (%d != 152).\n", size);
+ c = 0;
+ for(i=0; i<4; i++) {
+ c += bstream->data[size - i - 1];
+ }
+ assert_zero(c, "Padding bits are not zero.");
+ testFinish();
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+}
+
+static void test_padding2(void)
+{
+ QRinput *input;
+ BitStream *bstream;
+ int i, size, ret;
+ char data[] = "0123456789ABCDeF";
+ char correct[153];
+ unsigned char c;
+
+ testStart("Padding bit check. (1 or 2 padding bytes)");
+
+ /* 16 byte data (4 bit terminator and 1 byte padding) */
+ memset(correct, 0, 153);
+ memcpy(correct, "010000010000", 12);
+ for(size=0; size<16; size++) {
+ c = 0x80;
+ for(i=0; i<8; i++) {
+ correct[size * 8 + i + 12] = (data[size]&c)?'1':'0';
+ c = c >> 1;
+ }
+ }
+ memcpy(correct + 140, "000011101100", 12);
+
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, 16, (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_getBitStream(input, bstream);
+ size = BitStream_size(bstream);
+ assert_equal(size, 152, "16byte: # of bit is incorrect (%d != 152).\n", size);
+ ret = ncmpBin(correct, bstream, 152);
+ assert_zero(ret, "Padding bits incorrect.\n");
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ /* 15 byte data (4 bit terminator and 2 byte paddings) */
+
+ memcpy(correct, "010000001111", 12);
+ memcpy(correct + 132, "00001110110000010001", 20);
+
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, 15, (unsigned char *)data);
+ bstream = BitStream_new();
+ QRinput_getBitStream(input, bstream);
+ size = BitStream_size(bstream);
+ assert_equal(size, 152, "15byte: # of bit is incorrect (%d != 152).\n", size);
+ ret = ncmpBin(correct, bstream, 152);
+ assert_zero(ret, "Padding bits incorrect.\n");
+
+ testFinish();
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+}
+
+static void test_encodeNumeric2(void)
+{
+ char *str = "0123456789012345";
+ char *correct = "00010000010000000000110001010110011010100110111000010100111010100101";
+
+ testStart("Encoding numeric stream. (16 digits)");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_NUM, str, correct));
+}
+
+static void test_encodeNumeric3(void)
+{
+ char *str = "0123456";
+ char *correct = "0001 0000000111 0000001100 0101011001 0110";
+
+ testStart("Encoding numeric stream. (7 digits)");
+ testEnd(mergeAndCheckBStream(0, QR_MODE_NUM, str, correct));
+}
+
+static void test_encodeAnNum(void)
+{
+ QRinput *input;
+ BitStream *bstream;
+
+ testStart("Bit length check of alpha-numeric stream. (11 + 12)");
+ input = QRinput_new();
+ QRinput_append(input, QR_MODE_AN, 11, (unsigned char *)"ABCDEFGHIJK");
+ QRinput_append(input, QR_MODE_NUM, 12, (unsigned char *)"123456789012");
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ testEndExp(BitStream_size(bstream) == 128);
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ testStart("Bit length check of alphabet stream. (23)");
+ input = QRinput_new();
+ QRinput_append(input, QR_MODE_AN, 23, (unsigned char *)"ABCDEFGHIJK123456789012");
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ testEndExp(BitStream_size(bstream) == 140);
+ QRinput_free(input);
+ BitStream_free(bstream);
+}
+
+static void test_struct_listop(void)
+{
+ QRinput_Struct *s;
+ QRinput *inputs[5];
+ QRinput_InputList *l;
+ int i, ret;
+
+ testStart("QRinput_Struct list operation test.");
+ s = QRinput_Struct_new();
+ QRinput_Struct_setParity(s, 10);
+ assert_nonnull(s, "QRinput_Struct_new() failed.");
+ assert_equal(s->parity, 10, "QRinput_Struct_setParity() failed.");
+
+ for(i=0; i<5; i++) {
+ inputs[i] = QRinput_new();
+ QRinput_append(inputs[i], QR_MODE_AN, 5, (unsigned char *)"ABCDE");
+ ret = QRinput_Struct_appendInput(s, inputs[i]);
+ }
+ assert_equal(ret, 5, "QRinput_Struct_appendInput() returns wrong num?");
+ assert_equal(s->size, 5, "QRiput_Struct.size counts wrong number.");
+
+ l = s->head;
+ i = 0;
+ while(l != NULL) {
+ assert_equal(l->input, inputs[i], "QRinput_Struct input list order would be wrong?");
+ l = l->next;
+ i++;
+ }
+
+ QRinput_Struct_free(s);
+ testFinish();
+}
+
+static void test_insertStructuredAppendHeader(void)
+{
+ QRinput *stream;
+ char correct[] = "0011000011111010010101000000000101000001";
+ BitStream *bstream;
+ int ret;
+
+ testStart("Insert a structured-append header");
+ stream = QRinput_new();
+ bstream = BitStream_new();
+ QRinput_append(stream, QR_MODE_8, 1, (unsigned char *)"A");
+ ret = QRinput_insertStructuredAppendHeader(stream, 16, 1, 0xa5);
+ assert_zero(ret, "QRinput_insertStructuredAppendHeader() returns nonzero.\n");
+ QRinput_mergeBitStream(stream, bstream);
+ assert_nonnull(bstream->data, "Bstream->data is null.");
+ assert_zero(cmpBin(correct, bstream), "bitstream is wrong.");
+ testFinish();
+
+ QRinput_free(stream);
+ BitStream_free(bstream);
+}
+
+static void test_insertStructuredAppendHeader_error(void)
+{
+ QRinput *stream;
+ int ret;
+
+ testStart("Insert a structured-append header (errors expected)");
+ stream = QRinput_new();
+ QRinput_append(stream, QR_MODE_8, 1, (unsigned char *)"A");
+ ret = QRinput_insertStructuredAppendHeader(stream, 17, 1, 0xa5);
+ assert_equal(-1, ret, "QRinput_insertStructuredAppendHeader() returns 0.");
+ assert_equal(EINVAL, errno, "errno is not set correctly (%d returned).", errno);
+ ret = QRinput_insertStructuredAppendHeader(stream, 16, 17, 0xa5);
+ assert_equal(-1, ret, "QRinput_insertStructuredAppendHeader() returns 0.");
+ assert_equal(EINVAL, errno, "errno is not set correctly (%d returned).", errno);
+ ret = QRinput_insertStructuredAppendHeader(stream, 16, 0, 0xa5);
+ assert_equal(-1, ret, "QRinput_insertStructuredAppendHeader() returns 0.");
+ assert_equal(EINVAL, errno, "errno is not set correctly (%d returned).", errno);
+ testFinish();
+
+ QRinput_free(stream);
+}
+
+static void test_struct_insertStructuredAppendHeaders(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ QRinput_InputList *p;
+ int i;
+
+ testStart("Insert structured-append headers to a QRinput_Struct.");
+ s = QRinput_Struct_new();
+ for(i=0; i<10; i++) {
+ input = QRinput_new();
+ QRinput_append(input, QR_MODE_8, 1, (unsigned char *)"A");
+ QRinput_Struct_appendInput(s, input);
+ }
+ QRinput_Struct_insertStructuredAppendHeaders(s);
+ p = s->head;
+ i = 1;
+ while(p != NULL) {
+ assert_equal(p->input->head->mode, QR_MODE_STRUCTURE, "a structured-append header is not inserted.");
+ assert_equal(p->input->head->data[0], 10, "size of the structured-header is wrong: #%d, %d should be %d\n", i, p->input->head->data[0], 10);
+ assert_equal(p->input->head->data[1], i, "index of the structured-header is wrong: #%d, %d should be %d\n", i, p->input->head->data[1], i);
+ assert_equal(p->input->head->data[2], 0, "parity of the structured-header is wrong: #%d\n", i);
+ p = p->next;
+ i++;
+ }
+ testFinish();
+ QRinput_Struct_free(s);
+}
+
+static int check_lengthOfCode(QRencodeMode mode, char *data, int size, int version)
+{
+ QRinput *input;
+ BitStream *b;
+ size_t bits;
+ int bytes;
+
+ input = QRinput_new();
+ QRinput_setVersion(input, version);
+ QRinput_append(input, mode, size, (unsigned char *)data);
+ b = BitStream_new();
+ QRinput_mergeBitStream(input, b);
+ bits = BitStream_size(b);
+ bytes = QRinput_lengthOfCode(mode, version, bits);
+ QRinput_free(input);
+ BitStream_free(b);
+
+ return bytes;
+}
+
+static void test_lengthOfCode_num(void)
+{
+ int i, bytes;
+ char *data;
+
+ data = (char *)malloc(8000);
+ for(i=0; i<8000; i++) {
+ data[i] = '0' + i % 10;
+ }
+
+ testStart("Checking length of code (numeric)");
+ for(i=1; i<=9; i++) {
+ bytes = check_lengthOfCode(QR_MODE_NUM, data, i, 1);
+ assert_equal(i, bytes, "lengthOfCode failed. (QR_MODE_NUM, version:1, size:%d)\n", i);
+ }
+ for(i=1023; i<=1025; i++) {
+ bytes = check_lengthOfCode(QR_MODE_NUM, data, i, 1);
+ assert_equal(1023, bytes, "lengthOfCode failed. (QR_MODE_NUM, version:1, size:%d)\n", i);
+ }
+ testFinish();
+ free(data);
+}
+
+static void test_lengthOfCode_kanji(void)
+{
+ int i, bytes;
+ unsigned char str[12]= {0x93, 0x5f, 0xe4, 0xaa, 0x81, 0x40, 0x9f, 0xfc, 0xe0, 0x40, 0xeb, 0xbf};
+
+ testStart("Checking length of code (kanji)");
+ for(i=2; i<=12; i+=2) {
+ bytes = check_lengthOfCode(QR_MODE_KANJI, (char *)str, i, 1);
+ assert_equal(i, bytes, "lengthOfCode failed. (QR_MODE_KANJI, version:1, size:%d)\n", i);
+ }
+ testFinish();
+}
+
+static void test_struct_split_example(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ QRinput_InputList *e;
+ QRinput_List *l;
+ const char *str[4] = { "an example ", "of four Str", "uctured Appe", "nd symbols,"};
+ int i;
+ BitStream *bstream;
+
+ testStart("Testing the example of structured-append symbols");
+ s = QRinput_Struct_new();
+ for(i=0; i<4; i++) {
+ input = QRinput_new2(1, QR_ECLEVEL_M);
+ QRinput_append(input, QR_MODE_8, strlen(str[i]), (unsigned char *)str[i]);
+ QRinput_Struct_appendInput(s, input);
+ }
+ QRinput_Struct_insertStructuredAppendHeaders(s);
+ e = s->head;
+ i = 0;
+ while(e != NULL) {
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(e->input, bstream);
+ BitStream_free(bstream);
+ l = e->input->head->next;
+ assert_equal(l->mode, QR_MODE_8, "#%d: wrong mode (%d).\n", i, l->mode);
+ assert_equal(e->input->level, QR_ECLEVEL_M, "#%d: wrong level (%d).\n", i, e->input->level);
+
+ e = e->next;
+ i++;
+ }
+ testFinish();
+ QRinput_Struct_free(s);
+}
+
+static void test_struct_split_tooLarge(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ char *str;
+ int errsv;
+
+ testStart("Testing structured-append symbols. (too large data)");
+ str = (char *)malloc(128);
+ memset(str, 'a', 128);
+ input = QRinput_new2(1, QR_ECLEVEL_H);
+ QRinput_append(input, QR_MODE_8, 128, (unsigned char *)str);
+ s = QRinput_splitQRinputToStruct(input);
+ errsv = errno;
+ assert_null(s, "returns non-null.");
+ assert_equal(errsv, ERANGE, "did not return ERANGE.");
+ testFinish();
+ if(s != NULL) QRinput_Struct_free(s);
+ QRinput_free(input);
+ free(str);
+}
+
+static void test_struct_split_invalidVersion(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ char *str;
+ int errsv;
+
+ testStart("Testing structured-append symbols. (invalid version 0)");
+ str = (char *)malloc(128);
+ memset(str, 'a', 128);
+ input = QRinput_new2(0, QR_ECLEVEL_H);
+ QRinput_append(input, QR_MODE_8, 128, (unsigned char *)str);
+ s = QRinput_splitQRinputToStruct(input);
+ errsv = errno;
+ assert_null(s, "returns non-null.");
+ assert_equal(errsv, ERANGE, "did not return ERANGE.");
+ testFinish();
+ if(s != NULL) QRinput_Struct_free(s);
+ QRinput_free(input);
+ free(str);
+}
+
+static void test_struct_singlestructure(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ char *str = "TEST";
+
+ testStart("Testing structured-append symbols. (single structure)");
+ input = QRinput_new2(10, QR_ECLEVEL_H);
+ QRinput_append(input, QR_MODE_AN, strlen(str), (unsigned char *)str);
+ s = QRinput_splitQRinputToStruct(input);
+ assert_nonnull(s, "must return a code.");
+ assert_equal(s->size, 1, "size must be 1, but %d returned.", s->size);
+ if(s->size != 1) {
+ printQRinputStruct(s);
+ }
+ testFinish();
+ if(s != NULL) QRinput_Struct_free(s);
+ QRinput_free(input);
+}
+
+static void test_splitentry(void)
+{
+ QRinput *i1, *i2;
+ QRinput_List *e;
+ const char *str = "abcdefghij";
+ int size1, size2, i;
+ unsigned char *d1, *d2;
+
+ testStart("Testing QRinput_splitEntry. (next == NULL)");
+ i1 = QRinput_new();
+ QRinput_append(i1, QR_MODE_8, strlen(str), (unsigned char *)str);
+
+ i2 = QRinput_dup(i1);
+ e = i2->head;
+ QRinput_splitEntry(e, 4);
+
+ size1 = size2 = 0;
+ e = i1->head;
+ while(e != NULL) {
+ size1 += e->size;
+ e = e->next;
+ }
+ e = i2->head;
+ while(e != NULL) {
+ size2 += e->size;
+ e = e->next;
+ }
+
+ d1 = (unsigned char *)malloc(size1);
+ e = i1->head;
+ i = 0;
+ while(e != NULL) {
+ memcpy(&d1[i], e->data, e->size);
+ i += e->size;
+ e = e->next;
+ }
+ d2 = (unsigned char *)malloc(size2);
+ e = i2->head;
+ i = 0;
+ while(e != NULL) {
+ memcpy(&d2[i], e->data, e->size);
+ i += e->size;
+ e = e->next;
+ }
+
+ assert_equal(size1, size2, "sizes are different. (%d:%d)\n", size1, size2);
+ assert_equal(i2->head->size, 4, "split failed (first half)");
+ assert_equal(i2->head->next->size, 6, "split failed(second half)");
+ assert_zero(memcmp(d1, d2, size1), "strings are different.");
+ QRinput_free(i1);
+ QRinput_free(i2);
+ free(d1);
+ free(d2);
+
+ testFinish();
+}
+
+static void test_splitentry2(void)
+{
+ QRinput *i1, *i2;
+ QRinput_List *e;
+ const char *str = "abcdefghij";
+ int size1, size2, i;
+ unsigned char *d1, *d2;
+
+ testStart("Testing QRinput_splitEntry. (next != NULL)");
+ i1 = QRinput_new();
+ QRinput_append(i1, QR_MODE_8, strlen(str), (unsigned char *)str);
+ QRinput_append(i1, QR_MODE_8, strlen(str), (unsigned char *)str);
+
+ i2 = QRinput_dup(i1);
+ e = i2->head;
+ QRinput_splitEntry(e, 4);
+
+ size1 = size2 = 0;
+ e = i1->head;
+ while(e != NULL) {
+ size1 += e->size;
+ e = e->next;
+ }
+ e = i2->head;
+ while(e != NULL) {
+ size2 += e->size;
+ e = e->next;
+ }
+
+ d1 = (unsigned char *)malloc(size1);
+ e = i1->head;
+ i = 0;
+ while(e != NULL) {
+ memcpy(&d1[i], e->data, e->size);
+ i += e->size;
+ e = e->next;
+ }
+ d2 = (unsigned char *)malloc(size2);
+ e = i2->head;
+ i = 0;
+ while(e != NULL) {
+ memcpy(&d2[i], e->data, e->size);
+ i += e->size;
+ e = e->next;
+ }
+
+ assert_equal(size1, size2, "sizes are different. (%d:%d)\n", size1, size2);
+ assert_equal(i2->head->size, 4, "split failed (first half)");
+ assert_equal(i2->head->next->size, 6, "split failed(second half)");
+ assert_zero(memcmp(d1, d2, size1), "strings are different.");
+ QRinput_free(i1);
+ QRinput_free(i2);
+ free(d1);
+ free(d2);
+
+ testFinish();
+}
+
+static void test_splitentry3(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ QRinput_List *e00, *e01, *e10, *e11;
+ QRinput_InputList *list;
+ const char *str = "abcdefghijklmno";
+
+ testStart("Testing QRinput_splitEntry. (does not split an entry)");
+ /* version 1 symbol contains 152 bit (19 byte) data.
+ * 20 bits for a structured-append header, so 132 bits can be used.
+ * 15 bytes of 8-bit data is suitable for the symbol.
+ * (mode(4) + length(8) + data(120) == 132.)
+ */
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, strlen(str), (unsigned char *)str);
+ QRinput_append(input, QR_MODE_8, strlen(str), (unsigned char *)str);
+ s = QRinput_splitQRinputToStruct(input);
+ list = s->head;
+ e00 = list->input->head;
+ e01 = e00->next;
+ list = list->next;
+ e10 = list->input->head;
+ e11 = e10->next;
+
+ assert_equal(e00->mode, QR_MODE_STRUCTURE, "Structure header is missing?");
+ assert_equal(e01->mode, QR_MODE_8, "no data?!");
+ assert_null(e01->next, "Input list is not terminated!\n");
+ assert_equal(e10->mode, QR_MODE_STRUCTURE, "Structure header is missing?");
+ assert_equal(e11->mode, QR_MODE_8, "no data?!");
+ assert_null(e11->next, "Input list is not terminated!\n");
+
+ QRinput_free(input);
+ QRinput_Struct_free(s);
+ testFinish();
+}
+
+static void test_parity(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ const char *text = "an example of four Structured Append symbols,";
+ const char *str[4] = {
+ "an example ",
+ "of four Str",
+ "uctured Appe",
+ "nd symbols,"};
+ unsigned char p1, p2;
+ int i, len;
+
+ testStart("Testing parity calc.");
+ s = QRinput_Struct_new();
+ for(i=0; i<4; i++) {
+ input = QRinput_new2(1, QR_ECLEVEL_M);
+ QRinput_append(input, QR_MODE_8, strlen(str[i]), (unsigned char *)str[i]);
+ QRinput_Struct_appendInput(s, input);
+ }
+ QRinput_Struct_insertStructuredAppendHeaders(s);
+ p1 = s->parity;
+
+ p2 = 0;
+ len = strlen(text);
+ for(i=0; i<len; i++) {
+ p2 ^= text[i];
+ }
+ assert_equal(p1, p2, "Parity numbers didn't match. (%02x should be %02x).\n", p1, p2);
+ testFinish();
+ QRinput_Struct_free(s);
+}
+
+static void test_parity2(void)
+{
+ QRinput *input;
+ QRinput_Struct *s;
+ const char *text = "an example of four Structured Append symbols,";
+ unsigned char p1, p2;
+ int i, len;
+
+ testStart("Testing parity calc.(split)");
+ input = QRinput_new2(1, QR_ECLEVEL_L);
+ QRinput_append(input, QR_MODE_8, strlen(text), (unsigned char *)text);
+ s = QRinput_splitQRinputToStruct(input);
+ p1 = s->parity;
+
+ p2 = 0;
+ len = strlen(text);
+ for(i=0; i<len; i++) {
+ p2 ^= text[i];
+ }
+ assert_equal(p1, p2, "Parity numbers didn't match. (%02x should be %02x).\n", p1, p2);
+ testFinish();
+ QRinput_free(input);
+ QRinput_Struct_free(s);
+}
+
+static void test_null_free(void)
+{
+ testStart("Testing free NULL pointers");
+ assert_nothing(QRinput_free(NULL), "Check QRinput_free(NULL).\n");
+ assert_nothing(QRinput_Struct_free(NULL), "Check QRinput_Struct_free(NULL).\n");
+ testFinish();
+}
+
+static void fillCharacter(char *dest, char ch, int size)
+{
+ memset(dest, ch, size);
+ dest[size] = '\0';
+}
+
+static void checkEstimatedVersion(int ver, int mode)
+{
+ int estimatedVersion;
+ char data[7200];
+ QRinput *input;
+ QRencodeMode hint;
+ int size1, size2;
+ static char *modeStr[4] = {"numeric", "alphanumeric", "8 bit data", "kanji"};
+ static char ch[4] = {'0', 'A', 'a', '\x92'};
+
+ if(mode == QR_MODE_KANJI) {
+ hint = QR_MODE_KANJI;
+ size1 = maxCharacterLengths[ver - 1][mode] * 2;
+ size2 = size1 + 2;
+ } else {
+ hint = QR_MODE_8;
+ size1 = maxCharacterLengths[ver - 1][mode];
+ size2 = size1 + 1;
+ }
+
+ fillCharacter(data, ch[mode], size1);
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(data, input, hint, 1);
+ estimatedVersion = QRinput_estimateVersion(input);
+ assert_equal(estimatedVersion, ver, "Estimated version %d is not equal to the expected version %d for %d %s sequence.\n", estimatedVersion, ver, maxCharacterLengths[ver - 1][mode], modeStr[mode]);
+ QRinput_free(input);
+
+ fillCharacter(data, ch[mode], size2);
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(data, input, hint, 1);
+ estimatedVersion = QRinput_estimateVersion(input);
+ assert_equal(estimatedVersion, ver + 1, "Estimated version %d is not equal to the expected version %d for %d %s sequence.\n", estimatedVersion, ver, maxCharacterLengths[ver - 1][mode] + 1, modeStr[mode]);
+ QRinput_free(input);
+}
+
+static void test_estimateVersionBoundaryCheck(void)
+{
+ int ver;
+ testStart("Boundary check of estimateVersion");
+ for(ver = 1; ver < QRSPEC_VERSION_MAX; ver++) {
+ checkEstimatedVersion(ver, QR_MODE_NUM);
+ checkEstimatedVersion(ver, QR_MODE_AN);
+ checkEstimatedVersion(ver, QR_MODE_8);
+ checkEstimatedVersion(ver, QR_MODE_KANJI);
+ }
+ testFinish();
+}
+
+static void test_QRinput_new_invalid(void)
+{
+ testStart("Invalid input to QRinput_new2()");
+ QRinput *input;
+
+ input = QRinput_new2(-1, QR_ECLEVEL_H);
+ assert_null(input, "QRinput_new2() returns non-null for invalid version (-1).\n");
+ assert_equal(errno, EINVAL, "Error code is not EINVAL.\n");
+ input = QRinput_new2(41, QR_ECLEVEL_H);
+ assert_null(input, "QRinput_new2() returns non-null for invalid version (41).\n");
+ assert_equal(errno, EINVAL, "Error code is not EINVAL.\n");
+ input = QRinput_new2(1, -1);
+ assert_null(input, "QRinput_new2() returns non-null for invalid level (-1).\n");
+ assert_equal(errno, EINVAL, "Error code is not EINVAL.\n");
+ input = QRinput_new2(1, 5);
+ assert_null(input, "QRinput_new2() returns non-null for invalid level (5).\n");
+ assert_equal(errno, EINVAL, "Error code is not EINVAL.\n");
+ testFinish();
+}
+
+static void test_QRinput_getErrorCorrectionLevel(void)
+{
+ testStart("Invalid input to QRinput_getErrorCorrectionLevel()");
+ QRinput *input;
+ QRecLevel level;
+
+ input = QRinput_new2(1, QR_ECLEVEL_H);
+ level = QRinput_getErrorCorrectionLevel(input);
+ assert_equal(level, QR_ECLEVEL_H, "QRinput_getErrorCorrectionLevel() fails to return expected level.\n");
+ testFinish();
+ QRinput_free(input);
+}
+
+static void test_mqr_new(void)
+{
+ QRinput *input;
+ testStart("Testing QRinput_newMQR().");
+
+ input = QRinput_newMQR(0, QR_ECLEVEL_L);
+ assert_null(input, "Version 0 passed.\n");
+ QRinput_free(input);
+
+ input = QRinput_newMQR(5, QR_ECLEVEL_L);
+ assert_null(input, "Version 5 passed.\n");
+ QRinput_free(input);
+
+ input = QRinput_newMQR(1, QR_ECLEVEL_M);
+ assert_null(input, "Invalid ECLEVEL passed.\n");
+ QRinput_free(input);
+
+ input = QRinput_newMQR(1, QR_ECLEVEL_L);
+ assert_equal(input->version, 1, "QRinput.version was not as expected.\n");
+ assert_equal(input->level, QR_ECLEVEL_L, "QRinput.version was not as expected.\n");
+ QRinput_free(input);
+
+ testFinish();
+}
+
+static void test_mqr_setversion(void)
+{
+ QRinput *input;
+ int ret;
+ testStart("Testing QRinput_setVersion() for MQR.");
+
+ input = QRinput_newMQR(1, QR_ECLEVEL_L);
+ ret = QRinput_setVersion(input, 2);
+ assert_exp((ret < 0), "QRinput_setVersion should be denied.\n");
+ QRinput_free(input);
+
+ testFinish();
+}
+
+static void test_mqr_setlevel(void)
+{
+ QRinput *input;
+ int ret;
+ testStart("Testing QRinput_setErrorCorrectionLevel() for MQR.");
+
+ input = QRinput_newMQR(1, QR_ECLEVEL_L);
+ ret = QRinput_setErrorCorrectionLevel(input, QR_ECLEVEL_M);
+ assert_exp((ret < 0), "QRinput_setErrorCorrectionLevel should be denied.\n");
+ QRinput_free(input);
+
+ testFinish();
+}
+
+static void test_paddingMQR(void)
+{
+ char *dataM1[] = {"65", "513", "5139", "51365"};
+ char *correctM1[] = {"01010000010000000000",
+ "01110000000010000000",
+ "10010000000011001000",
+ "10110000000011000001"};
+ char *dataM2[] = {"513513", "51351365"};
+ char *correctM2[] = {"0 0110 1000000001 1000000001 0000000",
+ "0 1000 1000000001 1000000001 1000001"};
+ int i, ret;
+
+ testStart("Padding bit check of MQR. (only 0 padding)");
+ for(i=0; i<4; i++) {
+ ret = encodeAndCheckBStream(1, 1, QR_ECLEVEL_L, QR_MODE_NUM, dataM1[i], correctM1[i]);
+ assert_zero(ret, "Number %s incorrectly encoded.\n", dataM1[i]);
+ }
+ for(i=0; i<2; i++) {
+ ret = encodeAndCheckBStream(1, 2, QR_ECLEVEL_M, QR_MODE_NUM, dataM2[i], correctM2[i]);
+ assert_zero(ret, "Number %s incorrectly encoded.\n", dataM2[i]);
+ }
+ testFinish();
+}
+
+static void test_padding2MQR(void)
+{
+ char *data[] = {"9", "513513", "513", "513"};
+ int ver[] = {1, 2, 2, 3};
+ char *correct[] = {"00110010 00000000 0000",
+ "0 0110 1000000001 1000000001 0000000 11101100",
+ "0 0011 1000000001 000000000 11101100 00010001",
+ "00 00011 1000000001 0000000 11101100 00010001 11101100 00010001 11101100 00010001 11101100 0000"
+ };
+ int i, ret;
+
+ testStart("Padding bit check. (1 or 2 padding bytes)");
+
+ for(i=0; i<4; i++) {
+ ret = encodeAndCheckBStream(1, ver[i], QR_ECLEVEL_L, QR_MODE_NUM, data[i], correct[i]);
+ assert_zero(ret, "Number %s incorrectly encoded.\n", data[i]);
+ }
+ testFinish();
+}
+
+static void test_textMQR(void)
+{
+ int version = 3;
+ QRecLevel level = QR_ECLEVEL_M;
+ char *str = "MICROQR";
+ char *correct = {"01 0111 01111110000 01000110111 10001010010 011011 0000000 0000 11101100 0000"};
+ int ret;
+
+ testStart("Text encoding (Micro QR)");
+ ret = encodeAndCheckBStream(1, version, level, QR_MODE_AN, str, correct);
+ assert_zero(ret, "AlphaNumeric string '%s' incorrectly encoded.\n", str);
+ testFinish();
+}
+
+static void test_ECIinvalid(void)
+{
+ QRinput *stream;
+ int ret;
+
+ testStart("Appending invalid ECI header");
+ stream = QRinput_new();
+ ret = QRinput_appendECIheader(stream, 999999);
+ assert_zero(ret, "Valid ECI header rejected.");
+ ret = QRinput_appendECIheader(stream, 1000000);
+ assert_nonzero(ret, "Invalid ECI header accepted.");
+ QRinput_free(stream);
+ testFinish();
+}
+
+static void test_encodeECI(void)
+{
+ QRinput *input;
+ BitStream *bstream;
+ unsigned char str[] = {0xa1, 0xa2, 0xa3, 0xa4, 0xa5};
+ char *correct = "0111 00001001 0100 00000101 10100001 10100010 10100011 10100100 10100101";
+ int ret;
+
+ testStart("Encoding characters with ECI header.");
+ input = QRinput_new();
+ ret = QRinput_appendECIheader(input, 9);
+ assert_zero(ret, "Valid ECI header rejected.\n");
+
+ ret = QRinput_append(input, QR_MODE_8, 5, str);
+ assert_zero(ret, "Failed to append characters.\n");
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ assert_nonnull(bstream, "Failed to merge.\n");
+ if(bstream != NULL) {
+ ret = ncmpBin(correct, bstream, 64);
+ assert_zero(ret, "Encodation of ECI header was invalid.\n");
+ BitStream_free(bstream);
+ }
+ QRinput_free(input);
+ testFinish();
+}
+
+int main()
+{
+ int tests = 42;
+ testInit(tests);
+
+ test_encodeNumeric();
+ test_encodeNumeric2();
+ test_encodeNumeric3();
+ test_encodeNumeric_versionup();
+ test_encode8();
+ test_encode8_versionup();
+ test_encodeAn();
+ test_encodeAn2();
+ test_encodeKanji();
+ test_encodeNumericPadded();
+ test_encodeNumericPadded2();
+ test_encodeAnNum();
+ test_padding();
+ test_padding2();
+ test_struct_listop();
+ test_insertStructuredAppendHeader();
+ test_insertStructuredAppendHeader_error();
+ test_struct_insertStructuredAppendHeaders();
+ test_lengthOfCode_num();
+ test_lengthOfCode_kanji();
+ test_splitentry();
+ test_splitentry2();
+ test_splitentry3();
+ test_struct_split_example();
+ test_struct_split_tooLarge();
+ test_struct_split_invalidVersion();
+ test_struct_singlestructure();
+ test_parity();
+ test_parity2();
+ test_null_free();
+ test_estimateVersionBoundaryCheck();
+ test_QRinput_new_invalid();
+ test_QRinput_getErrorCorrectionLevel();
+
+ test_mqr_new();
+ test_mqr_setversion();
+ test_mqr_setlevel();
+ test_paddingMQR();
+ test_padding2MQR();
+ test_textMQR();
+
+ test_ECIinvalid();
+ test_encodeECI();
+
+ testReport(tests);
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_qrspec.c b/genqrcode/tests/test_qrspec.c
new file mode 100644
index 0000000000..15b7bbe9d2
--- /dev/null
+++ b/genqrcode/tests/test_qrspec.c
@@ -0,0 +1,319 @@
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+#include "../qrspec.h"
+#include "../qrencode_inner.h"
+#include "decoder.h"
+
+#ifndef SRCDIR
+# define SRCDIR
+#endif
+
+static void print_eccTable(void)
+{
+ int i, j;
+ int ecc;
+ int data;
+ int spec[5];
+
+ puts("\nPrinting ECC table.\n");
+ for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
+ printf("Version %2d\n", i);
+ for(j=0; j<4; j++) {
+ QRspec_getEccSpec(i, (QRecLevel)j, spec);
+ data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec)
+ + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec);
+ ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec)
+ + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec);
+ printf("%3d\t", data);
+ printf("%3d\t", ecc);
+ printf("%2d\t", QRspec_rsBlockNum1(spec));
+ printf("(%3d, %3d, %3d)\n",
+ QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec),
+ QRspec_rsDataCodes1(spec),
+ QRspec_rsEccCodes1(spec));
+ if(QRspec_rsBlockNum2(spec) > 0) {
+ printf("\t%2d\t", QRspec_rsBlockNum2(spec));
+ printf("(%3d, %3d, %3d)\n",
+ QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec),
+ QRspec_rsDataCodes2(spec),
+ QRspec_rsEccCodes2(spec));
+ }
+ }
+ }
+}
+
+static void test_eccTable(void)
+{
+ int i, j;
+ int ecc;
+ int data;
+ int err = 0;
+ int spec[5];
+
+ testStart("Checking ECC table.");
+ for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
+ for(j=0; j<4; j++) {
+ QRspec_getEccSpec(i, (QRecLevel)j, spec);
+ data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec)
+ + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec);
+ ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec)
+ + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec);
+ if(data + ecc != QRspec_getDataLength(i, (QRecLevel)j) + QRspec_getECCLength(i, (QRecLevel)j)) {
+ printf("Error in version %d, level %d: invalid size\n", i, j);
+ printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]);
+ err++;
+ }
+ if(ecc != QRspec_getECCLength(i, (QRecLevel)j)) {
+ printf("Error in version %d, level %d: invalid data\n", i, j);
+ printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]);
+ err++;
+ }
+ }
+ }
+ testEnd(err);
+}
+
+static void test_eccTable2(void)
+{
+ int i;
+ int spec[5];
+
+ const int correct[7][6] = {
+ { 8, 1, 0, 2, 60, 38},
+ { 8, 1, 1, 2, 61, 39},
+ {24, 2, 0, 11, 54, 24},
+ {24, 2, 1, 16, 55, 25},
+ {32, 0, 0, 17, 145, 115},
+ {40, 3, 0, 20, 45, 15},
+ {40, 3, 1, 61, 46, 16},
+ };
+
+ testStart("Checking ECC table(2)");
+ for(i=0; i<7; i++) {
+ QRspec_getEccSpec(correct[i][0], (QRecLevel)correct[i][1], spec);
+ if(correct[i][2] == 0) {
+ assert_equal(QRspec_rsBlockNum1(spec), correct[i][3],
+ "Error in version %d, level %d. rsBlockNum1 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsBlockNum1(spec), correct[i][3]);
+ assert_equal(QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4],
+ "Error in version %d, level %d. rsDataCodes1 + rsEccCodes1 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4]);
+ assert_equal(QRspec_rsDataCodes1(spec), correct[i][5],
+ "Error in version %d, level %d. rsDataCodes1 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsDataCodes1(spec), correct[i][5]);
+ } else {
+ assert_equal(QRspec_rsBlockNum2(spec), correct[i][3],
+ "Error in version %d, level %d. rsBlockNum2 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsBlockNum2(spec), correct[i][3]);
+ assert_equal(QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4],
+ "Error in version %d, level %d. rsDataCodes2 + rsEccCodes2 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4]);
+ assert_equal(QRspec_rsDataCodes2(spec), correct[i][5],
+ "Error in version %d, level %d. rsDataCodes2 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsDataCodes2(spec), correct[i][5]);
+ }
+ }
+ testFinish();
+}
+
+static void test_newframe(void)
+{
+ unsigned char buf[QRSPEC_WIDTH_MAX * QRSPEC_WIDTH_MAX];
+ int i, width;
+ size_t len;
+ FILE *fp;
+ unsigned char *frame;
+ QRcode *qrcode;
+ int version;
+
+ testStart("Checking newly created frame.");
+ fp = fopen(SRCDIR "frame", "rb");
+ if(fp == NULL) {
+ perror("Failed to open \"" SRCDIR "frame\":");
+ abort();
+ }
+ for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
+ frame = QRspec_newFrame(i);
+ width = QRspec_getWidth(i);
+ len = fread(buf, 1, width * width, fp);
+ if((int)len != width * width) {
+ perror("Failed to read the pattern file:");
+ abort();
+ }
+ assert_zero(memcmp(frame, buf, len), "frame pattern mismatch (version %d)\n", i);
+ qrcode = QRcode_new(i, width, frame);
+ version = QRcode_decodeVersion(qrcode);
+ assert_equal(version, i, "Decoded version number is wrong: %d, expected %d.\n", version, i);
+ QRcode_free(qrcode);
+ }
+
+ testFinish();
+ fclose(fp);
+}
+
+static void test_newframe_invalid(void)
+{
+ unsigned char *frame;
+
+ testStart("Checking QRspec_newFrame with invalid version.");
+ frame = QRspec_newFrame(0);
+ assert_null(frame, "QRspec_newFrame(0) returns non-NULL.");
+ frame = QRspec_newFrame(QRSPEC_VERSION_MAX+1);
+ assert_null(frame, "QRspec_newFrame(0) returns non-NULL.");
+ testFinish();
+}
+
+#if 0
+/* This test is used to check positions of alignment pattern. See Appendix E
+ * (p.71) of JIS X0510:2004 and compare to the output. Before comment out
+ * this test, change the value of the pattern marker's center dot from 0xa1
+ * to 0xb1 (QRspec_putAlignmentMarker() : finder).
+ */
+static void test_alignment(void)
+{
+ unsigned char *frame;
+ int i, x, y, width, c;
+
+ testStart("Checking alignment pattern.");
+ for(i=2; i<=QRSPEC_VERSION_MAX; i++) {
+ printf("%2d", i);
+ frame = QRspec_newFrame(i);
+ width = QRspec_getWidth(i);
+ c = 0;
+ for(x=0; x<width * width; x++) {
+ if(frame[x] == 0xb1) {
+ c++;
+ }
+ }
+ printf("|%2d| 6", c);
+ y = width - 7;
+ for(x=0; x < width; x++) {
+ if(frame[y * width + x] == 0xb1) {
+ printf(", %3d", x);
+ }
+ }
+ printf("\n");
+ free(frame);
+ }
+ testFinish();
+}
+#endif
+
+static void test_verpat(void)
+{
+ int version;
+ unsigned int pattern;
+ int err = 0;
+ unsigned int data;
+ unsigned int code;
+ int i, c;
+ unsigned int mask;
+
+ testStart("Checking version pattern.");
+ for(version=7; version <= QRSPEC_VERSION_MAX; version++) {
+ pattern = QRspec_getVersionPattern(version);
+ if((pattern >> 12) != (unsigned int)version) {
+ printf("Error in version %d.\n", version);
+ err++;
+ continue;
+ }
+ mask = 0x40;
+ for(i=0; mask != 0; i++) {
+ if(version & mask) break;
+ mask = mask >> 1;
+ }
+ c = 6 - i;
+ data = version << 12;
+ code = 0x1f25 << c;
+ mask = 0x40000 >> (6 - c);
+ for(i=0; i<=c; i++) {
+ if(mask & data) {
+ data ^= code;
+ }
+ code = code >> 1;
+ mask = mask >> 1;
+ }
+ data = (version << 12) | (data & 0xfff);
+ if(data != pattern) {
+ printf("Error in version %d\n", version);
+ err++;
+ }
+ }
+ testEnd(err);
+}
+
+/* See Table 22 (p.45) and Appendix C (p. 65) of JIS X0510:2004 */
+static unsigned int levelIndicator[4] = {1, 0, 3, 2};
+static unsigned int calcFormatInfo(int mask, QRecLevel level)
+{
+ unsigned int data, ecc, b, code;
+ int i, c;
+
+ data = (levelIndicator[level] << 13) | (mask << 10);
+ ecc = data;
+ b = 1 << 14;
+ for(i=0; b != 0; i++) {
+ if(ecc & b) break;
+ b = b >> 1;
+ }
+ c = 4 - i;
+ code = 0x537 << c ; //10100110111
+ b = 1 << (10 + c);
+ for(i=0; i<=c; i++) {
+ if(b & ecc) {
+ ecc ^= code;
+ }
+ code = code >> 1;
+ b = b >> 1;
+ }
+
+ return (data | ecc) ^ 0x5412;
+}
+
+static void test_format(void)
+{
+ unsigned int format;
+ int i, j;
+ int err = 0;
+
+ testStart("Format info test");
+ for(i=0; i<4; i++) {
+ for(j=0; j<8; j++) {
+ format = calcFormatInfo(j, (QRecLevel)i);
+// printf("0x%04x, ", format);
+ if(format != QRspec_getFormatInfo(j, (QRecLevel)i)) {
+ printf("Level %d, mask %x\n", i, j);
+ err++;
+ }
+ }
+// printf("\n");
+ }
+ testEnd(err);
+}
+
+int main(int argc, char **argv)
+{
+ int tests = 6;
+ testInit(tests);
+ test_eccTable();
+ test_eccTable2();
+ test_newframe();
+ test_newframe_invalid();
+ //test_alignment();
+ test_verpat();
+ test_format();
+ testReport(tests);
+
+ if(argc > 1) {
+ print_eccTable();
+ }
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_rs.c b/genqrcode/tests/test_rs.c
new file mode 100644
index 0000000000..d0df44bfb3
--- /dev/null
+++ b/genqrcode/tests/test_rs.c
@@ -0,0 +1,126 @@
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+#include "../qrencode_inner.h"
+#include "../qrspec.h"
+#include "../mqrspec.h"
+#include "../qrinput.h"
+#include "../rsecc.h"
+#include "decoder.h"
+#include "rsecc_decoder.h"
+#include "rscode.h"
+
+/* See pp. 73 of JIS X0510:2004 */
+void test_rscodeexample(void)
+{
+ QRinput *stream;
+ QRRawCode *code;
+ static const char str[9] = "01234567";
+ static unsigned char correct[26] = {
+ 0x10, 0x20, 0x0c, 0x56, 0x61, 0x80, 0xec, 0x11, 0xec, 0x11, 0xec, 0x11,
+ 0xec, 0x11, 0xec, 0x11, 0xa5, 0x24, 0xd4, 0xc1, 0xed, 0x36, 0xc7, 0x87,
+ 0x2c, 0x55};
+
+ testStart("RS ecc test");
+ stream = QRinput_new();
+ QRinput_append(stream, QR_MODE_NUM, 8, (unsigned char *)str);
+ QRinput_setErrorCorrectionLevel(stream, QR_ECLEVEL_M);
+ code = QRraw_new(stream);
+
+ testEnd(memcmp(correct + 16, code->rsblock[0].ecc, 10));
+ QRinput_free(stream);
+ QRraw_free(code);
+}
+
+static void compareRS(unsigned char data[])
+{
+ int i, j;
+ RS *rs;
+ int spec[5];
+ int dl, el;
+ unsigned char ecc_expected[256], ecc_rscodec[256];
+
+ for(i = 1; i <= QRSPEC_VERSION_MAX; i++) {
+ for(j = QR_ECLEVEL_L; j <= QR_ECLEVEL_H; j++) {
+ QRspec_getEccSpec(i, (QRecLevel)j, spec);
+ dl = QRspec_rsDataCodes1(spec);
+ el = QRspec_rsEccCodes1(spec);
+ rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
+ RSECC_encode(dl, el, data, ecc_rscodec);
+ encode_rs_char(rs, data, ecc_expected);
+ assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el);
+ assert_zero(RSECC_decoder_checkSyndrome(dl, data, el, ecc_rscodec), "ECC error found.");
+ free_rs_char(rs);
+
+
+ dl = QRspec_rsDataCodes2(spec);
+ el = QRspec_rsEccCodes2(spec);
+ if(dl != 0) {
+ rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
+ RSECC_encode(dl, el, data, ecc_rscodec);
+ encode_rs_char(rs, data, ecc_expected);
+ assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el);
+ assert_zero(RSECC_decoder_checkSyndrome(dl, data, el, ecc_rscodec), "ECC error found.");
+ free_rs_char(rs);
+ }
+ }
+ }
+}
+
+static void compareRSMQR(unsigned char data[])
+{
+ int i, j;
+ RS *rs;
+ int dl, el;
+ unsigned char ecc_expected[256], ecc_rscodec[256];
+
+ for(i = 1; i <= MQRSPEC_VERSION_MAX; i++) {
+ for(j = QR_ECLEVEL_L; j <= QR_ECLEVEL_Q; j++) {
+ dl = MQRspec_getDataLength(i, (QRecLevel)j);
+ el = MQRspec_getECCLength(i, (QRecLevel)j);
+ if(dl != 0) {
+ rs = init_rs(8, 0x11d, 0, 1, el, 255 - dl - el);
+ RSECC_encode(dl, el, data, ecc_rscodec);
+ encode_rs_char(rs, data, ecc_expected);
+ assert_zero(memcmp(ecc_expected, ecc_rscodec, el), "Invalid ECC found: length %d.\n", el);
+ assert_zero(RSECC_decoder_checkSyndrome(dl, data, el, ecc_rscodec), "ECC error found.");
+ free_rs_char(rs);
+ }
+ }
+ }
+}
+
+void test_allQRSizeAndECCLevel(void)
+{
+ int i;
+ unsigned char data[256];
+
+ testStart("Comparing with KA9Q's code: all QR Code sizes and ECC levels");
+ memset(data, 0, 256);
+ compareRS(data);
+ compareRSMQR(data);
+ memset(data, 0xaa, 256);
+ compareRS(data);
+ compareRSMQR(data);
+ memset(data, 0xff, 256);
+ compareRS(data);
+ compareRSMQR(data);
+ for(i=0; i<256; i++) {
+ data[i] = i;
+ }
+ compareRS(data);
+ compareRSMQR(data);
+ testFinish();
+}
+
+int main()
+{
+ RSECC_decoder_init();
+ int tests = 2;
+ testInit(tests);
+ test_rscodeexample();
+ test_allQRSizeAndECCLevel();
+ testReport(tests);
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_split.c b/genqrcode/tests/test_split.c
new file mode 100644
index 0000000000..e46f53514f
--- /dev/null
+++ b/genqrcode/tests/test_split.c
@@ -0,0 +1,553 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include "common.h"
+#include "../qrspec.h"
+#include "../qrinput.h"
+#include "../mask.h"
+#include "../split.h"
+#include "../bitstream.h"
+
+static int inputTest(QRinput_List *list, const char *fmt, ...)
+{
+ va_list ap;
+ int size;
+ QRencodeMode mode;
+ int i, err = 0;
+
+ va_start(ap, fmt);
+ i = 1;
+ while(*fmt) {
+ if(list == NULL) {
+ err = 1;
+ break;
+ }
+ size = va_arg(ap, int);
+ if(list->size != size) {
+ err = 1;
+ break;
+ }
+
+ switch(*fmt++) {
+ case 'n':
+ mode = QR_MODE_NUM;
+ break;
+ case 'a':
+ mode = QR_MODE_AN;
+ break;
+ case 'k':
+ mode = QR_MODE_KANJI;
+ break;
+ case '8':
+ mode = QR_MODE_8;
+ break;
+ default:
+ return -1;
+ break;
+ }
+ if(list->mode != mode) {
+ err = 1;
+ break;
+ }
+ list = list->next;
+ i++;
+ }
+ va_end(ap);
+ if(list != NULL) {
+ err = 1;
+ }
+ if(err) {
+ return -i;
+ }
+ return 0;
+}
+
+static int inputSize(QRinput *input)
+{
+ BitStream *bstream;
+ int size;
+
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ size = BitStream_size(bstream);
+ BitStream_free(bstream);
+
+ return size;
+}
+
+static void test_split1(void)
+{
+ QRinput *input;
+ BitStream *bstream;
+
+ testStart("Split test: null string");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("", input, QR_MODE_8, 0);
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+ testEndExp(BitStream_size(bstream) == 0);
+ QRinput_free(input);
+ BitStream_free(bstream);
+}
+
+static void test_split2(void)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int err = 0;
+
+ testStart("Split test: single typed strings (num)");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("0123", input, QR_MODE_8, 0);
+ list = input->head;
+ if(inputTest(list, "n", 4)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+
+ err = 0;
+ testStart("Split test: single typed strings (num2)");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("12345678901234567890", input, QR_MODE_KANJI, 0);
+ list = input->head;
+ if(inputTest(list, "n", 20)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+}
+
+static void test_split3(void)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int err = 0;
+
+ testStart("Split test: single typed strings (an)");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("ab:-E", input, QR_MODE_8, 0);
+ list = input->head;
+ if(inputTest(list, "a", 5)) {
+ printQRinputInfo(input);
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+
+ err = 0;
+ testStart("Split test: num + an");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("0123abcde", input, QR_MODE_KANJI, 0);
+ list = input->head;
+ if(inputTest(list, "a", 9)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+
+ err = 0;
+ testStart("Split test: an + num + an");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("Ab345fg", input, QR_MODE_KANJI, 0);
+ list = input->head;
+ if(inputTest(list, "a", 7)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+}
+
+static void test_split4(void)
+{
+ QRinput *input;
+ QRinput *i1, *i2;
+ int s1, s2, size;
+#define CHUNKA "ABCDEFGHIJK"
+#define CHUNKB "123456"
+#define CHUNKC "1234567"
+
+ testStart("Split test: an and num entries");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(CHUNKA/**/CHUNKB, input, QR_MODE_8, 0);
+ i1 = QRinput_new();
+ QRinput_append(i1, QR_MODE_AN, 17, (unsigned char *)CHUNKA/**/CHUNKB);
+ i2 = QRinput_new();
+ QRinput_append(i2, QR_MODE_AN, 11, (unsigned char *)CHUNKA);
+ QRinput_append(i2, QR_MODE_NUM, 6, (unsigned char *)CHUNKB);
+
+ size = inputSize(input);
+ s1 = inputSize(i1);
+ s2 = inputSize(i2);
+ testEndExp(size == ((s1 < s2)?s1:s2));
+ QRinput_free(input);
+ QRinput_free(i1);
+ QRinput_free(i2);
+
+ testStart("Split test: num and an entries");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(CHUNKB/**/CHUNKA, input, QR_MODE_8, 0);
+ i1 = QRinput_new();
+ QRinput_append(i1, QR_MODE_AN, 17, (unsigned char *)CHUNKB/**/CHUNKA);
+ i2 = QRinput_new();
+ QRinput_append(i2, QR_MODE_NUM, 6, (unsigned char *)CHUNKB);
+ QRinput_append(i2, QR_MODE_AN, 11, (unsigned char *)CHUNKA);
+
+ size = inputSize(input);
+ s1 = inputSize(i1);
+ s2 = inputSize(i2);
+ testEndExp(size == ((s1 < s2)?s1:s2));
+ QRinput_free(input);
+ QRinput_free(i1);
+ QRinput_free(i2);
+
+ testStart("Split test: num and an entries (should be splitted)");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(CHUNKC/**/CHUNKA, input, QR_MODE_8, 0);
+ i1 = QRinput_new();
+ QRinput_append(i1, QR_MODE_AN, 18, (unsigned char *)CHUNKC/**/CHUNKA);
+ i2 = QRinput_new();
+ QRinput_append(i2, QR_MODE_NUM, 7, (unsigned char *)CHUNKC);
+ QRinput_append(i2, QR_MODE_AN, 11, (unsigned char *)CHUNKA);
+
+ size = inputSize(input);
+ s1 = inputSize(i1);
+ s2 = inputSize(i2);
+ testEndExp(size == ((s1 < s2)?s1:s2));
+ QRinput_free(input);
+ QRinput_free(i1);
+ QRinput_free(i2);
+}
+
+static void test_split5(void)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int err = 0;
+
+ testStart("Split test: bit, an, bit, num");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("\x82\xd9""abcdeabcdea\x82\xb0""123456", input, QR_MODE_8, 0);
+ list = input->head;
+ if(inputTest(list, "8a8n", 2, 11, 2, 6)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+}
+
+static void test_split6(void)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int err = 0;
+
+ testStart("Split test: kanji, an, kanji, num");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("\x82\xd9""abcdeabcdea\x82\xb0""123456", input, QR_MODE_KANJI, 0);
+ list = input->head;
+ if(inputTest(list, "kakn", 2, 11, 2, 6)) {
+ printQRinputInfo(input);
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+}
+
+static void test_split7(void)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int err = 0;
+
+ testStart("Split test: an and num as bits");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("\x82\xd9""abcde\x82\xb0""12345", input, QR_MODE_8, 0);
+ list = input->head;
+ if(inputTest(list, "8n", 9, 5)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+}
+
+static void test_split8(void)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int err = 0;
+
+ testStart("Split test: terminated with a half of kanji code");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("\x82\xd9""abcdefgh\x82", input, QR_MODE_KANJI, 0);
+ list = input->head;
+ if(inputTest(list, "ka8", 2, 8, 1)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+}
+
+static void test_split3c(void)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int err = 0;
+
+ testStart("Split test: single typed strings (an, case-sensitive)");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("ab:-E", input, QR_MODE_8, 1);
+ list = input->head;
+ if(inputTest(list, "8", 5)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+
+ err = 0;
+ testStart("Split test: num + an");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("0123abcde", input, QR_MODE_KANJI, 1);
+ list = input->head;
+ if(inputTest(list, "n8", 4, 5)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+
+ err = 0;
+ testStart("Split test: an + num + an");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("Ab345fg", input, QR_MODE_KANJI, 1);
+ list = input->head;
+ if(inputTest(list, "8", 7)) {
+ printQRinputInfo(input);
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+}
+
+static void test_toupper(void)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int err = 0;
+
+ testStart("Split test: check dupAndToUpper (lower->upper)");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("abcde", input, QR_MODE_8, 0);
+ list = input->head;
+ if(inputTest(list, "a", 5)) {
+ err++;
+ }
+ if(strncmp((char *)list->data, "ABCDE", list->size)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+
+ err = 0;
+ testStart("Split test: check dupAndToUpper (kanji)");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("\x83n\x83q\x83t\x83w\x83z", input, QR_MODE_KANJI, 0);
+ list = input->head;
+ if(inputTest(list, "k", 10)) {
+ printQRinputInfo(input);
+ err++;
+ }
+ if(strncmp((char *)list->data, "\x83n\x83q\x83t\x83w\x83z", list->size)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+
+ err = 0;
+ testStart("Split test: check dupAndToUpper (8bit)");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("\x83n\x83q\x83t\x83w\x83z", input, QR_MODE_8, 0);
+ list = input->head;
+ if(inputTest(list, "8", 10)) {
+ printQRinputInfo(input);
+ err++;
+ }
+ if(strncmp((char *)list->data, "\x83N\x83Q\x83T\x83W\x83Z", list->size)) {
+ err++;
+ }
+ testEnd(err);
+ QRinput_free(input);
+}
+
+static void test_splitNum8(void)
+{
+ QRinput *input;
+ QRinput_List *list;
+ int err = 0;
+
+ testStart("Split test: num and 8bit to 8bit");
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput("1abcdefg", input, QR_MODE_8, 1);
+ list = input->head;
+ if(inputTest(list, "8", 8)) {
+ err++;
+ printQRinputInfo(input);
+ }
+ testEnd(err);
+ QRinput_free(input);
+}
+
+static void test_splitAnNAn(void)
+{
+ QRinput *input1, *input2, *input3;
+ int s1, s2, s3;
+ char *strall = "326A80A9C5004C0875571F8B71C311F2F86";
+ char *str1 = "326A80A9C5004C";
+ char *str2 = "0875571";
+ char *str3 = "F8B71C311F2F86";
+
+ testStart("Split test: An-N-An switching cost test");
+ input1 = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(strall, input1, QR_MODE_8, 0);
+
+ input2 = QRinput_new();
+ QRinput_append(input2, QR_MODE_AN, 35, (unsigned char *)strall);
+
+ input3 = QRinput_new();
+ QRinput_append(input3, QR_MODE_AN, 14, (unsigned char *)str1);
+ QRinput_append(input3, QR_MODE_NUM, 7, (unsigned char *)str2);
+ QRinput_append(input3, QR_MODE_AN, 14, (unsigned char *)str3);
+
+ s1 = inputSize(input1);
+ s2 = inputSize(input2);
+ s3 = inputSize(input3);
+
+ assert_equal(s1, s2, "Incorrect split");
+ assert_exp(s2 < s3, "Incorrect estimation");
+ testFinish();
+ QRinput_free(input1);
+ QRinput_free(input2);
+ QRinput_free(input3);
+}
+
+static void test_splitAn8An(void)
+{
+ QRinput *input1, *input2, *input3;
+ int s1, s2, s3;
+ char *strall = "ABCDabcdefABCD";
+ char *str1 = "ABCD";
+ char *str2 = "abcdef";
+ char *str3 = "ABCD";
+
+ testStart("Split test: An-8-An switching cost test");
+ input1 = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(strall, input1, QR_MODE_8, 1);
+
+ input2 = QRinput_new();
+ QRinput_append(input2, QR_MODE_8, 14, (unsigned char *)strall);
+
+ input3 = QRinput_new();
+ QRinput_append(input3, QR_MODE_AN, 4, (unsigned char *)str1);
+ QRinput_append(input3, QR_MODE_8, 6, (unsigned char *)str2);
+ QRinput_append(input3, QR_MODE_AN, 4, (unsigned char *)str3);
+
+ s1 = inputSize(input1);
+ s2 = inputSize(input2);
+ s3 = inputSize(input3);
+
+ assert_equal(s1, s2, "Incorrect split");
+ assert_exp(s2 < s3, "Incorrect estimation");
+ testFinish();
+ QRinput_free(input1);
+ QRinput_free(input2);
+ QRinput_free(input3);
+}
+
+static void test_split8An8(void)
+{
+ QRinput *input1, *input2, *input3;
+ int s1, s2, s3;
+ char *strall = "abcABCDEFGHabc";
+ char *str1 = "abc";
+ char *str2 = "ABCDEFGH";
+ char *str3 = "abc";
+
+ testStart("Split test: 8-An-8 switching cost test");
+ input1 = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(strall, input1, QR_MODE_8, 1);
+
+ input2 = QRinput_new();
+ QRinput_append(input2, QR_MODE_8, 14, (unsigned char *)strall);
+
+ input3 = QRinput_new();
+ QRinput_append(input3, QR_MODE_8, 3, (unsigned char *)str1);
+ QRinput_append(input3, QR_MODE_AN, 8, (unsigned char *)str2);
+ QRinput_append(input3, QR_MODE_8, 3, (unsigned char *)str3);
+
+ s1 = inputSize(input1);
+ s2 = inputSize(input2);
+ s3 = inputSize(input3);
+
+ assert_equal(s1, s2, "Incorrect split");
+ assert_exp(s2 < s3, "Incorrect estimation");
+ testFinish();
+ QRinput_free(input1);
+ QRinput_free(input2);
+ QRinput_free(input3);
+}
+
+static void test_split8N8(void)
+{
+ QRinput *input1, *input2, *input3;
+ int s1, s2, s3;
+ char *strall = "abc1234abc";
+ char *str1 = "abc";
+ char *str2 = "1234";
+ char *str3 = "abc";
+
+ testStart("Split test: 8-N-8 switching cost test");
+ input1 = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(strall, input1, QR_MODE_8, 1);
+
+ input2 = QRinput_new();
+ QRinput_append(input2, QR_MODE_8, 10, (unsigned char *)strall);
+
+ input3 = QRinput_new();
+ QRinput_append(input3, QR_MODE_8, 3, (unsigned char *)str1);
+ QRinput_append(input3, QR_MODE_NUM, 4, (unsigned char *)str2);
+ QRinput_append(input3, QR_MODE_8, 3, (unsigned char *)str3);
+
+ s1 = inputSize(input1);
+ s2 = inputSize(input2);
+ s3 = inputSize(input3);
+
+ assert_equal(s1, s2, "Incorrect split");
+ assert_exp(s2 < s3, "Incorrect estimation");
+ testFinish();
+ QRinput_free(input1);
+ QRinput_free(input2);
+ QRinput_free(input3);
+}
+
+int main()
+{
+ int tests = 24;
+ testInit(tests);
+ test_split1();
+ test_split2();
+ test_split3();
+ test_split4();
+ test_split5();
+ test_split6();
+ test_split7();
+ test_split8();
+ test_split3c();
+ test_toupper();
+ test_splitNum8();
+ test_splitAnNAn();
+ test_splitAn8An();
+ test_split8An8();
+ test_split8N8();
+ testReport(tests);
+
+ return 0;
+}
diff --git a/genqrcode/tests/test_split_urls.c b/genqrcode/tests/test_split_urls.c
new file mode 100644
index 0000000000..f1967ec0bd
--- /dev/null
+++ b/genqrcode/tests/test_split_urls.c
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include "common.h"
+#include "../qrinput.h"
+#include "../qrencode_inner.h"
+#include "../split.h"
+#include "decoder.h"
+
+#include "URI_testset.inc"
+
+#if 0
+static void encodeURLandPrint(char *url) {
+ QRinput *input;
+ BitStream *bstream;
+
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(url, input, QR_MODE_8, 1);
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+
+ printf("{%zu,\"%s\"},\n", BitStream_size(bstream), url);
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+}
+
+static void print_currentBitLength() {
+ struct TestSet *ts = testset;
+
+ puts("struct TestSet {\n\tint expected_length;\n\tchar *url;\n};");
+ puts("\nstruct TestSet testset[] = {");
+
+ while(ts->url != NULL) {
+ encodeURLandPrint(ts->url);
+ ts++;
+ }
+
+ puts("{0,NULL}\n};");
+}
+#endif
+
+static int encodeURLandCompare(char *url, size_t expected_length) {
+ QRinput *input;
+ BitStream *bstream;
+ int ret = 0;
+
+ input = QRinput_new2(0, QR_ECLEVEL_L);
+ Split_splitStringToQRinput(url, input, QR_MODE_8, 1);
+ bstream = BitStream_new();
+ QRinput_mergeBitStream(input, bstream);
+
+ size_t length = BitStream_size(bstream);
+ if(length > expected_length) {
+ printf("The length of the encode stream is longer than expected: %zu over %zu\n", length, expected_length);
+ printQRinput(input);
+
+ ret = 1;
+ } else if(length < expected_length) {
+ printf("The length of the encode stream is shorter than expected: %zu under %zu\n", length, expected_length);
+ printQRinput(input);
+
+ ret = 1;
+ }
+
+ QRinput_free(input);
+ BitStream_free(bstream);
+
+ return ret;
+}
+
+static void test_bitstream_length() {
+ struct TestSet *ts = testset;
+ int err = 0;
+
+ testStart("Split_URL test: compare bitstream length");
+ while(ts->url != NULL) {
+ err += encodeURLandCompare(ts->url, ts->expected_length);
+ ts++;
+ }
+ testEnd(err);
+}
+
+int main()
+{
+ int tests = 1;
+ testInit(tests);
+ test_bitstream_length();
+ testReport(tests);
+
+ return 0;
+}
diff --git a/genqrcode/tests/view_qrcode.c b/genqrcode/tests/view_qrcode.c
new file mode 100644
index 0000000000..f9d1bea96b
--- /dev/null
+++ b/genqrcode/tests/view_qrcode.c
@@ -0,0 +1,641 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <SDL.h>
+#include <getopt.h>
+#include <errno.h>
+#include "../config.h"
+#include "../qrspec.h"
+#include "../qrinput.h"
+#include "../split.h"
+#include "../qrencode_inner.h"
+
+static SDL_Window *window;
+static SDL_Renderer *renderer;
+static SDL_Texture *texture = NULL;
+static SDL_Surface *surface = NULL;
+static int casesensitive = 1;
+static int eightbit = 0;
+static int version = 0;
+static int size = 4;
+static int margin = -1;
+static int structured = 0;
+static int micro = 0;
+static int colorize = 0;
+static QRecLevel level = QR_ECLEVEL_L;
+static QRencodeMode hint = QR_MODE_8;
+
+static char **textv;
+static int textc;
+
+static const struct option options[] = {
+ {"help" , no_argument , NULL, 'h'},
+ {"level" , required_argument, NULL, 'l'},
+ {"size" , required_argument, NULL, 's'},
+ {"symversion" , required_argument, NULL, 'v'},
+ {"margin" , required_argument, NULL, 'm'},
+ {"structured" , no_argument , NULL, 'S'},
+ {"kanji" , no_argument , NULL, 'k'},
+ {"casesensitive", no_argument , NULL, 'c'},
+ {"ignorecase" , no_argument , NULL, 'i'},
+ {"8bit" , no_argument , NULL, '8'},
+ {"micro" , no_argument , NULL, 'M'},
+ {"version" , no_argument , NULL, 'V'},
+ {NULL, 0, NULL, 0}
+};
+
+static char *optstring = "hl:s:v:m:Skci8MV";
+
+static char levelChar[4] = {'L', 'M', 'Q', 'H'};
+static void usage(int help, int longopt)
+{
+ fprintf(stderr,
+"view_qrcode version %s\n"
+"Copyright (C) 2008, 2009, 2010 Kentaro Fukuchi\n", VERSION);
+ if(help) {
+ if(longopt) {
+ fprintf(stderr,
+"Usage: view_qrcode [OPTION]... [STRING]\n"
+"Encode input data in a QR Code and display.\n\n"
+" -h, --help display the help message. -h displays only the help of short\n"
+" options.\n\n"
+" -s NUMBER, --size=NUMBER\n"
+" specify module size in dots (pixels). (default=3)\n\n"
+" -l {LMQH}, --level={LMQH}\n"
+" specify error correction level from L (lowest) to H (highest).\n"
+" (default=L)\n\n"
+" -v NUMBER, --symversion=NUMBER\n"
+" specify the version of the symbol. See SYMBOL VERSIONS for more\n"
+" information. (default=auto)\n\n"
+" -m NUMBER, --margin=NUMBER\n"
+" specify the width of the margins. (default=4 (2 for Micro QR)))\n\n"
+" -S, --structured\n"
+" make structured symbols. Version must be specified.\n\n"
+" -k, --kanji assume that the input text contains kanji (shift-jis).\n\n"
+" -c, --casesensitive\n"
+" encode lower-case alphabet characters in 8-bit mode. (default)\n\n"
+" -i, --ignorecase\n"
+" ignore case distinctions and use only upper-case characters.\n\n"
+" -8, --8bit encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n\n"
+" -M, --micro encode in a Micro QR Code. (experimental)\n\n"
+" -V, --version\n"
+" display the version number and copyrights of the qrencode.\n\n"
+" [STRING] input data. If it is not specified, data will be taken from\n"
+" standard input.\n\n"
+"*SYMBOL VERSIONS\n"
+" The symbol versions of QR Code range from Version 1 to Version\n"
+" 40. Each version has a different module configuration or number\n"
+" of modules, ranging from Version 1 (21 x 21 modules) up to\n"
+" Version 40 (177 x 177 modules). Each higher version number\n"
+" comprises 4 additional modules per side by default. See\n"
+" http://www.qrcode.com/en/about/version.html for a detailed\n"
+" version list.\n"
+ );
+ } else {
+ fprintf(stderr,
+"Usage: view_qrcode [OPTION]... [STRING]\n"
+"Encode input data in a QR Code and display.\n\n"
+" -h display this message.\n"
+" --help display the usage of long options.\n"
+" -s NUMBER specify module size in dots (pixels). (default=3)\n"
+" -l {LMQH} specify error correction level from L (lowest) to H (highest).\n"
+" (default=L)\n"
+" -v NUMBER specify the version of the symbol. (default=auto)\n"
+" -m NUMBER specify the width of the margins. (default=4 (2 for Micro))\n"
+" -S make structured symbols. Version must be specified.\n"
+" -k assume that the input text contains kanji (shift-jis).\n"
+" -c encode lower-case alphabet characters in 8-bit mode. (default)\n"
+" -i ignore case distinctions and use only upper-case characters.\n"
+" -8 encode entire data in 8-bit mode. -k, -c and -i will be ignored.\n"
+" -M encode in a Micro QR Code.\n"
+" -V display the version number and copyrights of the qrencode.\n"
+" [STRING] input data. If it is not specified, data will be taken from\n"
+" standard input.\n"
+ );
+ }
+ }
+}
+
+#define MAX_DATA_SIZE (7090 * 16) /* from the specification */
+static unsigned char *readStdin(int *length)
+{
+ unsigned char *buffer;
+ int ret;
+
+ buffer = (unsigned char *)malloc(MAX_DATA_SIZE + 1);
+ if(buffer == NULL) {
+ fprintf(stderr, "Memory allocation failed.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ ret = fread(buffer, 1, MAX_DATA_SIZE, stdin);
+ if(ret == 0) {
+ fprintf(stderr, "No input data.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(feof(stdin) == 0) {
+ fprintf(stderr, "Input data is too large.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ buffer[ret] = '\0';
+ *length = ret;
+
+ return buffer;
+}
+
+static void draw_QRcode(QRcode *qrcode, int ox, int oy)
+{
+ int x, y, width;
+ unsigned char *p;
+ SDL_Rect rect;
+ Uint32 color[8];
+ int col;
+
+ color[0] = SDL_MapRGBA(surface->format, 255, 255, 255, 255);
+ color[1] = SDL_MapRGBA(surface->format, 0, 0, 0, 255);
+ color[2] = SDL_MapRGBA(surface->format, 192, 192, 255, 255);
+ color[3] = SDL_MapRGBA(surface->format, 0, 0, 64, 255);
+ color[4] = SDL_MapRGBA(surface->format, 255, 255, 192, 255);
+ color[5] = SDL_MapRGBA(surface->format, 64, 64, 0, 255);
+ color[6] = SDL_MapRGBA(surface->format, 255, 192, 192, 255);
+ color[7] = SDL_MapRGBA(surface->format, 64, 0, 0, 255);
+
+ ox += margin * size;
+ oy += margin * size;
+ width = qrcode->width;
+ p = qrcode->data;
+ for(y=0; y<width; y++) {
+ for(x=0; x<width; x++) {
+ rect.x = ox + x * size;
+ rect.y = oy + y * size;
+ rect.w = size;
+ rect.h = size;
+ if(!colorize) {
+ col = 0;
+ } else {
+ if(*p & 0x80) {
+ col = 6;
+ } else if(*p & 0x02) {
+ col = 4;
+ } else {
+ col = 2;
+ }
+ }
+ col += (*p & 1);
+ SDL_FillRect(surface, &rect, color[col]);
+ p++;
+ }
+ }
+}
+
+static void draw_singleQRcode(QRinput *stream, int mask)
+{
+ QRcode *qrcode;
+ int width;
+
+ QRinput_setVersionAndErrorCorrectionLevel(stream, version, level);
+ if(micro) {
+ qrcode = QRcode_encodeMaskMQR(stream, mask);
+ } else {
+ qrcode = QRcode_encodeMask(stream, mask);
+ }
+ if(qrcode == NULL) {
+ width = (11 + margin * 2) * size;
+ fprintf(stderr, "Input data does not fit to this setting.\n");
+ } else {
+ version = qrcode->version;
+ width = (qrcode->width + margin * 2) * size;
+ }
+
+ SDL_SetWindowSize(window, width, width);
+ if(surface != NULL) {
+ SDL_FreeSurface(surface);
+ }
+ surface = SDL_CreateRGBSurface(0, width, width, 32, 0, 0, 0, 0);
+ SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 255, 255, 255, 255));
+ if(qrcode) {
+ draw_QRcode(qrcode, 0, 0);
+ }
+ if(texture != NULL) {
+ SDL_DestroyTexture(texture);
+ }
+ texture = SDL_CreateTextureFromSurface(renderer, surface);
+ QRcode_free(qrcode);
+}
+
+static void draw_structuredQRcode(QRinput_Struct *s)
+{
+ int i, w, h, n, x, y;
+ int swidth;
+ QRcode_List *qrcodes, *p;
+
+ qrcodes = QRcode_encodeInputStructured(s);
+ if(qrcodes == NULL) return;
+
+ swidth = (qrcodes->code->width + margin * 2) * size;
+ n = QRcode_List_size(qrcodes);
+ w = (n < 4)?n:4;
+ h = (n - 1) / 4 + 1;
+
+ SDL_SetWindowSize(window, swidth * w, swidth * h);
+ if(surface != NULL) {
+ SDL_FreeSurface(surface);
+ }
+ surface = SDL_CreateRGBSurface(0, swidth * w, swidth * h, 32, 0, 0, 0, 0);
+ SDL_FillRect(surface, NULL, SDL_MapRGBA(surface->format, 255, 255, 255, 255));
+
+ p = qrcodes;
+ for(i=0; i<n; i++) {
+ x = (i % 4) * swidth;
+ y = (i / 4) * swidth;
+ draw_QRcode(p->code, x, y);
+ p = p->next;
+ }
+ if(texture != NULL) {
+ SDL_DestroyTexture(texture);
+ }
+ texture = SDL_CreateTextureFromSurface(renderer, surface);
+ QRcode_List_free(qrcodes);
+}
+
+static void draw_structuredQRcodeFromText(int argc, char **argv)
+{
+ QRinput_Struct *s;
+ QRinput *input;
+ int i, ret;
+
+ s = QRinput_Struct_new();
+ if(s == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+ for(i=0; i<argc; i++) {
+ input = QRinput_new2(version, level);
+ if(input == NULL) {
+ fprintf(stderr, "Failed to allocate memory.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(eightbit) {
+ ret = QRinput_append(input, QR_MODE_8, strlen(argv[i]), (unsigned char *)argv[i]);
+ } else {
+ ret = Split_splitStringToQRinput(argv[i], input, hint, casesensitive);
+ }
+ if(ret < 0) {
+ perror("Encoding the input string");
+ exit(EXIT_FAILURE);
+ }
+ ret = QRinput_Struct_appendInput(s, input);
+ if(ret < 0) {
+ perror("Encoding the input string");
+ exit(EXIT_FAILURE);
+ }
+ }
+ ret = QRinput_Struct_insertStructuredAppendHeaders(s);
+ if(ret < 0) {
+ fprintf(stderr, "Too many inputs.\n");
+ }
+
+ draw_structuredQRcode(s);
+ QRinput_Struct_free(s);
+}
+
+static void draw_structuredQRcodeFromQRinput(QRinput *stream)
+{
+ QRinput_Struct *s;
+
+ QRinput_setVersion(stream, version);
+ QRinput_setErrorCorrectionLevel(stream, level);
+ s = QRinput_splitQRinputToStruct(stream);
+ if(s != NULL) {
+ draw_structuredQRcode(s);
+ QRinput_Struct_free(s);
+ } else {
+ fprintf(stderr, "Input data is too large for this setting.\n");
+ }
+}
+
+static void view(int mode, QRinput *input)
+{
+ int flag = 1;
+ int mask = -1;
+ SDL_Event event;
+ int loop;
+ int codeChanged = 1;
+
+ while(flag) {
+ if(codeChanged) {
+ if(mode) {
+ draw_structuredQRcodeFromText(textc, textv);
+ } else {
+ if(structured) {
+ draw_structuredQRcodeFromQRinput(input);
+ } else {
+ draw_singleQRcode(input, mask);
+ }
+ }
+ if(mode || structured) {
+ printf("Version %d, Level %c.\n", version, levelChar[level]);
+ } else {
+ printf("Version %d, Level %c, Mask %d.\n", version, levelChar[level], mask);
+ }
+ }
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
+ loop = 1;
+ codeChanged = 0;
+ while(loop) {
+ SDL_WaitEvent(&event);
+ if(event.type == SDL_KEYDOWN) {
+ codeChanged = 1;
+ switch(event.key.keysym.sym) {
+ case SDLK_RIGHT:
+ version++;
+ if(version > QRSPEC_VERSION_MAX)
+ version = QRSPEC_VERSION_MAX;
+ loop = 0;
+ break;
+ case SDLK_LEFT:
+ version--;
+ if(version < 1)
+ version = 1;
+ loop = 0;
+ break;
+ case SDLK_UP:
+ size++;
+ loop = 0;
+ break;
+ case SDLK_DOWN:
+ size--;
+ if(size < 1) size = 1;
+ loop = 0;
+ break;
+ case SDLK_0:
+ case SDLK_1:
+ case SDLK_2:
+ case SDLK_3:
+ case SDLK_4:
+ case SDLK_5:
+ case SDLK_6:
+ case SDLK_7:
+ if(!mode && !structured) {
+ mask = (event.key.keysym.sym - SDLK_0);
+ loop = 0;
+ }
+ break;
+ case SDLK_8:
+ if(!mode && !structured) {
+ mask = -1;
+ loop = 0;
+ }
+ break;
+ case SDLK_9:
+ if(!mode && !structured) {
+ mask = -2;
+ loop = 0;
+ }
+ break;
+ case SDLK_l:
+ level = QR_ECLEVEL_L;
+ loop = 0;
+ break;
+ case SDLK_m:
+ level = QR_ECLEVEL_M;
+ loop = 0;
+ break;
+ case SDLK_h:
+ level = QR_ECLEVEL_H;
+ loop = 0;
+ break;
+ case SDLK_q:
+ level = QR_ECLEVEL_Q;
+ loop = 0;
+ break;
+ case SDLK_c:
+ colorize ^= 1;
+ loop = 0;
+ break;
+ case SDLK_ESCAPE:
+ loop = 0;
+ flag = 0;
+ break;
+ default:
+ break;
+ }
+ if(event.type == SDL_QUIT) {
+ loop = 0;
+ flag = 0;
+ }
+ }
+ if (event.type == SDL_WINDOWEVENT) {
+ switch (event.window.event) {
+ case SDL_WINDOWEVENT_SHOWN:
+ case SDL_WINDOWEVENT_EXPOSED:
+ case SDL_WINDOWEVENT_SIZE_CHANGED:
+ case SDL_WINDOWEVENT_RESIZED:
+ loop = 0;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+}
+
+static void view_simple(const unsigned char *str, int length)
+{
+ QRinput *input;
+ int ret;
+
+ if(micro) {
+ input = QRinput_newMQR(version, level);
+ } else {
+ input = QRinput_new2(version, level);
+ }
+ if(input == NULL) {
+ fprintf(stderr, "Memory allocation error.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(eightbit) {
+ ret = QRinput_append(input, QR_MODE_8, length, str);
+ } else {
+ ret = Split_splitStringToQRinput((char *)str, input, hint, casesensitive);
+ }
+ if(ret < 0) {
+ perror("Encoding the input string");
+ exit(EXIT_FAILURE);
+ }
+
+ view(0, input);
+
+ QRinput_free(input);
+}
+
+static void view_multiText(char **argv, int argc)
+{
+ textc = argc;
+ textv = argv;
+
+ view(1, NULL);
+}
+
+int main(int argc, char **argv)
+{
+ int opt, lindex = -1;
+ unsigned char *intext = NULL;
+ int length = 0;
+ int ret;
+
+ while((opt = getopt_long(argc, argv, optstring, options, &lindex)) != -1) {
+ switch(opt) {
+ case 'h':
+ if(lindex == 0) {
+ usage(1, 1);
+ } else {
+ usage(1, 0);
+ }
+ exit(EXIT_SUCCESS);
+ break;
+ case 's':
+ size = atoi(optarg);
+ if(size <= 0) {
+ fprintf(stderr, "Invalid size: %d\n", size);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'v':
+ version = atoi(optarg);
+ if(version < 0) {
+ fprintf(stderr, "Invalid version: %d\n", version);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'l':
+ switch(*optarg) {
+ case 'l':
+ case 'L':
+ level = QR_ECLEVEL_L;
+ break;
+ case 'm':
+ case 'M':
+ level = QR_ECLEVEL_M;
+ break;
+ case 'q':
+ case 'Q':
+ level = QR_ECLEVEL_Q;
+ break;
+ case 'h':
+ case 'H':
+ level = QR_ECLEVEL_H;
+ break;
+ default:
+ fprintf(stderr, "Invalid level: %s\n", optarg);
+ exit(EXIT_FAILURE);
+ break;
+ }
+ break;
+ case 'm':
+ margin = atoi(optarg);
+ if(margin < 0) {
+ fprintf(stderr, "Invalid margin: %d\n", margin);
+ exit(EXIT_FAILURE);
+ }
+ break;
+ case 'S':
+ structured = 1;
+ case 'k':
+ hint = QR_MODE_KANJI;
+ break;
+ case 'c':
+ casesensitive = 1;
+ break;
+ case 'i':
+ casesensitive = 0;
+ break;
+ case '8':
+ eightbit = 1;
+ break;
+ case 'M':
+ micro = 1;
+ break;
+ case 'V':
+ usage(0, 0);
+ exit(EXIT_SUCCESS);
+ break;
+ default:
+ fprintf(stderr, "Try `view_qrcode --help' for more information.\n");
+ exit(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if(argc == 1) {
+ usage(1, 0);
+ exit(EXIT_SUCCESS);
+ }
+
+ if(optind < argc) {
+ intext = (unsigned char *)argv[optind];
+ length = strlen((char *)intext);
+ }
+ if(intext == NULL) {
+ intext = readStdin(&length);
+ }
+
+ if(micro && version > MQRSPEC_VERSION_MAX) {
+ fprintf(stderr, "Version should be less or equal to %d.\n", MQRSPEC_VERSION_MAX);
+ exit(EXIT_FAILURE);
+ } else if(!micro && version > QRSPEC_VERSION_MAX) {
+ fprintf(stderr, "Version should be less or equal to %d.\n", QRSPEC_VERSION_MAX);
+ exit(EXIT_FAILURE);
+ }
+
+ if(margin < 0) {
+ if(micro) {
+ margin = 2;
+ } else {
+ margin = 4;
+ }
+ }
+
+ if(micro) {
+ if(version == 0) {
+ fprintf(stderr, "Version must be specified to encode a Micro QR Code symbol.\n");
+ exit(EXIT_FAILURE);
+ }
+ if(structured) {
+ fprintf(stderr, "Micro QR Code does not support structured symbols.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if(structured && version == 0) {
+ fprintf(stderr, "Version must be specified to encode structured symbols.\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if(SDL_Init(SDL_INIT_VIDEO) < 0) {
+ fprintf(stderr, "Failed initializing SDL: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ ret = SDL_CreateWindowAndRenderer(100, 100, SDL_WINDOW_SHOWN, &window, &renderer);
+ if(ret < 0) {
+ fprintf(stderr, "Failed to create a window: %s\n", SDL_GetError());
+ return -1;
+ }
+
+ SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
+
+ if(structured && (argc - optind > 1)) {
+ view_multiText(argv + optind, argc - optind);
+ } else {
+ view_simple(intext, length);
+ }
+
+ SDL_Quit();
+
+ return 0;
+}
diff --git a/genqrcode/use/config.rpath b/genqrcode/use/config.rpath
new file mode 100755
index 0000000000..98183ff2f2
--- /dev/null
+++ b/genqrcode/use/config.rpath
@@ -0,0 +1,684 @@
+#! /bin/sh
+# Output a system dependent set of variables, describing how to set the
+# run time search path of shared libraries in an executable.
+#
+# Copyright 1996-2016 Free Software Foundation, Inc.
+# Taken from GNU libtool, 2001
+# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
+#
+# This file is free software; the Free Software Foundation gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# The first argument passed to this file is the canonical host specification,
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# The environment variables CC, GCC, LDFLAGS, LD, with_gnu_ld
+# should be set by the caller.
+#
+# The set of defined variables is at the end of this script.
+
+# Known limitations:
+# - On IRIX 6.5 with CC="cc", the run time search patch must not be longer
+# than 256 bytes, otherwise the compiler driver will dump core. The only
+# known workaround is to choose shorter directory names for the build
+# directory and/or the installation directory.
+
+# All known linkers require a '.a' archive for static linking (except MSVC,
+# which needs '.lib').
+libext=a
+shrext=.so
+
+host="$1"
+host_cpu=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
+host_vendor=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
+host_os=`echo "$host" | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
+
+# Code taken from libtool.m4's _LT_CC_BASENAME.
+
+for cc_temp in $CC""; do
+ case $cc_temp in
+ compile | *[\\/]compile | ccache | *[\\/]ccache ) ;;
+ distcc | *[\\/]distcc | purify | *[\\/]purify ) ;;
+ \-*) ;;
+ *) break;;
+ esac
+done
+cc_basename=`echo "$cc_temp" | sed -e 's%^.*/%%'`
+
+# Code taken from libtool.m4's _LT_COMPILER_PIC.
+
+wl=
+if test "$GCC" = yes; then
+ wl='-Wl,'
+else
+ case "$host_os" in
+ aix*)
+ wl='-Wl,'
+ ;;
+ mingw* | cygwin* | pw32* | os2* | cegcc*)
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ wl='-Wl,'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ wl='-Wl,'
+ ;;
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ case $cc_basename in
+ ecc*)
+ wl='-Wl,'
+ ;;
+ icc* | ifort*)
+ wl='-Wl,'
+ ;;
+ lf95*)
+ wl='-Wl,'
+ ;;
+ nagfor*)
+ wl='-Wl,-Wl,,'
+ ;;
+ pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*)
+ wl='-Wl,'
+ ;;
+ ccc*)
+ wl='-Wl,'
+ ;;
+ xl* | bgxl* | bgf* | mpixl*)
+ wl='-Wl,'
+ ;;
+ como)
+ wl='-lopt='
+ ;;
+ *)
+ case `$CC -V 2>&1 | sed 5q` in
+ *Sun\ F* | *Sun*Fortran*)
+ wl=
+ ;;
+ *Sun\ C*)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ newsos6)
+ ;;
+ *nto* | *qnx*)
+ ;;
+ osf3* | osf4* | osf5*)
+ wl='-Wl,'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ case $cc_basename in
+ f77* | f90* | f95* | sunf77* | sunf90* | sunf95*)
+ wl='-Qoption ld '
+ ;;
+ *)
+ wl='-Wl,'
+ ;;
+ esac
+ ;;
+ sunos4*)
+ wl='-Qoption ld '
+ ;;
+ sysv4 | sysv4.2uw2* | sysv4.3*)
+ wl='-Wl,'
+ ;;
+ sysv4*MP*)
+ ;;
+ sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*)
+ wl='-Wl,'
+ ;;
+ unicos*)
+ wl='-Wl,'
+ ;;
+ uts4*)
+ ;;
+ esac
+fi
+
+# Code taken from libtool.m4's _LT_LINKER_SHLIBS.
+
+hardcode_libdir_flag_spec=
+hardcode_libdir_separator=
+hardcode_direct=no
+hardcode_minus_L=no
+
+case "$host_os" in
+ cygwin* | mingw* | pw32* | cegcc*)
+ # FIXME: the MSVC++ port hasn't been tested in a loooong time
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ if test "$GCC" != yes; then
+ with_gnu_ld=no
+ fi
+ ;;
+ interix*)
+ # we just hope/assume this is gcc and not c89 (= MSVC++)
+ with_gnu_ld=yes
+ ;;
+ openbsd*)
+ with_gnu_ld=no
+ ;;
+esac
+
+ld_shlibs=yes
+if test "$with_gnu_ld" = yes; then
+ # Set some defaults for GNU ld with shared library support. These
+ # are reset later if shared libraries are not supported. Putting them
+ # here allows them to be overridden if necessary.
+ # Unlike libtool, we use -rpath here, not --rpath, since the documented
+ # option of GNU ld is called -rpath, not --rpath.
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ case "$host_os" in
+ aix[3-9]*)
+ # On AIX/PPC, the GNU linker is very broken
+ if test "$host_cpu" != ia64; then
+ ld_shlibs=no
+ fi
+ ;;
+ amigaos*)
+ case "$host_cpu" in
+ powerpc)
+ ;;
+ m68k)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+ beos*)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ cygwin* | mingw* | pw32* | cegcc*)
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec='-L$libdir'
+ if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ haiku*)
+ ;;
+ interix[3-9]*)
+ hardcode_direct=no
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ netbsd*)
+ ;;
+ solaris*)
+ if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then
+ ld_shlibs=no
+ elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*)
+ case `$LD -v 2>&1` in
+ *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*)
+ ld_shlibs=no
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-rpath,$libdir`'
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ ;;
+ sunos4*)
+ hardcode_direct=yes
+ ;;
+ *)
+ if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ esac
+ if test "$ld_shlibs" = no; then
+ hardcode_libdir_flag_spec=
+ fi
+else
+ case "$host_os" in
+ aix3*)
+ # Note: this linker hardcodes the directories in LIBPATH if there
+ # are no directories specified by -L.
+ hardcode_minus_L=yes
+ if test "$GCC" = yes; then
+ # Neither direct hardcoding nor static linking is supported with a
+ # broken collect2.
+ hardcode_direct=unsupported
+ fi
+ ;;
+ aix[4-9]*)
+ if test "$host_cpu" = ia64; then
+ # On IA64, the linker does run time linking by default, so we don't
+ # have to do anything special.
+ aix_use_runtimelinking=no
+ else
+ aix_use_runtimelinking=no
+ # Test if we are trying to use run time linking or normal
+ # AIX style linking. If -brtl is somewhere in LDFLAGS, we
+ # need to do runtime linking.
+ case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*)
+ for ld_flag in $LDFLAGS; do
+ if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then
+ aix_use_runtimelinking=yes
+ break
+ fi
+ done
+ ;;
+ esac
+ fi
+ hardcode_direct=yes
+ hardcode_libdir_separator=':'
+ if test "$GCC" = yes; then
+ case $host_os in aix4.[012]|aix4.[012].*)
+ collect2name=`${CC} -print-prog-name=collect2`
+ if test -f "$collect2name" && \
+ strings "$collect2name" | grep resolve_lib_name >/dev/null
+ then
+ # We have reworked collect2
+ :
+ else
+ # We have old collect2
+ hardcode_direct=unsupported
+ hardcode_minus_L=yes
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_libdir_separator=
+ fi
+ ;;
+ esac
+ fi
+ # Begin _LT_AC_SYS_LIBPATH_AIX.
+ echo 'int main () { return 0; }' > conftest.c
+ ${CC} ${LDFLAGS} conftest.c -o conftest
+ aix_libpath=`dump -H conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ if test -z "$aix_libpath"; then
+ aix_libpath=`dump -HX64 conftest 2>/dev/null | sed -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; }
+}'`
+ fi
+ if test -z "$aix_libpath"; then
+ aix_libpath="/usr/lib:/lib"
+ fi
+ rm -f conftest.c conftest
+ # End _LT_AC_SYS_LIBPATH_AIX.
+ if test "$aix_use_runtimelinking" = yes; then
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ else
+ if test "$host_cpu" = ia64; then
+ hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib'
+ else
+ hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath"
+ fi
+ fi
+ ;;
+ amigaos*)
+ case "$host_cpu" in
+ powerpc)
+ ;;
+ m68k)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ esac
+ ;;
+ bsdi[45]*)
+ ;;
+ cygwin* | mingw* | pw32* | cegcc*)
+ # When not using gcc, we currently assume that we are using
+ # Microsoft Visual C++.
+ # hardcode_libdir_flag_spec is actually meaningless, as there is
+ # no search path for DLLs.
+ hardcode_libdir_flag_spec=' '
+ libext=lib
+ ;;
+ darwin* | rhapsody*)
+ hardcode_direct=no
+ if { case $cc_basename in ifort*) true;; *) test "$GCC" = yes;; esac; }; then
+ :
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ dgux*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ freebsd2.[01]*)
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ freebsd* | dragonfly*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ hpux9*)
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ hpux10*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ fi
+ ;;
+ hpux11*)
+ if test "$with_gnu_ld" = no; then
+ hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir'
+ hardcode_libdir_separator=:
+ case $host_cpu in
+ hppa*64*|ia64*)
+ hardcode_direct=no
+ ;;
+ *)
+ hardcode_direct=yes
+ # hardcode_minus_L: Not really in the search PATH,
+ # but as the default location of the library.
+ hardcode_minus_L=yes
+ ;;
+ esac
+ fi
+ ;;
+ irix5* | irix6* | nonstopux*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ netbsd*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ hardcode_direct=yes
+ ;;
+ newsos6)
+ hardcode_direct=yes
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ *nto* | *qnx*)
+ ;;
+ openbsd*)
+ if test -f /usr/libexec/ld.so; then
+ hardcode_direct=yes
+ if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ else
+ case "$host_os" in
+ openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ *)
+ hardcode_libdir_flag_spec='${wl}-rpath,$libdir'
+ ;;
+ esac
+ fi
+ else
+ ld_shlibs=no
+ fi
+ ;;
+ os2*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_minus_L=yes
+ ;;
+ osf3*)
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ hardcode_libdir_separator=:
+ ;;
+ osf4* | osf5*)
+ if test "$GCC" = yes; then
+ hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir'
+ else
+ # Both cc and cxx compiler support -rpath directly
+ hardcode_libdir_flag_spec='-rpath $libdir'
+ fi
+ hardcode_libdir_separator=:
+ ;;
+ solaris*)
+ hardcode_libdir_flag_spec='-R$libdir'
+ ;;
+ sunos4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ hardcode_direct=yes
+ hardcode_minus_L=yes
+ ;;
+ sysv4)
+ case $host_vendor in
+ sni)
+ hardcode_direct=yes # is this really true???
+ ;;
+ siemens)
+ hardcode_direct=no
+ ;;
+ motorola)
+ hardcode_direct=no #Motorola manual says yes, but my tests say they lie
+ ;;
+ esac
+ ;;
+ sysv4.3*)
+ ;;
+ sysv4*MP*)
+ if test -d /usr/nec; then
+ ld_shlibs=yes
+ fi
+ ;;
+ sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*)
+ ;;
+ sysv5* | sco3.2v5* | sco5v6*)
+ hardcode_libdir_flag_spec='`test -z "$SCOABSPATH" && echo ${wl}-R,$libdir`'
+ hardcode_libdir_separator=':'
+ ;;
+ uts4*)
+ hardcode_libdir_flag_spec='-L$libdir'
+ ;;
+ *)
+ ld_shlibs=no
+ ;;
+ esac
+fi
+
+# Check dynamic linker characteristics
+# Code taken from libtool.m4's _LT_SYS_DYNAMIC_LINKER.
+# Unlike libtool.m4, here we don't care about _all_ names of the library, but
+# only about the one the linker finds when passed -lNAME. This is the last
+# element of library_names_spec in libtool.m4, or possibly two of them if the
+# linker has special search rules.
+library_names_spec= # the last element of library_names_spec in libtool.m4
+libname_spec='lib$name'
+case "$host_os" in
+ aix3*)
+ library_names_spec='$libname.a'
+ ;;
+ aix[4-9]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ amigaos*)
+ case "$host_cpu" in
+ powerpc*)
+ library_names_spec='$libname$shrext' ;;
+ m68k)
+ library_names_spec='$libname.a' ;;
+ esac
+ ;;
+ beos*)
+ library_names_spec='$libname$shrext'
+ ;;
+ bsdi[45]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ cygwin* | mingw* | pw32* | cegcc*)
+ shrext=.dll
+ library_names_spec='$libname.dll.a $libname.lib'
+ ;;
+ darwin* | rhapsody*)
+ shrext=.dylib
+ library_names_spec='$libname$shrext'
+ ;;
+ dgux*)
+ library_names_spec='$libname$shrext'
+ ;;
+ freebsd[23].*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ freebsd* | dragonfly*)
+ library_names_spec='$libname$shrext'
+ ;;
+ gnu*)
+ library_names_spec='$libname$shrext'
+ ;;
+ haiku*)
+ library_names_spec='$libname$shrext'
+ ;;
+ hpux9* | hpux10* | hpux11*)
+ case $host_cpu in
+ ia64*)
+ shrext=.so
+ ;;
+ hppa*64*)
+ shrext=.sl
+ ;;
+ *)
+ shrext=.sl
+ ;;
+ esac
+ library_names_spec='$libname$shrext'
+ ;;
+ interix[3-9]*)
+ library_names_spec='$libname$shrext'
+ ;;
+ irix5* | irix6* | nonstopux*)
+ library_names_spec='$libname$shrext'
+ case "$host_os" in
+ irix5* | nonstopux*)
+ libsuff= shlibsuff=
+ ;;
+ *)
+ case $LD in
+ *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") libsuff= shlibsuff= ;;
+ *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") libsuff=32 shlibsuff=N32 ;;
+ *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") libsuff=64 shlibsuff=64 ;;
+ *) libsuff= shlibsuff= ;;
+ esac
+ ;;
+ esac
+ ;;
+ linux*oldld* | linux*aout* | linux*coff*)
+ ;;
+ linux* | k*bsd*-gnu | kopensolaris*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ knetbsd*-gnu)
+ library_names_spec='$libname$shrext'
+ ;;
+ netbsd*)
+ library_names_spec='$libname$shrext'
+ ;;
+ newsos6)
+ library_names_spec='$libname$shrext'
+ ;;
+ *nto* | *qnx*)
+ library_names_spec='$libname$shrext'
+ ;;
+ openbsd*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ os2*)
+ libname_spec='$name'
+ shrext=.dll
+ library_names_spec='$libname.a'
+ ;;
+ osf3* | osf4* | osf5*)
+ library_names_spec='$libname$shrext'
+ ;;
+ rdos*)
+ ;;
+ solaris*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sunos4*)
+ library_names_spec='$libname$shrext$versuffix'
+ ;;
+ sysv4 | sysv4.3*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv4*MP*)
+ library_names_spec='$libname$shrext'
+ ;;
+ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*)
+ library_names_spec='$libname$shrext'
+ ;;
+ tpf*)
+ library_names_spec='$libname$shrext'
+ ;;
+ uts4*)
+ library_names_spec='$libname$shrext'
+ ;;
+esac
+
+sed_quote_subst='s/\(["`$\\]\)/\\\1/g'
+escaped_wl=`echo "X$wl" | sed -e 's/^X//' -e "$sed_quote_subst"`
+shlibext=`echo "$shrext" | sed -e 's,^\.,,'`
+escaped_libname_spec=`echo "X$libname_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_library_names_spec=`echo "X$library_names_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+escaped_hardcode_libdir_flag_spec=`echo "X$hardcode_libdir_flag_spec" | sed -e 's/^X//' -e "$sed_quote_subst"`
+
+LC_ALL=C sed -e 's/^\([a-zA-Z0-9_]*\)=/acl_cv_\1=/' <<EOF
+
+# How to pass a linker flag through the compiler.
+wl="$escaped_wl"
+
+# Static library suffix (normally "a").
+libext="$libext"
+
+# Shared library suffix (normally "so").
+shlibext="$shlibext"
+
+# Format of library name prefix.
+libname_spec="$escaped_libname_spec"
+
+# Library names that the linker finds when passed -lNAME.
+library_names_spec="$escaped_library_names_spec"
+
+# Flag to hardcode \$libdir into a binary during linking.
+# This must work even if \$libdir does not exist.
+hardcode_libdir_flag_spec="$escaped_hardcode_libdir_flag_spec"
+
+# Whether we need a single -rpath flag with a separated argument.
+hardcode_libdir_separator="$hardcode_libdir_separator"
+
+# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the
+# resulting binary.
+hardcode_direct="$hardcode_direct"
+
+# Set to yes if using the -LDIR flag during linking hardcodes DIR into the
+# resulting binary.
+hardcode_minus_L="$hardcode_minus_L"
+
+EOF